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.java154
1 files changed, 115 insertions, 39 deletions
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index 759dddf..d985032 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -10,8 +10,10 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma.mapping; 11package cuchaz.enigma.mapping;
12 12
13import java.util.List;
13import java.util.Map; 14import java.util.Map;
14 15
16import com.beust.jcommander.internal.Lists;
15import com.google.common.collect.Maps; 17import com.google.common.collect.Maps;
16 18
17import cuchaz.enigma.analysis.TranslationIndex; 19import cuchaz.enigma.analysis.TranslationIndex;
@@ -50,54 +52,106 @@ public class Translator {
50 } 52 }
51 } 53 }
52 54
55 public <T extends Entry> String translate(T entry) {
56 if (entry instanceof ClassEntry) {
57 return translate((ClassEntry)entry);
58 } else if (entry instanceof FieldEntry) {
59 return translate((FieldEntry)entry);
60 } else if (entry instanceof MethodEntry) {
61 return translate((MethodEntry)entry);
62 } else if (entry instanceof ConstructorEntry) {
63 return translate((ConstructorEntry)entry);
64 } else if (entry instanceof ArgumentEntry) {
65 return translate((ArgumentEntry)entry);
66 } else {
67 throw new Error("Unknown entry type: " + entry.getClass().getName());
68 }
69 }
70
53 public String translateClass(String className) { 71 public String translateClass(String className) {
54 return translate(new ClassEntry(className)); 72 return translate(new ClassEntry(className));
55 } 73 }
56 74
57 public String translate(ClassEntry in) { 75 public String translate(ClassEntry in) {
58 ClassMapping classMapping = m_classes.get(in.getOuterClassName()); 76
59 if (classMapping != null) { 77 if (in.isInnerClass()) {
60 if (in.isInnerClass()) { 78
61 // translate the inner class 79 // translate everything in the class chain, or return null
62 String translatedInnerClassName = m_direction.choose( 80 List<ClassMapping> mappingsChain = getClassMappingChain(in);
63 classMapping.getDeobfInnerClassName(in.getInnerClassName()), 81 StringBuilder buf = new StringBuilder();
64 classMapping.getObfInnerClassName(in.getInnerClassName()) 82 for (ClassMapping classMapping : mappingsChain) {
83 if (classMapping == null) {
84 return null;
85 }
86 boolean isFirstClass = buf.length() == 0;
87 String name = m_direction.choose(
88 classMapping.getDeobfName(),
89 isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName()
65 ); 90 );
66 if (translatedInnerClassName != null) { 91 if (name == null) {
67 // try to translate the outer name 92 return null;
68 String translatedOuterClassName = m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName()); 93 }
69 if (translatedOuterClassName != null) { 94 if (!isFirstClass) {
70 return translatedOuterClassName + "$" + translatedInnerClassName; 95 buf.append("$");
71 } else {
72 return in.getOuterClassName() + "$" + translatedInnerClassName;
73 }
74 } 96 }
75 } else { 97 buf.append(name);
76 // just return outer
77 return m_direction.choose(classMapping.getDeobfName(), classMapping.getObfName());
78 } 98 }
99 return buf.toString();
100
101 } else {
102
103 // normal classes are easier
104 ClassMapping classMapping = m_classes.get(in.getName());
105 if (classMapping == null) {
106 return null;
107 }
108 return m_direction.choose(
109 classMapping.getDeobfName(),
110 classMapping.getObfFullName()
111 );
79 } 112 }
80 return null;
81 } 113 }
82 114
83 public ClassEntry translateEntry(ClassEntry in) { 115 public ClassEntry translateEntry(ClassEntry in) {
84 116
85 // can we translate the inner class?
86 String name = translate(in);
87 if (name != null) {
88 return new ClassEntry(name);
89 }
90
91 if (in.isInnerClass()) { 117 if (in.isInnerClass()) {
92 118
93 // guess not. just translate the outer class name then 119 // translate as much of the class chain as we can
94 String outerClassName = translate(in.getOuterClassEntry()); 120 List<ClassMapping> mappingsChain = getClassMappingChain(in);
95 if (outerClassName != null) { 121 String[] obfClassNames = in.getName().split("\\$");
96 return new ClassEntry(outerClassName + "$" + in.getInnerClassName()); 122 StringBuilder buf = new StringBuilder();
123 for (int i=0; i<obfClassNames.length; i++) {
124 boolean isFirstClass = buf.length() == 0;
125 String className = null;
126 ClassMapping classMapping = mappingsChain.get(i);
127 if (classMapping != null) {
128 className = m_direction.choose(
129 classMapping.getDeobfName(),
130 isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName()
131 );
132 }
133 if (className == null) {
134 className = obfClassNames[i];
135 }
136 if (!isFirstClass) {
137 buf.append("$");
138 }
139 buf.append(className);
97 } 140 }
141 return new ClassEntry(buf.toString());
142
143 } else {
144
145 // normal classes are easy
146 ClassMapping classMapping = m_classes.get(in.getName());
147 if (classMapping == null) {
148 return in;
149 }
150 return m_direction.choose(
151 classMapping.getDeobfName() != null ? new ClassEntry(classMapping.getDeobfName()) : in,
152 new ClassEntry(classMapping.getObfFullName())
153 );
98 } 154 }
99
100 return in;
101 } 155 }
102 156
103 public String translate(FieldEntry in) { 157 public String translate(FieldEntry in) {
@@ -226,14 +280,36 @@ public class Translator {
226 }); 280 });
227 } 281 }
228 282
229 private ClassMapping findClassMapping(ClassEntry classEntry) { 283 private ClassMapping findClassMapping(ClassEntry in) {
230 ClassMapping classMapping = m_classes.get(classEntry.getOuterClassName()); 284 List<ClassMapping> mappingChain = getClassMappingChain(in);
231 if (classMapping != null && classEntry.isInnerClass()) { 285 return mappingChain.get(mappingChain.size() - 1);
232 classMapping = m_direction.choose( 286 }
233 classMapping.getInnerClassByObf(classEntry.getInnerClassName()), 287
234 classMapping.getInnerClassByDeobfThenObf(classEntry.getInnerClassName()) 288 private List<ClassMapping> getClassMappingChain(ClassEntry in) {
235 ); 289
290 // get a list of all the classes in the hierarchy
291 String[] parts = in.getName().split("\\$");
292 List<ClassMapping> mappingsChain = Lists.newArrayList();
293
294 // get mappings for the outer class
295 ClassMapping outerClassMapping = m_classes.get(parts[0]);
296 mappingsChain.add(outerClassMapping);
297
298 for (int i=1; i<parts.length; i++) {
299
300 // get mappings for the inner class
301 ClassMapping innerClassMapping = null;
302 if (outerClassMapping != null) {
303 innerClassMapping = m_direction.choose(
304 outerClassMapping.getInnerClassByObf(parts[i]),
305 outerClassMapping.getInnerClassByDeobfThenObf(parts[i])
306 );
307 }
308 mappingsChain.add(innerClassMapping);
309 outerClassMapping = innerClassMapping;
236 } 310 }
237 return classMapping; 311
312 assert(mappingsChain.size() == parts.length);
313 return mappingsChain;
238 } 314 }
239} 315}