summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/convert/ClassMatching.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/convert/ClassMatching.java')
-rw-r--r--src/cuchaz/enigma/convert/ClassMatching.java200
1 files changed, 91 insertions, 109 deletions
diff --git a/src/cuchaz/enigma/convert/ClassMatching.java b/src/cuchaz/enigma/convert/ClassMatching.java
index 53b6f7f..b94fd8b 100644
--- a/src/cuchaz/enigma/convert/ClassMatching.java
+++ b/src/cuchaz/enigma/convert/ClassMatching.java
@@ -10,164 +10,146 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.convert; 11package cuchaz.enigma.convert;
12 12
13import java.util.AbstractMap;
14import java.util.ArrayList; 13import java.util.ArrayList;
15import java.util.Arrays;
16import java.util.Collection; 14import java.util.Collection;
17import java.util.List; 15import java.util.List;
18import java.util.Map; 16import java.util.Map.Entry;
17import java.util.Set;
19 18
20import com.google.common.collect.ArrayListMultimap;
21import com.google.common.collect.BiMap; 19import com.google.common.collect.BiMap;
22import com.google.common.collect.HashBiMap; 20import com.google.common.collect.HashBiMap;
23import com.google.common.collect.Lists; 21import com.google.common.collect.Lists;
24import com.google.common.collect.Maps; 22import com.google.common.collect.Sets;
25import com.google.common.collect.Multimap; 23
24import cuchaz.enigma.mapping.ClassEntry;
26 25
27public class ClassMatching { 26public class ClassMatching {
28 27
29 private Multimap<ClassIdentity,ClassIdentity> m_sourceClasses; 28 private ClassForest m_sourceClasses;
30 private Multimap<ClassIdentity,ClassIdentity> m_matchedDestClasses; 29 private ClassForest m_destClasses;
31 private List<ClassIdentity> m_unmatchedDestClasses; 30 private BiMap<ClassEntry,ClassEntry> m_knownMatches;
32
33 public ClassMatching() {
34 m_sourceClasses = ArrayListMultimap.create();
35 m_matchedDestClasses = ArrayListMultimap.create();
36 m_unmatchedDestClasses = Lists.newArrayList();
37 }
38 31
39 public void addSource(ClassIdentity c) { 32 public ClassMatching(ClassIdentifier sourceIdentifier, ClassIdentifier destIdentifier) {
40 m_sourceClasses.put(c, c); 33 m_sourceClasses = new ClassForest(sourceIdentifier);
34 m_destClasses = new ClassForest(destIdentifier);
35 m_knownMatches = HashBiMap.create();
41 } 36 }
42 37
43 public void matchDestClass(ClassIdentity destClass) { 38 public void addKnownMatches(BiMap<ClassEntry,ClassEntry> knownMatches) {
44 Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get(destClass); 39 m_knownMatches.putAll(knownMatches);
45 if (matchedSourceClasses.isEmpty()) {
46 // no match
47 m_unmatchedDestClasses.add(destClass);
48 } else {
49 // found a match
50 m_matchedDestClasses.put(destClass, destClass);
51
52 // DEBUG
53 ClassIdentity sourceClass = matchedSourceClasses.iterator().next();
54 assert (sourceClass.hashCode() == destClass.hashCode());
55 assert (sourceClass.equals(destClass));
56 }
57 } 40 }
58 41
59 public void removeSource(ClassIdentity sourceClass) { 42 public void match(Iterable<ClassEntry> sourceClasses, Iterable<ClassEntry> destClasses) {
60 m_sourceClasses.remove(sourceClass, sourceClass); 43 m_sourceClasses.addAll(sourceClasses);
44 m_destClasses.addAll(destClasses);
61 } 45 }
62 46
63 public void removeDest(ClassIdentity destClass) { 47 public Collection<ClassMatch> matches() {
64 m_matchedDestClasses.remove(destClass, destClass); 48 List<ClassMatch> matches = Lists.newArrayList();
65 m_unmatchedDestClasses.remove(destClass); 49 for (Entry<ClassEntry,ClassEntry> entry : m_knownMatches.entrySet()) {
50 matches.add(new ClassMatch(
51 entry.getKey(),
52 entry.getValue()
53 ));
54 }
55 for (ClassIdentity identity : m_sourceClasses.identities()) {
56 matches.add(new ClassMatch(
57 m_sourceClasses.getClasses(identity),
58 m_destClasses.getClasses(identity)
59 ));
60 }
61 for (ClassIdentity identity : m_destClasses.identities()) {
62 if (!m_sourceClasses.containsIdentity(identity)) {
63 matches.add(new ClassMatch(
64 new ArrayList<ClassEntry>(),
65 m_destClasses.getClasses(identity)
66 ));
67 }
68 }
69 return matches;
66 } 70 }
67 71
68 public List<ClassIdentity> getSourceClasses() { 72 public Collection<ClassEntry> sourceClasses() {
69 return new ArrayList<ClassIdentity>(m_sourceClasses.values()); 73 Set<ClassEntry> classes = Sets.newHashSet();
74 for (ClassMatch match : matches()) {
75 classes.addAll(match.sourceClasses);
76 }
77 return classes;
70 } 78 }
71 79
72 public List<ClassIdentity> getDestClasses() { 80 public Collection<ClassEntry> destClasses() {
73 List<ClassIdentity> classes = Lists.newArrayList(); 81 Set<ClassEntry> classes = Sets.newHashSet();
74 classes.addAll(m_matchedDestClasses.values()); 82 for (ClassMatch match : matches()) {
75 classes.addAll(m_unmatchedDestClasses); 83 classes.addAll(match.destClasses);
84 }
76 return classes; 85 return classes;
77 } 86 }
78 87
79 public BiMap<ClassIdentity,ClassIdentity> getUniqueMatches() { 88 public BiMap<ClassEntry,ClassEntry> uniqueMatches() {
80 BiMap<ClassIdentity,ClassIdentity> uniqueMatches = HashBiMap.create(); 89 BiMap<ClassEntry,ClassEntry> uniqueMatches = HashBiMap.create();
81 for (ClassIdentity sourceClass : m_sourceClasses.keySet()) { 90 for (ClassMatch match : matches()) {
82 Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get(sourceClass); 91 if (match.isMatched() && !match.isAmbiguous()) {
83 Collection<ClassIdentity> matchedDestClasses = m_matchedDestClasses.get(sourceClass); 92 uniqueMatches.put(match.getUniqueSource(), match.getUniqueDest());
84 if (matchedSourceClasses.size() == 1 && matchedDestClasses.size() == 1) {
85 ClassIdentity matchedSourceClass = matchedSourceClasses.iterator().next();
86 ClassIdentity matchedDestClass = matchedDestClasses.iterator().next();
87 uniqueMatches.put(matchedSourceClass, matchedDestClass);
88 } 93 }
89 } 94 }
90 return uniqueMatches; 95 return uniqueMatches;
91 } 96 }
92 97
93 public BiMap<List<ClassIdentity>,List<ClassIdentity>> getAmbiguousMatches() { 98 public Collection<ClassMatch> ambiguousMatches() {
94 BiMap<List<ClassIdentity>,List<ClassIdentity>> ambiguousMatches = HashBiMap.create(); 99 List<ClassMatch> ambiguousMatches = Lists.newArrayList();
95 for (ClassIdentity sourceClass : m_sourceClasses.keySet()) { 100 for (ClassMatch match : matches()) {
96 Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get(sourceClass); 101 if (match.isMatched() && match.isAmbiguous()) {
97 Collection<ClassIdentity> matchedDestClasses = m_matchedDestClasses.get(sourceClass); 102 ambiguousMatches.add(match);
98 if (matchedSourceClasses.size() > 1 && matchedDestClasses.size() > 1) {
99 ambiguousMatches.put(
100 new ArrayList<ClassIdentity>(matchedSourceClasses),
101 new ArrayList<ClassIdentity>(matchedDestClasses)
102 );
103 } 103 }
104 } 104 }
105 return ambiguousMatches; 105 return ambiguousMatches;
106 } 106 }
107 107
108 public int getNumAmbiguousSourceMatches() { 108 public Collection<ClassEntry> unmatchedSourceClasses() {
109 int num = 0; 109 List<ClassEntry> classes = Lists.newArrayList();
110 for (Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet()) { 110 for (ClassMatch match : matches()) {
111 num += entry.getKey().size(); 111 if (!match.isMatched() && !match.sourceClasses.isEmpty()) {
112 } 112 classes.addAll(match.sourceClasses);
113 return num; 113 }
114 }
115
116 public int getNumAmbiguousDestMatches() {
117 int num = 0;
118 for (Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet()) {
119 num += entry.getValue().size();
120 } 114 }
121 return num; 115 return classes;
122 } 116 }
123 117
124 public List<ClassIdentity> getUnmatchedSourceClasses() { 118 public Collection<ClassEntry> unmatchedDestClasses() {
125 List<ClassIdentity> classes = Lists.newArrayList(); 119 List<ClassEntry> classes = Lists.newArrayList();
126 for (ClassIdentity sourceClass : getSourceClasses()) { 120 for (ClassMatch match : matches()) {
127 if (m_matchedDestClasses.get(sourceClass).isEmpty()) { 121 if (!match.isMatched() && !match.destClasses.isEmpty()) {
128 classes.add(sourceClass); 122 classes.addAll(match.destClasses);
129 } 123 }
130 } 124 }
131 return classes; 125 return classes;
132 } 126 }
133 127
134 public List<ClassIdentity> getUnmatchedDestClasses() { 128 public ClassIdentifier getSourceIdentifier() {
135 return new ArrayList<ClassIdentity>(m_unmatchedDestClasses); 129 return m_sourceClasses.getIdentifier();
136 } 130 }
137 131
138 public Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> getIndex() { 132 public ClassIdentifier getDestIdentifier() {
139 Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> conversion = Maps.newHashMap(); 133 return m_destClasses.getIdentifier();
140 for (Map.Entry<ClassIdentity,ClassIdentity> entry : getUniqueMatches().entrySet()) {
141 conversion.put(
142 entry.getKey().getClassEntry().getName(),
143 new AbstractMap.SimpleEntry<ClassIdentity,List<ClassIdentity>>(entry.getKey(), Arrays.asList(entry.getValue()))
144 );
145 }
146 for (Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet()) {
147 for (ClassIdentity sourceClass : entry.getKey()) {
148 conversion.put(
149 sourceClass.getClassEntry().getName(),
150 new AbstractMap.SimpleEntry<ClassIdentity,List<ClassIdentity>>(sourceClass, entry.getValue())
151 );
152 }
153 }
154 for (ClassIdentity sourceClass : getUnmatchedSourceClasses()) {
155 conversion.put(
156 sourceClass.getClassEntry().getName(),
157 new AbstractMap.SimpleEntry<ClassIdentity,List<ClassIdentity>>(sourceClass, getUnmatchedDestClasses())
158 );
159 }
160 return conversion;
161 } 134 }
162 135
163 @Override 136 @Override
164 public String toString() { 137 public String toString() {
138
139 // count the ambiguous classes
140 int numAmbiguousSource = 0;
141 int numAmbiguousDest = 0;
142 for (ClassMatch match : ambiguousMatches()) {
143 numAmbiguousSource += match.sourceClasses.size();
144 numAmbiguousDest += match.destClasses.size();
145 }
146
165 StringBuilder buf = new StringBuilder(); 147 StringBuilder buf = new StringBuilder();
166 buf.append(String.format("%12s%8s%8s\n", "", "Source", "Dest")); 148 buf.append(String.format("%20s%8s%8s\n", "", "Source", "Dest"));
167 buf.append(String.format("%12s%8d%8d\n", "Classes", getSourceClasses().size(), getDestClasses().size())); 149 buf.append(String.format("%20s%8d%8d\n", "Classes", sourceClasses().size(), destClasses().size()));
168 buf.append(String.format("%12s%8d%8d\n", "Unique", getUniqueMatches().size(), getUniqueMatches().size())); 150 buf.append(String.format("%20s%8d%8d\n", "Uniquely matched", uniqueMatches().size(), uniqueMatches().size()));
169 buf.append(String.format("%12s%8d%8d\n", "Ambiguous", getNumAmbiguousSourceMatches(), getNumAmbiguousDestMatches())); 151 buf.append(String.format("%20s%8d%8d\n", "Ambiguously matched", numAmbiguousSource, numAmbiguousDest));
170 buf.append(String.format("%12s%8d%8d\n", "Unmatched", getUnmatchedSourceClasses().size(), getUnmatchedDestClasses().size())); 152 buf.append(String.format("%20s%8d%8d\n", "Unmatched", unmatchedSourceClasses().size(), unmatchedDestClasses().size()));
171 return buf.toString(); 153 return buf.toString();
172 } 154 }
173} 155}