package com.arellomobile.mvp.compiler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.arellomobile.mvp.MvpProcessor;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
/**
* Date: 07.12.2016
* Time: 19:05
*
* @author Yuri Shmakov
*/
public class MoxyReflectorGenerator {
public static String generate(String moxyReflectorPackage,
List<String> presenterClassNames,
Set<TypeElement> presentersContainers,
Set<String> strategyClasses,
List<String> additionalMoxyReflectorsPackages) {
Map<TypeElement, TypeElement> extendingMap = new HashMap<>();
for (TypeElement presentersContainer : presentersContainers) {
TypeMirror superclass = presentersContainer.getSuperclass();
TypeElement parent = null;
while (superclass.getKind() == TypeKind.DECLARED) {
TypeElement superclassElement = (TypeElement) ((DeclaredType) superclass).asElement();
if (presentersContainers.contains(superclassElement)) {
parent = superclassElement;
break;
}
superclass = superclassElement.getSuperclass();
}
extendingMap.put(presentersContainer, parent);
}
Map<TypeElement, List<TypeElement>> elementListMap = new HashMap<>();
for (TypeElement presentersContainer : presentersContainers) {
ArrayList<TypeElement> typeElements = new ArrayList<>();
typeElements.add(presentersContainer);
elementListMap.put(presentersContainer, typeElements);
TypeElement key = presentersContainer;
while ((key = extendingMap.get(key)) != null) {
typeElements.add(key);
}
}
String builder = "package " + moxyReflectorPackage + ";\n" +
"\n" +
"import java.util.Arrays;\n" +
"import java.util.HashMap;\n" +
"import java.util.List;\n" +
"import java.util.Map;\n" +
"\n" +
"public class MoxyReflector {\n\n" +
"\tprivate static Map<Class<?>, Object> sViewStateProviders;\n" +
"\tprivate static Map<Class<?>, List<Object>> sPresenterBinders;\n" +
"\tprivate static Map<Class<?>, Object> sStrategies;\n" +
"\n" +
"\tstatic {\n" +
"\t\tsViewStateProviders = new HashMap<>();\n";
Collections.sort(presenterClassNames);
for (String presenterClassName : presenterClassNames) {
builder += "\t\tsViewStateProviders.put(" + presenterClassName + ".class, new " + presenterClassName + MvpProcessor.VIEW_STATE_PROVIDER_SUFFIX + "());\n";
}
builder += "\t\t\n"+
"\t\tsPresenterBinders = new HashMap<>();\n";
List<Map.Entry<TypeElement, List<TypeElement>>> elementListMapEntries = new ArrayList<>(elementListMap.entrySet());
Collections.sort(elementListMapEntries, new Comparator<Map.Entry<TypeElement, List<TypeElement>>>() {
@Override
public int compare(Map.Entry<TypeElement, List<TypeElement>> entry1, Map.Entry<TypeElement, List<TypeElement>> entry2) {
return entry1.getKey().getQualifiedName().toString().compareTo(entry2.getKey().getQualifiedName().toString());
}
});
for (Map.Entry<TypeElement, List<TypeElement>> keyValue : elementListMapEntries) {
builder += "\t\tsPresenterBinders.put(" + keyValue.getKey().getQualifiedName() + ".class, Arrays.<Object>asList(";
boolean isFirst = true;
for (TypeElement typeElement : keyValue.getValue()) {
if (isFirst) {
isFirst = false;
} else {
builder += ", ";
}
builder += "new " + Util.getFullClassName(typeElement) + MvpProcessor.PRESENTER_BINDER_SUFFIX + "()";
}
builder += "));\n";
}
builder += "\t\t\n" +
"\t\tsStrategies = new HashMap<>();\n";
List<String> strategyClassesList = new ArrayList<>(strategyClasses);
Collections.sort(strategyClassesList);
for (String strategyClass : strategyClassesList) {
builder += "\t\tsStrategies.put(" + strategyClass + ", new " + strategyClass.substring(0, strategyClass.lastIndexOf('.')) + "());\n";
}
Collections.sort(additionalMoxyReflectorsPackages);
for (String pkg : additionalMoxyReflectorsPackages) {
builder += "\t\t\n";
builder += "\t\tsViewStateProviders.putAll(" + pkg + ".MoxyReflector.getViewStateProviders());\n";
builder += "\t\tsPresenterBinders.putAll(" + pkg + ".MoxyReflector.getPresenterBinders());\n";
builder += "\t\tsStrategies.putAll(" + pkg + ".MoxyReflector.getStrategies());\n";
}
builder += "\t}\n";
if (moxyReflectorPackage.equals("com.arellomobile.mvp")) {
builder += "\t\n" +
"\tpublic static Object getViewState(Class<?> presenterClass) {\n" +
"\t\tViewStateProvider viewStateProvider = (ViewStateProvider) sViewStateProviders.get(presenterClass);\n" +
"\t\tif (viewStateProvider == null) {\n" +
"\t\t\treturn null;\n" +
"\t\t}\n" +
"\t\t\n" +
"\t\treturn viewStateProvider.getViewState();\n" +
"\t}\n" +
"\n" +
"\tpublic static List<Object> getPresenterBinders(Class<?> delegated) {\n" +
"\t\treturn sPresenterBinders.get(delegated);\n" +
"\t}\n" +
"\n" +
"\tpublic static Object getStrategy(Class<?> strategyClass) {\n" +
"\t\treturn sStrategies.get(strategyClass);\n" +
"\t}\n" +
"}\n";
} else {
builder += "\t\n" +
"\tpublic static Map<Class<?>, Object> getViewStateProviders() {\n" +
"\t\treturn sViewStateProviders;\n" +
"\t}\n" +
"\n" +
"\tpublic static Map<Class<?>, List<Object>> getPresenterBinders() {\n" +
"\t\treturn sPresenterBinders;\n" +
"\t}\n" +
"\n" +
"\tpublic static Map<Class<?>, Object> getStrategies() {\n" +
"\t\treturn sStrategies;\n" +
"\t}\n" +
"}\n";
}
return builder;
}
}