/*******************************************************************************
* 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 {
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();
matches.forEach(this::indexMatch);
}
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);
}
}
}
}