summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping/Mappings.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/mapping/Mappings.java')
-rw-r--r--src/cuchaz/enigma/mapping/Mappings.java188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java
new file mode 100644
index 0000000..57d8001
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/Mappings.java
@@ -0,0 +1,188 @@
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.mapping;
12
13import java.io.Serializable;
14import java.util.ArrayList;
15import java.util.Collection;
16import java.util.Map;
17import java.util.Set;
18
19import com.google.common.collect.Maps;
20import com.google.common.collect.Sets;
21
22import cuchaz.enigma.analysis.TranslationIndex;
23
24public class Mappings implements Serializable {
25
26 private static final long serialVersionUID = 4649790259460259026L;
27
28 protected Map<String,ClassMapping> m_classesByObf;
29 protected Map<String,ClassMapping> m_classesByDeobf;
30
31 public Mappings() {
32 m_classesByObf = Maps.newHashMap();
33 m_classesByDeobf = Maps.newHashMap();
34 }
35
36 public Mappings(Iterable<ClassMapping> classes) {
37 this();
38
39 for (ClassMapping classMapping : classes) {
40 m_classesByObf.put(classMapping.getObfName(), classMapping);
41 if (classMapping.getDeobfName() != null) {
42 m_classesByDeobf.put(classMapping.getDeobfName(), classMapping);
43 }
44 }
45 }
46
47 public Collection<ClassMapping> classes() {
48 assert (m_classesByObf.size() >= m_classesByDeobf.size());
49 return m_classesByObf.values();
50 }
51
52 public void addClassMapping(ClassMapping classMapping) {
53 if (m_classesByObf.containsKey(classMapping.getObfName())) {
54 throw new Error("Already have mapping for " + classMapping.getObfName());
55 }
56 boolean obfWasAdded = m_classesByObf.put(classMapping.getObfName(), classMapping) == null;
57 assert (obfWasAdded);
58 if (classMapping.getDeobfName() != null) {
59 if (m_classesByDeobf.containsKey(classMapping.getDeobfName())) {
60 throw new Error("Already have mapping for " + classMapping.getDeobfName());
61 }
62 boolean deobfWasAdded = m_classesByDeobf.put(classMapping.getDeobfName(), classMapping) == null;
63 assert (deobfWasAdded);
64 }
65 }
66
67 public void removeClassMapping(ClassMapping classMapping) {
68 boolean obfWasRemoved = m_classesByObf.remove(classMapping.getObfName()) != null;
69 assert (obfWasRemoved);
70 if (classMapping.getDeobfName() != null) {
71 boolean deobfWasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null;
72 assert (deobfWasRemoved);
73 }
74 }
75
76 public ClassMapping getClassByObf(ClassEntry entry) {
77 return getClassByObf(entry.getName());
78 }
79
80 public ClassMapping getClassByObf(String obfName) {
81 return m_classesByObf.get(obfName);
82 }
83
84 public ClassMapping getClassByDeobf(ClassEntry entry) {
85 return getClassByDeobf(entry.getName());
86 }
87
88 public ClassMapping getClassByDeobf(String deobfName) {
89 return m_classesByDeobf.get(deobfName);
90 }
91
92 public Translator getTranslator(TranslationDirection direction, TranslationIndex index) {
93 switch (direction) {
94 case Deobfuscating:
95
96 return new Translator(direction, m_classesByObf, index);
97
98 case Obfuscating:
99
100 // fill in the missing deobf class entries with obf entries
101 Map<String,ClassMapping> classes = Maps.newHashMap();
102 for (ClassMapping classMapping : classes()) {
103 if (classMapping.getDeobfName() != null) {
104 classes.put(classMapping.getDeobfName(), classMapping);
105 } else {
106 classes.put(classMapping.getObfName(), classMapping);
107 }
108 }
109
110 // translate the translation index
111 // NOTE: this isn't actually recursive
112 TranslationIndex deobfIndex = new TranslationIndex(index, getTranslator(TranslationDirection.Deobfuscating, index));
113
114 return new Translator(direction, classes, deobfIndex);
115
116 default:
117 throw new Error("Invalid translation direction!");
118 }
119 }
120
121 @Override
122 public String toString() {
123 StringBuilder buf = new StringBuilder();
124 for (ClassMapping classMapping : m_classesByObf.values()) {
125 buf.append(classMapping.toString());
126 buf.append("\n");
127 }
128 return buf.toString();
129 }
130
131 public void renameObfClass(String oldObfName, String newObfName) {
132 for (ClassMapping classMapping : new ArrayList<ClassMapping>(classes())) {
133 if (classMapping.renameObfClass(oldObfName, newObfName)) {
134 boolean wasRemoved = m_classesByObf.remove(oldObfName) != null;
135 assert (wasRemoved);
136 boolean wasAdded = m_classesByObf.put(newObfName, classMapping) == null;
137 assert (wasAdded);
138 }
139 }
140 }
141
142 public Set<String> getAllObfClassNames() {
143 final Set<String> classNames = Sets.newHashSet();
144 for (ClassMapping classMapping : classes()) {
145
146 // add the class name
147 classNames.add(classMapping.getObfName());
148
149 // add classes from method signatures
150 for (MethodMapping methodMapping : classMapping.methods()) {
151 for (Type type : methodMapping.getObfSignature().types()) {
152 if (type.hasClass()) {
153 classNames.add(type.getClassEntry().getClassName());
154 }
155 }
156 }
157 }
158 return classNames;
159 }
160
161 public boolean containsDeobfClass(String deobfName) {
162 return m_classesByDeobf.containsKey(deobfName);
163 }
164
165 public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName) {
166 ClassMapping classMapping = m_classesByObf.get(obfClassEntry.getName());
167 if (classMapping != null) {
168 return classMapping.containsDeobfField(deobfName);
169 }
170 return false;
171 }
172
173 public boolean containsDeobfMethod(ClassEntry obfClassEntry, String deobfName, Signature deobfSignature) {
174 ClassMapping classMapping = m_classesByObf.get(obfClassEntry.getName());
175 if (classMapping != null) {
176 return classMapping.containsDeobfMethod(deobfName, deobfSignature);
177 }
178 return false;
179 }
180
181 public boolean containsArgument(BehaviorEntry obfBehaviorEntry, String name) {
182 ClassMapping classMapping = m_classesByObf.get(obfBehaviorEntry.getClassName());
183 if (classMapping != null) {
184 return classMapping.containsArgument(obfBehaviorEntry, name);
185 }
186 return false;
187 }
188}