summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/mapping/Translator.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/mapping/Translator.java')
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
new file mode 100644
index 0000000..a5a3e2f
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -0,0 +1,235 @@
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.util.Map;
14
15import com.google.common.collect.Maps;
16
17import cuchaz.enigma.analysis.TranslationIndex;
18import cuchaz.enigma.mapping.SignatureUpdater.ClassNameUpdater;
19
20public class Translator {
21
22 private TranslationDirection m_direction;
23 private Map<String,ClassMapping> m_classes;
24 private TranslationIndex m_index;
25
26 public Translator() {
27 m_direction = null;
28 m_classes = Maps.newHashMap();
29 }
30
31 public Translator(TranslationDirection direction, Map<String,ClassMapping> classes, TranslationIndex index) {
32 m_direction = direction;
33 m_classes = classes;
34 m_index = index;
35 }
36
37 @SuppressWarnings("unchecked")
38 public <T extends Entry> T translateEntry(T entry) {
39 if (entry instanceof ClassEntry) {
40 return (T)translateEntry((ClassEntry)entry);
41 } else if (entry instanceof FieldEntry) {
42 return (T)translateEntry((FieldEntry)entry);
43 } else if (entry instanceof MethodEntry) {
44 return (T)translateEntry((MethodEntry)entry);
45 } else if (entry instanceof ConstructorEntry) {
46 return (T)translateEntry((ConstructorEntry)entry);
47 } else if (entry instanceof ArgumentEntry) {
48 return (T)translateEntry((ArgumentEntry)entry);
49 } else {
50 throw new Error("Unknown entry type: " + entry.getClass().getName());
51 }
52 }
53
54 public String translateClass(String className) {
55 return translate(new ClassEntry(className));
56 }
57
58 public String translate(ClassEntry in) {
59 ClassMapping classMapping = m_classes.get(in.getOuterClassName());
60 if (classMapping != null) {
61 if (in.isInnerClass()) {
62 // translate the inner class
63 String translatedInnerClassName = m_direction.choose(
64 classMapping.getDeobfInnerClassName(in.getInnerClassName()),
65 classMapping.getObfInnerClassName(in.getInnerClassName())
66 );
67 if (translatedInnerClassName != null) {
68 // try to translate the outer name
69 String translatedOuterClassName = m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName());
70 if (translatedOuterClassName != null) {
71 return translatedOuterClassName + "$" + translatedInnerClassName;
72 } else {
73 return in.getOuterClassName() + "$" + translatedInnerClassName;
74 }
75 }
76 } else {
77 // just return outer
78 return m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName());
79 }
80 }
81 return null;
82 }
83
84 public ClassEntry translateEntry(ClassEntry in) {
85
86 // can we translate the inner class?
87 String name = translate(in);
88 if (name != null) {
89 return new ClassEntry(name);
90 }
91
92 if (in.isInnerClass()) {
93
94 // guess not. just translate the outer class name then
95 String outerClassName = translate(in.getOuterClassEntry());
96 if (outerClassName != null) {
97 return new ClassEntry(outerClassName + "$" + in.getInnerClassName());
98 }
99 }
100
101 return in;
102 }
103
104 public String translate(FieldEntry in) {
105
106 // resolve the class entry
107 ClassEntry resolvedClassEntry = m_index.resolveEntryClass(in);
108 if (resolvedClassEntry != null) {
109
110 // look for the class
111 ClassMapping classMapping = findClassMapping(resolvedClassEntry);
112 if (classMapping != null) {
113
114 // look for the field
115 String translatedName = m_direction.choose(
116 classMapping.getDeobfFieldName(in.getName()),
117 classMapping.getObfFieldName(in.getName())
118 );
119 if (translatedName != null) {
120 return translatedName;
121 }
122 }
123 }
124 return null;
125 }
126
127 public FieldEntry translateEntry(FieldEntry in) {
128 String name = translate(in);
129 if (name == null) {
130 name = in.getName();
131 }
132 return new FieldEntry(translateEntry(in.getClassEntry()), name);
133 }
134
135 public String translate(MethodEntry in) {
136
137 // resolve the class entry
138 ClassEntry resolvedClassEntry = m_index.resolveEntryClass(in);
139 if (resolvedClassEntry != null) {
140
141 // look for class
142 ClassMapping classMapping = findClassMapping(resolvedClassEntry);
143 if (classMapping != null) {
144
145 // look for the method
146 MethodMapping methodMapping = m_direction.choose(
147 classMapping.getMethodByObf(in.getName(), in.getSignature()),
148 classMapping.getMethodByDeobf(in.getName(), translateSignature(in.getSignature()))
149 );
150 if (methodMapping != null) {
151 return m_direction.choose(methodMapping.getDeobfName(), methodMapping.getObfName());
152 }
153 }
154 }
155 return null;
156 }
157
158 public MethodEntry translateEntry(MethodEntry in) {
159 String name = translate(in);
160 if (name == null) {
161 name = in.getName();
162 }
163 return new MethodEntry(translateEntry(in.getClassEntry()), name, translateSignature(in.getSignature()));
164 }
165
166 public ConstructorEntry translateEntry(ConstructorEntry in) {
167 if (in.isStatic()) {
168 return new ConstructorEntry(translateEntry(in.getClassEntry()));
169 } else {
170 return new ConstructorEntry(translateEntry(in.getClassEntry()), translateSignature(in.getSignature()));
171 }
172 }
173
174 public BehaviorEntry translateEntry(BehaviorEntry in) {
175 if (in instanceof MethodEntry) {
176 return translateEntry((MethodEntry)in);
177 } else if (in instanceof ConstructorEntry) {
178 return translateEntry((ConstructorEntry)in);
179 }
180 throw new Error("Wrong entry type!");
181 }
182
183 public String translate(ArgumentEntry in) {
184
185 // look for the class
186 ClassMapping classMapping = findClassMapping(in.getClassEntry());
187 if (classMapping != null) {
188
189 // look for the method
190 MethodMapping methodMapping = m_direction.choose(
191 classMapping.getMethodByObf(in.getMethodName(), in.getMethodSignature()),
192 classMapping.getMethodByDeobf(in.getMethodName(), translateSignature(in.getMethodSignature()))
193 );
194 if (methodMapping != null) {
195 return m_direction.choose(
196 methodMapping.getDeobfArgumentName(in.getIndex()),
197 methodMapping.getObfArgumentName(in.getIndex())
198 );
199 }
200 }
201 return null;
202 }
203
204 public ArgumentEntry translateEntry(ArgumentEntry in) {
205 String name = translate(in);
206 if (name == null) {
207 name = in.getName();
208 }
209 return new ArgumentEntry(translateEntry(in.getBehaviorEntry()), in.getIndex(), name);
210 }
211
212 public String translateSignature(String signature) {
213 return SignatureUpdater.update(signature, new ClassNameUpdater() {
214 @Override
215 public String update(String className) {
216 String translatedName = translateClass(className);
217 if (translatedName != null) {
218 return translatedName;
219 }
220 return className;
221 }
222 });
223 }
224
225 private ClassMapping findClassMapping(ClassEntry classEntry) {
226 ClassMapping classMapping = m_classes.get(classEntry.getOuterClassName());
227 if (classMapping != null && classEntry.isInnerClass()) {
228 classMapping = m_direction.choose(
229 classMapping.getInnerClassByObf(classEntry.getInnerClassName()),
230 classMapping.getInnerClassByDeobfThenObf(classEntry.getInnerClassName())
231 );
232 }
233 return classMapping;
234 }
235}