/******************************************************************************* * Copyright (c) 2014 Jeff Martin. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Jeff Martin - initial API and implementation ******************************************************************************/ package cuchaz.enigma.mapping; import java.util.List; import java.util.Map; import com.beust.jcommander.internal.Lists; import com.google.common.collect.Maps; import cuchaz.enigma.analysis.TranslationIndex; public class Translator { private TranslationDirection m_direction; private Map m_classes; private TranslationIndex m_index; private ClassNameReplacer m_classNameReplacer = new ClassNameReplacer() { @Override public String replace(String className) { return translateEntry(new ClassEntry(className)).getName(); } }; public Translator() { m_direction = null; m_classes = Maps.newHashMap(); m_index = new TranslationIndex(); } public Translator(TranslationDirection direction, Map classes, TranslationIndex index) { m_direction = direction; m_classes = classes; m_index = index; } @SuppressWarnings("unchecked") public T translateEntry(T entry) { if (entry instanceof ClassEntry) { return (T)translateEntry((ClassEntry)entry); } else if (entry instanceof FieldEntry) { return (T)translateEntry((FieldEntry)entry); } else if (entry instanceof MethodEntry) { return (T)translateEntry((MethodEntry)entry); } else if (entry instanceof ConstructorEntry) { return (T)translateEntry((ConstructorEntry)entry); } else if (entry instanceof ArgumentEntry) { return (T)translateEntry((ArgumentEntry)entry); } else { throw new Error("Unknown entry type: " + entry.getClass().getName()); } } public String translate(T entry) { if (entry instanceof ClassEntry) { return translate((ClassEntry)entry); } else if (entry instanceof FieldEntry) { return translate((FieldEntry)entry); } else if (entry instanceof MethodEntry) { return translate((MethodEntry)entry); } else if (entry instanceof ConstructorEntry) { return translate((ConstructorEntry)entry); } else if (entry instanceof ArgumentEntry) { return translate((ArgumentEntry)entry); } else { throw new Error("Unknown entry type: " + entry.getClass().getName()); } } public String translate(ClassEntry in) { ClassEntry translated = translateEntry(in); if (translated.equals(in)) { return null; } return translated.getName(); } public String translateClass(String className) { return translate(new ClassEntry(className)); } public ClassEntry translateEntry(ClassEntry in) { if (in.isInnerClass()) { // translate as much of the class chain as we can List mappingsChain = getClassMappingChain(in); String[] obfClassNames = in.getName().split("\\$"); StringBuilder buf = new StringBuilder(); for (int i=0; i mappingChain = getClassMappingChain(in); return mappingChain.get(mappingChain.size() - 1); } private List getClassMappingChain(ClassEntry in) { // get a list of all the classes in the hierarchy String[] parts = in.getName().split("\\$"); List mappingsChain = Lists.newArrayList(); // get mappings for the outer class ClassMapping outerClassMapping = m_classes.get(parts[0]); mappingsChain.add(outerClassMapping); for (int i=1; i