Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.wangjiegulu.rapidooo.library.compiler.oooentry.OOOConversionEntry Maven / Gradle / Ivy
package com.wangjiegulu.rapidooo.library.compiler.oooentry;
import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.squareup.javapoet.TypeName;
import com.wangjiegulu.rapidooo.api.OOOControlMode;
import com.wangjiegulu.rapidooo.api.OOOConversion;
import com.wangjiegulu.rapidooo.library.compiler.exception.RapidOOOCompileException;
import com.wangjiegulu.rapidooo.library.compiler.oooentry.type.OOOTypeEntry;
import com.wangjiegulu.rapidooo.library.compiler.oooentry.type.OOOTypeEntryFactory;
import com.wangjiegulu.rapidooo.library.compiler.util.AnnoUtil;
import com.wangjiegulu.rapidooo.library.compiler.util.ElementUtil;
import com.wangjiegulu.rapidooo.library.compiler.util.LogicUtil;
import com.wangjiegulu.rapidooo.library.compiler.util.TextUtil;
import com.wangjiegulu.rapidooo.library.compiler.util.func.Func0R;
import com.wangjiegulu.rapidooo.library.compiler.variables.IOOOVariable;
import com.wangjiegulu.rapidooo.library.compiler.variables.impl.OtherFieldVariable;
import com.wangjiegulu.rapidooo.library.compiler.variables.impl.OtherObjectVariable;
import com.wangjiegulu.rapidooo.library.compiler.variables.impl.SelfObjectVariable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
/**
* Author: wangjie Email: [email protected] Date: 2019-06-12.
*/
public class OOOConversionEntry implements IOOOVariable {
private OOOEntry oooEntry;
private OOOConversion oooConversion;
private String targetFieldName;
// private TypeName targetFieldType;
private String targetFieldTypeId;
private OOOTypeEntry oooTargetFieldTypeEntry;
// attach
private String attachFieldName;
private OOOFieldEntry oooAttachFieldEntry;
// private String attachFieldType; // as some as targetFieldType
// bind
private TypeName bindMethodClassType;
private TypeMirror bindMethodClass;
private String bindMethodName;
private String inverseBindMethodName;
private HashMap bindTargetParamFields = new LinkedHashMap<>();
private HashMap inverseBindTargetParamFields = new LinkedHashMap<>();
// conversion
private TypeName conversionMethodClassType;
private TypeMirror conversionMethodClass;
private String conversionMethodName;
private String inverseConversionMethodName;
private HashMap conversionTargetParamFields = new LinkedHashMap<>();
private HashMap inverseConversionTargetParamFields = new LinkedHashMap<>();
private OOOControlMode controlMode;
private boolean parcelable;
public OOOConversionEntry(OOOEntry oooEntry, final OOOConversion oooConversion) {
this.oooEntry = oooEntry;
this.oooConversion = oooConversion;
targetFieldName = oooConversion.targetFieldName();
// oooTargetFieldTypeEntry = new OOOTypeEntry();
// oooTargetFieldTypeEntry.parse(ElementUtil.getTypeName(AnnoUtil.getType(new Func0R() {
// @Override
// public Object call() {
// return oooConversion.targetFieldType();
// }
// })));
targetFieldTypeId = oooConversion.targetFieldTypeId();
parcelable = oooConversion.parcelable();
// attach mode
attachFieldName = oooConversion.attachFieldName();
// bind mode
bindMethodClass = AnnoUtil.getType(new Func0R() {
@Override
public Object call() {
return oooConversion.bindMethodClass();
}
});
bindMethodClassType = ElementUtil.getTypeName(bindMethodClass);
if (ElementUtil.isSameType(bindMethodClassType, TypeName.get(Object.class))) { // 如果没有配置,则默认是 Generator 类
bindMethodClassType = oooEntry.getOoosEntry().getOooGenerator().getGeneratorClassType();
bindMethodClass = oooEntry.getOoosEntry().getOooGenerator().getGeneratorClassEl().asType();
}
bindMethodName = oooConversion.bindMethodName();
inverseBindMethodName = oooConversion.inverseBindMethodName();
// conversion mode
conversionMethodClass = AnnoUtil.getType(new Func0R() {
@Override
public Object call() {
return oooConversion.conversionMethodClass();
}
});
conversionMethodClassType = ElementUtil.getTypeName(conversionMethodClass);
if (ElementUtil.isSameType(conversionMethodClassType, TypeName.get(Object.class))) { // 如果没有配置,则默认是 Generator 类
conversionMethodClassType = oooEntry.getOoosEntry().getOooGenerator().getGeneratorClassType();
conversionMethodClass = oooEntry.getOoosEntry().getOooGenerator().getGeneratorClassEl().asType();
}
conversionMethodName = oooConversion.conversionMethodName();
inverseConversionMethodName = oooConversion.inverseConversionMethodName();
init();
}
public OOOConversionEntry prepare() {
if (!AnnoUtil.oooParamIsNotSet(targetFieldTypeId)) { // 设置了 type id,则从缓存中查询
// oooTargetFieldTypeEntry.parse(this, targetFieldTypeId);
oooTargetFieldTypeEntry = OOOTypeEntryFactory.create(targetFieldTypeId);
} else {
oooTargetFieldTypeEntry = OOOTypeEntryFactory.create(ElementUtil.getTypeName(AnnoUtil.getType(new Func0R() {
@Override
public Object call() {
return oooConversion.targetFieldType();
}
})));
}
return this;
}
public void parse() {
parseControlMode();
}
private void init() {
}
/**
* 解析 control mode 的类型,并做好校验工作
*/
private void parseControlMode() {
boolean attachSet = !AnnoUtil.oooParamIsNotSet(attachFieldName);
boolean bindSet = !AnnoUtil.oooParamIsNotSet(bindMethodName) || !AnnoUtil.oooParamIsNotSet(inverseBindMethodName);
boolean conversionSet = !AnnoUtil.oooParamIsNotSet(conversionMethodName) || !AnnoUtil.oooParamIsNotSet(inverseConversionMethodName);
if (LogicUtil.countBoolean(attachSet, bindSet, conversionSet).size() > 1) {
throw new RapidOOOCompileException("Can not be set ATTACH or BIND or CONVERSION at the same time.");
}
if (bindSet) {
controlMode = OOOControlMode.BIND;
parseBindMode();
} else if (conversionSet) {
controlMode = OOOControlMode.CONVERSION;
parseConversionMode();
} else if (attachSet) {
controlMode = OOOControlMode.ATTACH;
if (AnnoUtil.oooParamIsNotSet(attachFieldName)) {
attachFieldName = targetFieldName;
}
parseAttachMode();
} else {
controlMode = OOOControlMode.NONE;
}
}
private void parseAttachMode() {
oooAttachFieldEntry = LogicUtil.checkNullCondition(oooEntry.searchFromField(attachFieldName), "Field[" + attachFieldName + "] is not exist in " + oooEntry.getFromTypeName() + " class.");
// TypeName attachTypeName = oooAttachFieldEntry.fieldTypeEntry().getTypeName();
// TypeName targetTypeName = oooTargetFieldTypeEntry.getTypeName();
}
private void parseBindMode() {
if (isBindMethodSet()) {
TypeName targetFieldType = oooTargetFieldTypeEntry.getTypeName();
// 检查 bind method 是否存在
ExecutableElement method = findPublicStaticMethodInClass(bindMethodClass, bindMethodName, targetFieldType);
if (null == method) {
throw new RapidOOOCompileException("Method[public static " + targetFieldType.toString() + " " + bindMethodName + "(...)] not found \nin " + bindMethodClass.toString() + " class.");
}
// 检查 bind method 方法中的所有参数是否存在在 OOO 中
bindTargetParamFields = findBindMethodVariables(method);
}
if (isInverseBindMethodSet()) {
// 检查 bind method 是否存在
ExecutableElement method = findPublicStaticMethodInClass(bindMethodClass, inverseBindMethodName, ElementUtil.getTypeName(void.class));
if (null == method) {
throw new RapidOOOCompileException("Method[public static void " + inverseBindMethodName + "(...)] not found \nin " + bindMethodClass.toString() + " class.");
}
// 检查 bind method 方法中的所有参数是否存在在 OOO 中
inverseBindTargetParamFields = findBindMethodVariables(method);
}
}
private void parseConversionMode() {
if (isConversionMethodSet()) {
TypeName targetFieldType = oooTargetFieldTypeEntry.getTypeName();
// 检查 conversion method 是否存在
ExecutableElement method = findPublicStaticMethodInClass(conversionMethodClass, conversionMethodName, targetFieldType);
if (null == method) {
throw new RapidOOOCompileException("Method[public static " + targetFieldType.toString() + " " + conversionMethodName + "(...)] not found \nin " + conversionMethodClass.toString() + " class.");
}
// 检查 conversion method 方法中的所有参数是否存在在 OOO 中
conversionTargetParamFields = findConversionMethodVariables(method);
}
if (isInverseConversionMethodSet()) {
// 检查 conversion method 是否存在
ExecutableElement method = findPublicStaticMethodInClass(conversionMethodClass, inverseConversionMethodName, ElementUtil.getTypeName(void.class));
if (null == method) {
throw new RapidOOOCompileException("Method[public static void " + inverseConversionMethodName + "(...)] not found \nin " + conversionMethodClass.toString() + " class.");
}
// 检查 conversion method 方法中的所有参数是否存在在 OOO 中
inverseConversionTargetParamFields = findConversionMethodVariables(method);
}
}
/**
* 检查 bind method 方法中的所有参数是否存在在 OOO 中
*/
private HashMap findBindMethodVariables(ExecutableElement method) {
HashMap variableElements = new LinkedHashMap<>();
for (VariableElement ve : method.getParameters()) {
if (
TextUtil.equals(ve.getSimpleName().toString(), "self")
&&
// TODO: 2019-06-13 wangjie validate class type simple name here, need optimize
TextUtil.equals(ve.asType().toString(), oooEntry.getTargetClassSimpleName())
) {
SelfObjectVariable selfObjectVariable = new SelfObjectVariable(ve.getSimpleName().toString());
variableElements.put(selfObjectVariable.fieldName(), selfObjectVariable);
} else {
// 检查某个参数是否存在在 OOO 中
IOOOVariable fieldEntry = findFieldInOOO(ve);
if (null == fieldEntry) {
throw new RapidOOOCompileException("Can not found field[" + ve.getSimpleName() + "-" + method.getSimpleName() + "] \nin " + oooEntry.getTargetClassSimpleName());
}
variableElements.put(fieldEntry.fieldName(), fieldEntry);
}
}
return variableElements;
}
/**
* 检查 conversion method 方法中的所有参数是否存在在 OOO 中
*/
private HashMap findConversionMethodVariables(ExecutableElement method) {
HashMap variableElements = new LinkedHashMap<>();
for (VariableElement ve : method.getParameters()) {
if (
TextUtil.equals(ve.getSimpleName().toString(), "self")
&&
// TODO: 2019-06-13 wangjie validate class type simple name here, need optimize
TextUtil.equals(MoreTypes.asTypeElement(ve.asType()).getSimpleName().toString(), oooEntry.getTargetClassSimpleName())
) {
SelfObjectVariable selfObjectVariable = new SelfObjectVariable(ve.getSimpleName().toString());
variableElements.put(selfObjectVariable.fieldName(), selfObjectVariable);
} else if (
TextUtil.equals(ve.getSimpleName().toString(), "other")
&&
// TODO: 2019-06-13 wangjie validate class type simple name here, need optimize
TextUtil.equals(MoreTypes.asTypeElement(ve.asType()).getSimpleName().toString(), oooEntry.getFromSimpleName())
) {
OtherObjectVariable otherObjectVariable = new OtherObjectVariable(ve.getSimpleName().toString(), TextUtil.firstCharLower(oooEntry.getFromSimpleName()));
variableElements.put(otherObjectVariable.fieldName(), otherObjectVariable);
} else {
// 检查某个参数是否存在在 OOO 中
IOOOVariable fieldEntry = findFieldInOOO(ve);
if (null != fieldEntry) {
variableElements.put(fieldEntry.fieldName(), fieldEntry);
} else {
// TODO: 2019-06-14 wangjie 校验 ve 是否存在 other class 里面?
OtherFieldVariable otherFieldVariable = new OtherFieldVariable(ve, TextUtil.firstCharLower(oooEntry.getFromSimpleName()));
variableElements.put(otherFieldVariable.fieldName(), otherFieldVariable);
}
}
}
return variableElements;
}
/**
* 检查某个参数是否存在在 OOO 中
*/
private IOOOVariable findFieldInOOO(VariableElement variableElement) {
// TODO: 2019-06-13 wangjie 支持父类字段?
for (Map.Entry e : oooEntry.getAllContinuingFields().entrySet()) {
OOOFieldEntry fieldEntry = e.getValue();
if (
// 属性名一样
TextUtil.equals(variableElement.getSimpleName().toString(), fieldEntry.getSimpleName())
&&
// 属性类型一样
ElementUtil.isSameType(variableElement.asType(), fieldEntry.getTypeName())
) {
return fieldEntry;
}
}
for (Map.Entry e : oooEntry.getConversions().entrySet()) {
OOOConversionEntry conversionEntry = e.getValue();
if (
// 属性名一样
TextUtil.equals(variableElement.getSimpleName().toString(), conversionEntry.getTargetFieldName())
&&
// 属性类型一样
ElementUtil.isSameType(variableElement.asType(), conversionEntry.getTargetFieldType())
) {
return conversionEntry;
}
}
return null;
}
/**
* 检查对应名字的 method 是否在某个类中存在
*/
private ExecutableElement findPublicStaticMethodInClass(TypeMirror methodClass, String methodName, TypeName returnType) {
for (Element e : MoreTypes.asElement(methodClass).getEnclosedElements()) {
if (e.getKind() == ElementKind.METHOD) {
// Must public static
ExecutableElement method = MoreElements.asExecutable(e);
if (!MoreElements.hasModifiers(Modifier.STATIC).apply(method)
||
!MoreElements.hasModifiers(Modifier.PUBLIC).apply(method)
) {
continue;
}
if (
TextUtil.equals(methodName, method.getSimpleName().toString())
&&
ElementUtil.isSameType(method.getReturnType(), returnType)
) {
return method;
}
}
}
return null;
}
public OOOEntry getOooEntry() {
return oooEntry;
}
public String getTargetFieldName() {
return targetFieldName;
}
public TypeName getTargetFieldType() {
return oooTargetFieldTypeEntry.getTypeName();
}
public String getTargetFieldTypeId() {
return targetFieldTypeId;
}
public String getBindMethodName() {
return bindMethodName;
}
public String getInverseBindMethodName() {
return inverseBindMethodName;
}
public String getConversionMethodName() {
return conversionMethodName;
}
public String getInverseConversionMethodName() {
return inverseConversionMethodName;
}
public TypeName getBindMethodClassType() {
return bindMethodClassType;
}
public TypeName getConversionMethodClassType() {
return conversionMethodClassType;
}
public OOOControlMode getControlMode() {
return controlMode;
}
public OOOTypeEntry getTargetFieldTypeEntry() {
return oooTargetFieldTypeEntry;
}
public OOOFieldEntry getAttachFieldEntry() {
return oooAttachFieldEntry;
}
public boolean isBindMethodSet() {
return !AnnoUtil.oooParamIsNotSet(bindMethodName);
}
public boolean isInverseBindMethodSet() {
return !AnnoUtil.oooParamIsNotSet(inverseBindMethodName);
}
public boolean isConversionMethodSet() {
return !AnnoUtil.oooParamIsNotSet(conversionMethodName);
}
public boolean isInverseConversionMethodSet() {
return !AnnoUtil.oooParamIsNotSet(inverseConversionMethodName);
}
public HashMap getBindTargetParamFields() {
return bindTargetParamFields;
}
public HashMap getInverseBindTargetParamFields() {
return inverseBindTargetParamFields;
}
public HashMap getConversionTargetParamFields() {
return conversionTargetParamFields;
}
public HashMap getInverseConversionTargetParamFields() {
return inverseConversionTargetParamFields;
}
public boolean isTargetFieldTypeId() {
return null != targetFieldTypeId && !AnnoUtil.oooParamIsNotSet(targetFieldTypeId);
}
public TypeName getAttachFieldType() {
// attach 属性类型与 target 一样
return oooAttachFieldEntry.getTypeName();
// return oooTargetFieldTypeEntry.getTypeName();
}
public boolean isParcelable() {
return parcelable;
}
public String getAttachFieldName() {
return attachFieldName;
}
@Override
public String fieldName() {
return targetFieldName;
}
@Override
public String inputCode() {
return "this." + targetFieldName;
}
}