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.java173
1 files changed, 173 insertions, 0 deletions
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 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.convert;
12
13import java.util.AbstractMap;
14import java.util.ArrayList;
15import java.util.Arrays;
16import java.util.Collection;
17import java.util.List;
18import java.util.Map;
19
20import com.google.common.collect.ArrayListMultimap;
21import com.google.common.collect.BiMap;
22import com.google.common.collect.HashBiMap;
23import com.google.common.collect.Lists;
24import com.google.common.collect.Maps;
25import com.google.common.collect.Multimap;
26
27public class ClassMatching {
28
29 private Multimap<ClassIdentity,ClassIdentity> m_sourceClasses;
30 private Multimap<ClassIdentity,ClassIdentity> m_matchedDestClasses;
31 private List<ClassIdentity> m_unmatchedDestClasses;
32
33 public ClassMatching() {
34 m_sourceClasses = ArrayListMultimap.create();
35 m_matchedDestClasses = ArrayListMultimap.create();
36 m_unmatchedDestClasses = Lists.newArrayList();
37 }
38
39 public void addSource(ClassIdentity c) {
40 m_sourceClasses.put(c, c);
41 }
42
43 public void matchDestClass(ClassIdentity destClass) {
44 Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get(destClass);
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 }
58
59 public void removeSource(ClassIdentity sourceClass) {
60 m_sourceClasses.remove(sourceClass, sourceClass);
61 }
62
63 public void removeDest(ClassIdentity destClass) {
64 m_matchedDestClasses.remove(destClass, destClass);
65 m_unmatchedDestClasses.remove(destClass);
66 }
67
68 public List<ClassIdentity> getSourceClasses() {
69 return new ArrayList<ClassIdentity>(m_sourceClasses.values());
70 }
71
72 public List<ClassIdentity> getDestClasses() {
73 List<ClassIdentity> classes = Lists.newArrayList();
74 classes.addAll(m_matchedDestClasses.values());
75 classes.addAll(m_unmatchedDestClasses);
76 return classes;
77 }
78
79 public BiMap<ClassIdentity,ClassIdentity> getUniqueMatches() {
80 BiMap<ClassIdentity,ClassIdentity> uniqueMatches = HashBiMap.create();
81 for (ClassIdentity sourceClass : m_sourceClasses.keySet()) {
82 Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get(sourceClass);
83 Collection<ClassIdentity> matchedDestClasses = m_matchedDestClasses.get(sourceClass);
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 }
89 }
90 return uniqueMatches;
91 }
92
93 public BiMap<List<ClassIdentity>,List<ClassIdentity>> getAmbiguousMatches() {
94 BiMap<List<ClassIdentity>,List<ClassIdentity>> ambiguousMatches = HashBiMap.create();
95 for (ClassIdentity sourceClass : m_sourceClasses.keySet()) {
96 Collection<ClassIdentity> matchedSourceClasses = m_sourceClasses.get(sourceClass);
97 Collection<ClassIdentity> matchedDestClasses = m_matchedDestClasses.get(sourceClass);
98 if (matchedSourceClasses.size() > 1 && matchedDestClasses.size() > 1) {
99 ambiguousMatches.put(
100 new ArrayList<ClassIdentity>(matchedSourceClasses),
101 new ArrayList<ClassIdentity>(matchedDestClasses)
102 );
103 }
104 }
105 return ambiguousMatches;
106 }
107
108 public int getNumAmbiguousSourceMatches() {
109 int num = 0;
110 for (Map.Entry<List<ClassIdentity>,List<ClassIdentity>> entry : getAmbiguousMatches().entrySet()) {
111 num += entry.getKey().size();
112 }
113 return num;
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 }
121 return num;
122 }
123
124 public List<ClassIdentity> getUnmatchedSourceClasses() {
125 List<ClassIdentity> classes = Lists.newArrayList();
126 for (ClassIdentity sourceClass : getSourceClasses()) {
127 if (m_matchedDestClasses.get(sourceClass).isEmpty()) {
128 classes.add(sourceClass);
129 }
130 }
131 return classes;
132 }
133
134 public List<ClassIdentity> getUnmatchedDestClasses() {
135 return new ArrayList<ClassIdentity>(m_unmatchedDestClasses);
136 }
137
138 public Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> getIndex() {
139 Map<String,Map.Entry<ClassIdentity,List<ClassIdentity>>> conversion = Maps.newHashMap();
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 }
162
163 @Override
164 public String toString() {
165 StringBuilder buf = new StringBuilder();
166 buf.append(String.format("%12s%8s%8s\n", "", "Source", "Dest"));
167 buf.append(String.format("%12s%8d%8d\n", "Classes", getSourceClasses().size(), getDestClasses().size()));
168 buf.append(String.format("%12s%8d%8d\n", "Unique", getUniqueMatches().size(), getUniqueMatches().size()));
169 buf.append(String.format("%12s%8d%8d\n", "Ambiguous", getNumAmbiguousSourceMatches(), getNumAmbiguousDestMatches()));
170 buf.append(String.format("%12s%8d%8d\n", "Unmatched", getUnmatchedSourceClasses().size(), getUnmatchedDestClasses().size()));
171 return buf.toString();
172 }
173}