From 52ab426d8fad3dbee7e728f523a35af94facebda Mon Sep 17 00:00:00 2001 From: jeff Date: Tue, 3 Feb 2015 22:00:53 -0500 Subject: oops, don't depend on local procyon project --- src/cuchaz/enigma/convert/ClassMatching.java | 173 +++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/cuchaz/enigma/convert/ClassMatching.java (limited to 'src/cuchaz/enigma/convert/ClassMatching.java') diff --git a/src/cuchaz/enigma/convert/ClassMatching.java b/src/cuchaz/enigma/convert/ClassMatching.java new file mode 100644 index 0000000..53b6f7f --- /dev/null +++ b/src/cuchaz/enigma/convert/ClassMatching.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma.convert; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; + +public class ClassMatching { + + private Multimap m_sourceClasses; + private Multimap m_matchedDestClasses; + private List m_unmatchedDestClasses; + + public ClassMatching() { + m_sourceClasses = ArrayListMultimap.create(); + m_matchedDestClasses = ArrayListMultimap.create(); + m_unmatchedDestClasses = Lists.newArrayList(); + } + + public void addSource(ClassIdentity c) { + m_sourceClasses.put(c, c); + } + + public void matchDestClass(ClassIdentity destClass) { + Collection matchedSourceClasses = m_sourceClasses.get(destClass); + if (matchedSourceClasses.isEmpty()) { + // no match + m_unmatchedDestClasses.add(destClass); + } else { + // found a match + m_matchedDestClasses.put(destClass, destClass); + + // DEBUG + ClassIdentity sourceClass = matchedSourceClasses.iterator().next(); + assert (sourceClass.hashCode() == destClass.hashCode()); + assert (sourceClass.equals(destClass)); + } + } + + public void removeSource(ClassIdentity sourceClass) { + m_sourceClasses.remove(sourceClass, sourceClass); + } + + public void removeDest(ClassIdentity destClass) { + m_matchedDestClasses.remove(destClass, destClass); + m_unmatchedDestClasses.remove(destClass); + } + + public List getSourceClasses() { + return new ArrayList(m_sourceClasses.values()); + } + + public List getDestClasses() { + List classes = Lists.newArrayList(); + classes.addAll(m_matchedDestClasses.values()); + classes.addAll(m_unmatchedDestClasses); + return classes; + } + + public BiMap getUniqueMatches() { + BiMap uniqueMatches = HashBiMap.create(); + for (ClassIdentity sourceClass : m_sourceClasses.keySet()) { + Collection matchedSourceClasses = m_sourceClasses.get(sourceClass); + Collection matchedDestClasses = m_matchedDestClasses.get(sourceClass); + if (matchedSourceClasses.size() == 1 && matchedDestClasses.size() == 1) { + ClassIdentity matchedSourceClass = matchedSourceClasses.iterator().next(); + ClassIdentity matchedDestClass = matchedDestClasses.iterator().next(); + uniqueMatches.put(matchedSourceClass, matchedDestClass); + } + } + return uniqueMatches; + } + + public BiMap,List> getAmbiguousMatches() { + BiMap,List> ambiguousMatches = HashBiMap.create(); + for (ClassIdentity sourceClass : m_sourceClasses.keySet()) { + Collection matchedSourceClasses = m_sourceClasses.get(sourceClass); + Collection matchedDestClasses = m_matchedDestClasses.get(sourceClass); + if (matchedSourceClasses.size() > 1 && matchedDestClasses.size() > 1) { + ambiguousMatches.put( + new ArrayList(matchedSourceClasses), + new ArrayList(matchedDestClasses) + ); + } + } + return ambiguousMatches; + } + + public int getNumAmbiguousSourceMatches() { + int num = 0; + for (Map.Entry,List> entry : getAmbiguousMatches().entrySet()) { + num += entry.getKey().size(); + } + return num; + } + + public int getNumAmbiguousDestMatches() { + int num = 0; + for (Map.Entry,List> entry : getAmbiguousMatches().entrySet()) { + num += entry.getValue().size(); + } + return num; + } + + public List getUnmatchedSourceClasses() { + List classes = Lists.newArrayList(); + for (ClassIdentity sourceClass : getSourceClasses()) { + if (m_matchedDestClasses.get(sourceClass).isEmpty()) { + classes.add(sourceClass); + } + } + return classes; + } + + public List getUnmatchedDestClasses() { + return new ArrayList(m_unmatchedDestClasses); + } + + public Map>> getIndex() { + Map>> conversion = Maps.newHashMap(); + for (Map.Entry entry : getUniqueMatches().entrySet()) { + conversion.put( + entry.getKey().getClassEntry().getName(), + new AbstractMap.SimpleEntry>(entry.getKey(), Arrays.asList(entry.getValue())) + ); + } + for (Map.Entry,List> entry : getAmbiguousMatches().entrySet()) { + for (ClassIdentity sourceClass : entry.getKey()) { + conversion.put( + sourceClass.getClassEntry().getName(), + new AbstractMap.SimpleEntry>(sourceClass, entry.getValue()) + ); + } + } + for (ClassIdentity sourceClass : getUnmatchedSourceClasses()) { + conversion.put( + sourceClass.getClassEntry().getName(), + new AbstractMap.SimpleEntry>(sourceClass, getUnmatchedDestClasses()) + ); + } + return conversion; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append(String.format("%12s%8s%8s\n", "", "Source", "Dest")); + buf.append(String.format("%12s%8d%8d\n", "Classes", getSourceClasses().size(), getDestClasses().size())); + buf.append(String.format("%12s%8d%8d\n", "Unique", getUniqueMatches().size(), getUniqueMatches().size())); + buf.append(String.format("%12s%8d%8d\n", "Ambiguous", getNumAmbiguousSourceMatches(), getNumAmbiguousDestMatches())); + buf.append(String.format("%12s%8d%8d\n", "Unmatched", getUnmatchedSourceClasses().size(), getUnmatchedDestClasses().size())); + return buf.toString(); + } +} -- cgit v1.2.3