/******************************************************************************* * Copyright (c) 2015 Jeff Martin. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public * License v3.0 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html *

* Contributors: * Jeff Martin - initial API and implementation ******************************************************************************/ package cuchaz.enigma.convert; 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 java.util.*; import cuchaz.enigma.mapping.ClassEntry; public class ClassMatches implements Iterable { private Collection matches; private Map matchesBySource; private Map matchesByDest; private BiMap uniqueMatches; private Map ambiguousMatchesBySource; private Map ambiguousMatchesByDest; private Set unmatchedSourceClasses; private Set unmatchedDestClasses; public ClassMatches() { this(new ArrayList<>()); } public ClassMatches(Collection matches) { this.matches = matches; matchesBySource = Maps.newHashMap(); matchesByDest = Maps.newHashMap(); uniqueMatches = HashBiMap.create(); ambiguousMatchesBySource = Maps.newHashMap(); ambiguousMatchesByDest = Maps.newHashMap(); unmatchedSourceClasses = Sets.newHashSet(); unmatchedDestClasses = Sets.newHashSet(); for (ClassMatch match : matches) { indexMatch(match); } } public void add(ClassMatch match) { matches.add(match); indexMatch(match); } public void remove(ClassMatch match) { for (ClassEntry sourceClass : match.sourceClasses) { matchesBySource.remove(sourceClass); uniqueMatches.remove(sourceClass); ambiguousMatchesBySource.remove(sourceClass); unmatchedSourceClasses.remove(sourceClass); } for (ClassEntry destClass : match.destClasses) { matchesByDest.remove(destClass); uniqueMatches.inverse().remove(destClass); ambiguousMatchesByDest.remove(destClass); unmatchedDestClasses.remove(destClass); } matches.remove(match); } public int size() { return matches.size(); } @Override public Iterator iterator() { return matches.iterator(); } private void indexMatch(ClassMatch match) { if (!match.isMatched()) { // unmatched unmatchedSourceClasses.addAll(match.sourceClasses); unmatchedDestClasses.addAll(match.destClasses); } else { if (match.isAmbiguous()) { // ambiguously matched for (ClassEntry entry : match.sourceClasses) { ambiguousMatchesBySource.put(entry, match); } for (ClassEntry entry : match.destClasses) { ambiguousMatchesByDest.put(entry, match); } } else { // uniquely matched uniqueMatches.put(match.getUniqueSource(), match.getUniqueDest()); } } for (ClassEntry entry : match.sourceClasses) { matchesBySource.put(entry, match); } for (ClassEntry entry : match.destClasses) { matchesByDest.put(entry, match); } } public BiMap getUniqueMatches() { return uniqueMatches; } public Set getUnmatchedSourceClasses() { return unmatchedSourceClasses; } public Set getUnmatchedDestClasses() { return unmatchedDestClasses; } public Set getAmbiguouslyMatchedSourceClasses() { return ambiguousMatchesBySource.keySet(); } public ClassMatch getAmbiguousMatchBySource(ClassEntry sourceClass) { return ambiguousMatchesBySource.get(sourceClass); } public ClassMatch getMatchBySource(ClassEntry sourceClass) { return matchesBySource.get(sourceClass); } public ClassMatch getMatchByDest(ClassEntry destClass) { return matchesByDest.get(destClass); } public void removeSource(ClassEntry sourceClass) { ClassMatch match = 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 = matchesByDest.get(destClass); if (match != null) { remove(match); match.destClasses.remove(destClass); if (!match.sourceClasses.isEmpty() || !match.destClasses.isEmpty()) { add(match); } } } }