package org.gsonformat.intellij.process;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import org.apache.http.util.TextUtils;
import org.gsonformat.intellij.common.FieldHelper;
import org.gsonformat.intellij.common.PsiClassUtil;
import org.gsonformat.intellij.common.Try;
import org.gsonformat.intellij.config.Config;
import org.gsonformat.intellij.config.Constant;
import org.gsonformat.intellij.entity.ConvertLibrary;
import org.gsonformat.intellij.entity.FieldEntity;
import org.gsonformat.intellij.entity.ClassEntity;
import java.util.HashMap;
import static org.gsonformat.intellij.common.StringUtils.captureName;
/**
* Created by dim on 16/11/7.
*/
public abstract class Processor {
private static HashMap<ConvertLibrary, Processor> sProcessorMap = new HashMap<>();
static {
sProcessorMap.put(ConvertLibrary.Gson, new GsonProcessor());
sProcessorMap.put(ConvertLibrary.Jack, new JackProcessor());
sProcessorMap.put(ConvertLibrary.FastJson, new FastJsonProcessor());
sProcessorMap.put(ConvertLibrary.AutoValue, new AutoValueProcessor());
sProcessorMap.put(ConvertLibrary.LoganSquare, new LoganSquareProcessor());
sProcessorMap.put(ConvertLibrary.Other, new OtherProcessor());
sProcessorMap.put(ConvertLibrary.Lombok, new LombokProcessor());
}
static Processor getProcessor(ConvertLibrary convertLibrary) {
return sProcessorMap.get(convertLibrary);
}
protected String mainPackage;
public void process(ClassEntity classEntity, PsiElementFactory factory, PsiClass cls, IProcessor visitor) {
mainPackage = PsiClassUtil.getPackage(cls);
onStarProcess(classEntity, factory, cls, visitor);
for (FieldEntity fieldEntity : classEntity.getFields()) {
generateField(factory, fieldEntity, cls, classEntity);
}
for (ClassEntity innerClass : classEntity.getInnerClasss()) {
generateClass(factory, innerClass, cls, visitor);
}
generateGetterAndSetter(factory, cls, classEntity);
generateConvertMethod(factory, cls, classEntity);
onEndProcess(classEntity, factory, cls, visitor);
}
protected void onEndProcess(ClassEntity classEntity, PsiElementFactory factory, PsiClass cls, IProcessor visitor) {
if (visitor != null) {
visitor.onEndProcess(classEntity, factory, cls);
}
formatJavCode(cls);
}
protected void formatJavCode(PsiClass cls) {
if (cls == null) {
return;
}
JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(cls.getProject());
styleManager.optimizeImports(cls.getContainingFile());
styleManager.shortenClassReferences(cls);
}
protected void onStarProcess(ClassEntity classEntity, PsiElementFactory factory, PsiClass cls, IProcessor visitor) {
if (visitor != null) {
visitor.onStarProcess(classEntity, factory, cls);
}
}
protected void generateConvertMethod(PsiElementFactory factory, PsiClass cls, ClassEntity classEntity) {
if (cls == null || cls.getName() == null) {
return;
}
if (Config.getInstant().isObjectFromData()) {
createMethod(factory, Config.getInstant().getObjectFromDataStr().replace("$ClassName$", cls.getName()).trim(), cls);
}
if (Config.getInstant().isObjectFromData1()) {
createMethod(factory, Config.getInstant().getObjectFromDataStr1().replace("$ClassName$", cls.getName()).trim(), cls);
}
if (Config.getInstant().isArrayFromData()) {
createMethod(factory, Config.getInstant().getArrayFromDataStr().replace("$ClassName$", cls.getName()).trim(), cls);
}
if (Config.getInstant().isArrayFromData1()) {
createMethod(factory, Config.getInstant().getArrayFromData1Str().replace("$ClassName$", cls.getName()).trim(), cls);
}
}
protected void generateGetterAndSetter(PsiElementFactory factory, PsiClass cls, ClassEntity classEntity) {
if (Config.getInstant().isFieldPrivateMode()) {
for (FieldEntity field : classEntity.getFields()) {
createGetAndSetMethod(factory, cls, field);
}
}
}
protected void createMethod(PsiElementFactory factory, String method, PsiClass cls) {
Try.run(new Try.TryListener() {
@Override
public void run() {
cls.add(factory.createMethodFromText(method, cls));
}
@Override
public void runAgain() {
}
@Override
public void error() {
}
});
}
protected void createGetAndSetMethod(PsiElementFactory factory, PsiClass cls, FieldEntity field) {
if (field.isGenerate()) {
String fieldName = field.getGenerateFieldName();
String typeStr = field.getRealType();
if (Config.getInstant().isUseFieldNamePrefix()) {
String temp = fieldName.replaceAll("^" + Config.getInstant().getFiledNamePreFixStr(), "");
if (!TextUtils.isEmpty(temp)) {
fieldName = temp;
}
}
if (typeStr.equals("boolean") || typeStr.equals("Boolean")) {
String method = "public ".concat(typeStr).concat(" is").concat(
captureName(fieldName)).concat("() { return ").concat(
field.getGenerateFieldName()).concat(" ;} ");
cls.add(factory.createMethodFromText(method, cls));
} else {
String method = "public ".concat(typeStr).concat(" get").concat(
captureName(fieldName)).concat(
"() { return ").concat(
field.getGenerateFieldName()).concat(" ;} ");
cls.add(factory.createMethodFromText(method, cls));
}
String arg = fieldName;
if (Config.getInstant().isUseFieldNamePrefix()) {
String temp = fieldName.replaceAll("^" + Config.getInstant().getFiledNamePreFixStr(), "");
if (!TextUtils.isEmpty(temp)) {
fieldName = temp;
arg = fieldName;
if (arg.length() > 0) {
if (arg.length() > 1) {
arg = (arg.charAt(0) + "").toLowerCase() + arg.substring(1);
} else {
arg = arg.toLowerCase();
}
}
}
}
String method = "public void set".concat(captureName(fieldName)).concat("( ").concat(typeStr).concat(" ").concat(arg).concat(") { ");
if (field.getGenerateFieldName().equals(arg)) {
method = method.concat("this.").concat(field.getGenerateFieldName()).concat(" = ").concat(arg).concat(";} ");
} else {
method = method.concat(field.getGenerateFieldName()).concat(" = ").concat(arg).concat(";} ");
}
String finalMethod = method;
String finalFieldName = fieldName;
Try.run(new Try.TryListener() {
@Override
public void run() {
cls.add(factory.createMethodFromText(finalMethod, cls));
}
@Override
public void runAgain() {
cls.addBefore(factory.createCommentFromText("// FIXME generate failure method set and get " + captureName(finalFieldName), cls), cls.getChildren()[0]);
}
@Override
public void error() {
}
});
}
}
protected void generateClass(PsiElementFactory factory, ClassEntity classEntity, PsiClass parentClass, IProcessor visitor) {
onStartGenerateClass(factory, classEntity, parentClass, visitor);
PsiClass generateClass = null;
if (classEntity.isGenerate()) {
//// TODO: 16/11/9 εΎ
ιζ
if (Config.getInstant().isSplitGenerate()) {
try {
generateClass = PsiClassUtil.getPsiClass(
parentClass.getContainingFile(), parentClass.getProject(), classEntity.getQualifiedName());
} catch (Throwable throwable) {
throwable.printStackTrace();
}
} else {
String classContent =
"public static class " + classEntity.getClassName() + "{}";
generateClass = factory.createClassFromText(classContent, null).getInnerClasses()[0];
}
if (generateClass != null) {
for (ClassEntity innerClass : classEntity.getInnerClasss()) {
generateClass(factory, innerClass, generateClass, visitor);
}
if (!Config.getInstant().isSplitGenerate()) {
generateClass = (PsiClass) parentClass.add(generateClass);
}
for (FieldEntity fieldEntity : classEntity.getFields()) {
generateField(factory, fieldEntity, generateClass, classEntity);
}
generateGetterAndSetter(factory, generateClass, classEntity);
generateConvertMethod(factory, generateClass, classEntity);
}
}
onEndGenerateClass(factory, classEntity, parentClass, generateClass, visitor);
if (Config.getInstant().isSplitGenerate()) {
formatJavCode(generateClass);
}
}
protected void onStartGenerateClass(PsiElementFactory factory, ClassEntity classEntity, PsiClass parentClass, IProcessor visitor) {
if (visitor != null) {
visitor.onStartGenerateClass(factory, classEntity, parentClass);
}
}
protected void onEndGenerateClass(PsiElementFactory factory, ClassEntity classEntity, PsiClass parentClass, PsiClass generateClass, IProcessor visitor) {
if (visitor != null) {
visitor.onEndGenerateClass(factory, classEntity, parentClass, generateClass);
}
}
protected void generateField(PsiElementFactory factory, FieldEntity fieldEntity, PsiClass cls, ClassEntity classEntity) {
if (fieldEntity.isGenerate()) {
Try.run(new Try.TryListener() {
@Override
public void run() {
cls.add(factory.createFieldFromText(generateFieldText(classEntity, fieldEntity, null), cls));
}
@Override
public void runAgain() {
fieldEntity.setFieldName(FieldHelper.generateLuckyFieldName(fieldEntity.getFieldName()));
cls.add(factory.createFieldFromText(generateFieldText(classEntity, fieldEntity, Constant.FIXME), cls));
}
@Override
public void error() {
cls.addBefore(factory.createCommentFromText("// FIXME generate failure field " + fieldEntity.getFieldName(), cls), cls.getChildren()[0]);
}
});
}
}
private String generateFieldText(ClassEntity classEntity, FieldEntity fieldEntity, String fixme) {
fixme = fixme == null ? "" : fixme;
StringBuilder fieldSb = new StringBuilder();
String filedName = fieldEntity.getGenerateFieldName();
if (!TextUtils.isEmpty(classEntity.getExtra())) {
fieldSb.append(classEntity.getExtra()).append("\n");
classEntity.setExtra(null);
}
if (fieldEntity.getTargetClass() != null) {
fieldEntity.getTargetClass().setGenerate(true);
}
if (!filedName.equals(fieldEntity.getKey()) || Config.getInstant().isUseSerializedName()) {
fieldSb.append(Config.getInstant().geFullNameAnnotation().replaceAll("\\{filed\\}", fieldEntity.getKey()));
}
if (Config.getInstant().isFieldPrivateMode()) {
fieldSb.append("private ").append(fieldEntity.getFullNameType()).append(" ").append(filedName).append(" ; ");
} else {
fieldSb.append("public ").append(fieldEntity.getFullNameType()).append(" ").append(filedName).append(" ; ");
}
return fieldSb.append(fixme).toString();
}
}