package cuchaz.enigma.convert; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import cuchaz.enigma.mapping.ClassEntry; public class ClassMatches implements Iterable { Collection m_matches; Map m_matchesBySource; Map m_matchesByDest; BiMap m_uniqueMatches; Map m_ambiguousMatchesBySource; Map m_ambiguousMatchesByDest; Set m_unmatchedSourceClasses; Set m_unmatchedDestClasses; public ClassMatches() { this(new ArrayList()); } public ClassMatches(Collection matches) { m_matches = matches; m_matchesBySource = Maps.newHashMap(); m_matchesByDest = Maps.newHashMap(); m_uniqueMatches = HashBiMap.create(); m_ambiguousMatchesBySource = Maps.newHashMap(); m_ambiguousMatchesByDest = Maps.newHashMap(); m_unmatchedSourceClasses = Sets.newHashSet(); m_unmatchedDestClasses = Sets.newHashSet(); for (ClassMatch match : matches) { indexMatch(match); } } public void add(ClassMatch match) { m_matches.add(match); indexMatch(match); } public void remove(ClassMatch match) { for (ClassEntry sourceClass : match.sourceClasses) { m_matchesBySource.remove(sourceClass); m_uniqueMatches.remove(sourceClass); m_ambiguousMatchesBySource.remove(sourceClass); m_unmatchedSourceClasses.remove(sourceClass); } for (ClassEntry destClass : match.destClasses) { m_matchesByDest.remove(destClass); m_uniqueMatches.inverse().remove(destClass); m_ambiguousMatchesByDest.remove(destClass); m_unmatchedDestClasses.remove(destClass); } m_matches.remove(match); } public int size() { return m_matches.size(); } @Override public Iterator iterator() { return m_matches.iterator(); } private void indexMatch(ClassMatch match) { if (!match.isMatched()) { // unmatched m_unmatchedSourceClasses.addAll(match.sourceClasses); m_unmatchedDestClasses.addAll(match.destClasses); } else { if (match.isAmbiguous()) { // ambiguously matched for (ClassEntry entry : match.sourceClasses) { m_ambiguousMatchesBySource.put(entry, match); } for (ClassEntry entry : match.destClasses) { m_ambiguousMatchesByDest.put(entry, match); } } else { // uniquely matched m_uniqueMatches.put(match.getUniqueSource(), match.getUniqueDest()); } } for (ClassEntry entry : match.sourceClasses) { m_matchesBySource.put(entry, match); } for (ClassEntry entry : match.destClasses) { m_matchesByDest.put(entry, match); } } public BiMap getUniqueMatches() { return m_uniqueMatches; } public Set getUnmatchedSourceClasses() { return m_unmatchedSourceClasses; } public Set getUnmatchedDestClasses() { return m_unmatchedDestClasses; } public Set getAmbiguouslyMatchedSourceClasses() { return m_ambiguousMatchesBySource.keySet(); } public ClassMatch getAmbiguousMatchBySource(ClassEntry sourceClass) { return m_ambiguousMatchesBySource.get(sourceClass); } public ClassMatch getMatchBySource(ClassEntry sourceClass) { return m_matchesBySource.get(sourceClass); } public ClassMatch getMatchByDest(ClassEntry destClass) { return m_matchesByDest.get(destClass); } public void removeSource(ClassEntry sourceClass) { ClassMatch match = m_matchesBySource.get(sourceClass); if (match != null) { remove(match); match.sourceClasses.remove(sourceClass); if (!match.sourceClasses.isEmpty() || !match.destClasses.isEmpty()) { add(match); } } } public void removeDest(ClassEntry destClass) { ClassMatch match = m_matchesByDest.get(destClass); if (match != null) { remove(match); match.destClasses.remove(destClass); if (!match.sourceClasses.isEmpty() || !match.destClasses.isEmpty()) { add(match); } } } }