package com.github.florent37.rxandroidorm; import com.github.florent37.rxandroidorm.annotations.Id; import com.github.florent37.rxandroidorm.annotations.Ignore; import com.squareup.javapoet.ArrayTypeName; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; import javax.lang.model.util.ElementFilter; /** * Created by florentchampigny on 17/01/16. */ public class ProcessUtils { public static List<VariableElement> filterIgnore(List<VariableElement> elements) { List<VariableElement> filtered = new ArrayList<>(); for (VariableElement variableElement : elements) { if (variableElement.getAnnotation(Ignore.class) == null && !Constants.PARCEL_CREATOR.equals( ProcessUtils.getObjectName(variableElement)) || ProcessUtils.isNotVariable(variableElement)) { filtered.add(variableElement); } } return filterStaticFinal(filtered); } private static boolean isNotVariable(VariableElement variableElement) { return variableElement.getKind() == ElementKind.ENUM || variableElement.getKind() == ElementKind.INTERFACE || variableElement.getKind() == ElementKind.CLASS; } public static List<VariableElement> filterStaticFinal(List<VariableElement> elements) { List<VariableElement> filtered = new ArrayList<>(); for (VariableElement variableElement : elements) { final Set<Modifier> modifiers = variableElement.getModifiers(); if (!modifiers.containsAll(Arrays.asList(Modifier.FINAL, Modifier.STATIC))) { filtered.add(variableElement); } } return filtered; } public static List<VariableElement> getFields(Element element) { return filterIgnore(ElementFilter.fieldsIn(element.getEnclosedElements())); } public static List<VariableElement> getPrimitiveFields(Element element) { List<VariableElement> primitives = new ArrayList<>(); for (VariableElement e : getFields(element)) { if (isPrimitive(e) && !isCollectionOfPrimitive(e) && !isNotVariable(e)) { primitives.add(e); } } return filterIgnore(primitives); } public static List<VariableElement> getCollectionsOfPrimitiveFields(Element element) { List<VariableElement> collectionsOfPrimitives = new ArrayList<>(); for (VariableElement e : getFields(element)) { if (isCollectionOfPrimitive(e) && !isNotVariable(e)) { collectionsOfPrimitives.add(e); } } return filterIgnore(collectionsOfPrimitives); } public static List<VariableElement> getNonPrimitiveClassFields(Element element) { List<VariableElement> nonPrimitive = new ArrayList<>(); for (VariableElement e : getFields(element)) { if (!isPrimitive(e) && !isCollectionOfPrimitive(e) && !isNotVariable(e)) { nonPrimitive.add(e); } } return filterIgnore(nonPrimitive); } public static boolean hasIdField(Element element) { return getIdField(element) != null; } public static Element getIdField(Element element) { for (VariableElement e : getFields(element)) { if (isIdField(e)) { return e; } } return null; } public static String getFieldType(VariableElement variableElement) { TypeName typeName = getFieldClass(variableElement); if (typeName == TypeName.INT || typeName == TypeName.BOOLEAN || typeName == TypeName.BYTE) { return "Int"; } else if (typeName == TypeName.LONG) { return "Long"; } else if (typeName == TypeName.FLOAT) { return "Float"; } else if (typeName == TypeName.DOUBLE) { return "Double"; } else if (ClassName.get(String.class).equals(typeName)) { return "String"; } return ""; } public static String getFieldCast(VariableElement variableElement) { TypeName typeName = getFieldClass(variableElement); if (typeName == TypeName.BOOLEAN) { return "(1 == %s)"; } return "%s"; } public static String getFieldTableType(Element variableElement) { TypeName typeName = getFieldClass(variableElement); if (typeName == TypeName.INT || typeName == TypeName.BOOLEAN || typeName == TypeName.LONG || typeName == TypeName.BYTE) { return "integer"; } if (typeName == TypeName.FLOAT) { return "real"; } else if (ClassName.get(String.class).equals(typeName) || isDate(typeName)) { return "text"; } return null; } public static String getObjectName(Element element) { return element.getSimpleName().toString(); } public static boolean isIdField(Element element) { return element.getAnnotation(Id.class) != null && TypeName.LONG.equals(TypeName.get(element.asType())); } public static String getObjectPackage(Element element) { return element.getEnclosingElement().toString(); } public static TypeName getCursorHelper(Element element) { return ClassName.get(getObjectPackage(element), getCursorHelperName(getObjectName(element))); } public static String getCursorHelperName(String objectName) { return objectName + Constants.CURSOR_HELPER_SUFFIX; } public static String getQueryBuilderName(String modelName) { return modelName + Constants.QUERY_BUILDER_SUFFIX; } public static TypeName getQueryBuilder(Element element) { return ClassName.get(getObjectPackage(element), getObjectName(element) + Constants.QUERY_BUILDER_SUFFIX); } public static String getModelDaoName(Element element) { return getModelDaoName(getObjectName(element)); } public static String getModelDaoName(String modelName) { return modelName + Constants.DAO_SUFFIX; } public static ClassName getModelDao(Element element) { return ClassName.get(getObjectPackage(element), getModelDaoName(element)); } public static ParameterizedTypeName listOf(TypeName type) { return ParameterizedTypeName.get(ClassName.get(List.class), type); } public static ParameterizedTypeName listOf(Element element) { return ParameterizedTypeName.get(ClassName.get(List.class), getFieldClass(element)); } public static ParameterizedTypeName listOf(Class classe) { return ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get(classe)); } public static ParameterizedTypeName arraylistOf(TypeName type) { return ParameterizedTypeName.get(ClassName.get(ArrayList.class), type); } public static ParameterizedTypeName arraylistOf(Class classe) { return ParameterizedTypeName.get(ClassName.get(ArrayList.class), ClassName.get(classe)); } public static boolean isPrimitive(Element element) { return isPrimitive(TypeName.get(element.asType())); } public static boolean isModelId(VariableElement variableElement) { return Constants.FIELD_ID.equals(variableElement.getSimpleName().toString()); } public static TypeName unbox(TypeName typeName) { try { return typeName.unbox(); } catch (Exception e) { return typeName; } } public static boolean isPrimitive(TypeName typeName) { return typeName.isPrimitive() || unbox(typeName).isPrimitive() || (ClassName.get(String.class).equals(typeName)) || isDate(typeName); } public static boolean isCollectionOfPrimitive(Element element) { return isCollection(element) && isPrimitive(getFieldClass(element)); } public static String getQueryCast(VariableElement variableElement) { TypeName typeName = getFieldClass(variableElement); if (ClassName.get(String.class).equals(typeName)) { return "$L"; } else if (typeName == TypeName.BOOLEAN || typeName.equals(TypeName.get(Boolean.class))) { return "String.valueOf($L ? 1 : 0)"; } else { return "String.valueOf($L)"; } } public static String getKeyName(VariableElement variableElement) { return getKeyName(getFieldClassName(variableElement)); } public static String getKeyName(String modelName) { return modelName.toLowerCase() + "_id"; } public static String getTableName(String elementName) { return elementName.toUpperCase(); } public static String getTableName(Element element) { return getTableName(getFieldClassName(element)); } public static List<TypeName> getParameters(Element element) { try { return ((ParameterizedTypeName) ParameterizedTypeName.get(element.asType())).typeArguments; } catch (Exception e) { return null; } } public static TypeName getEnclosedTypeName(Element element) { List<TypeName> parameters = getParameters(element); if (parameters == null || parameters.isEmpty()) { return null; } else { return parameters.get(0); } } public static TypeName getFieldCursorHelperClass(VariableElement element) { return ClassName.bestGuess(getFieldClass(element).toString() + Constants.CURSOR_HELPER_SUFFIX); } public static TypeName getFieldQueryBuilderClass(VariableElement element) { return ClassName.bestGuess(getFieldClass(element).toString() + Constants.QUERY_BUILDER_SUFFIX); } public static TypeName getFieldClass(Element element) { if (isArray(element)) { TypeName typeName = getArrayEnclosedType(element); return unbox(typeName); } else { TypeName enclosed = unbox(getEnclosedTypeName(element)); if (enclosed != null) { return enclosed; } else { return unbox(TypeName.get(element.asType())); } } } public static String getFieldClassName(Element element) { String name; TypeName t = getFieldClass(element); if (t instanceof ClassName) { ClassName className = (ClassName) t; name = className.simpleName(); } else { name = t.toString(); } return name; } public static boolean isArray(Element element) { try { return getArrayEnclosedType(element) != null; } catch (Exception e) { return false; } } public static TypeName getArrayEnclosedType(Element element) { return ((ArrayTypeName) ArrayTypeName.get(element.asType())).componentType; } public static boolean isCollection(Element element) { return isArray(element) || getEnclosedTypeName(element) != null; } public static String getMethodId(MethodSpec methodSpec) { return methodSpec.name + methodSpec.parameters.toString(); } public static TypeName getElementEnumColumn(Element element) { return ClassName.bestGuess(getFieldClass(element).toString() + Constants.ENUM_COLUMN_SUFFIX); } public static String getModelId(Element element, String elementVarialbe, String idVariableName) { StringBuilder stringBuilder = new StringBuilder(); Element idField = getIdField(element); if (idField != null) { stringBuilder.append("java.lang.Long ") .append(idVariableName) .append(" = ") .append(elementVarialbe) .append(".") .append(getObjectName(idField)); } else { stringBuilder.append("java.lang.Long ").append(idVariableName).append(" = "); stringBuilder.append(elementVarialbe) .append(" instanceof ") .append(Constants.entityProxyClassString) .append(" ? "); stringBuilder.append( String.format("((%s.%s)%s).%s()", Constants.DAO_PACKAGE, Constants.MODEL_ENTITY_PROXY_INTERFACE, elementVarialbe, Constants.MODEL_ENTITY_PROXY_GET_ID_METHOD)); stringBuilder.append(": null"); } return stringBuilder.toString(); } public static String setModelId(String variable) { return String.format("((%s.%s)%s).%s", Constants.DAO_PACKAGE, Constants.MODEL_ENTITY_PROXY_INTERFACE, variable, Constants.MODEL_ENTITY_PROXY_SET_ID_METHOD); } public static TypeName getModelProxy(Element element) { return ClassName.get(getObjectPackage(element), getObjectName(element) + Constants.MODEL_ENTITY_PROXY); } public static String getPrimitiveCursorHelperFunction(Element element) { TypeName typeName = getFieldClass(element); if (isArray(element)) { if (getArrayEnclosedType(element).isPrimitive()) { if (ClassName.get(String.class).equals(typeName)) { return "getStringsPrimitiveArray"; } else if (TypeName.INT.equals(typeName)) { return "getIntegersPrimitiveArray"; } else if (TypeName.LONG.equals(typeName)) { return "getLongsPrimitiveArray"; } else if (TypeName.FLOAT.equals(typeName)) { return "getFloatsPrimitiveArray"; } else if (TypeName.DOUBLE.equals(typeName)) { return "getDoublesPrimitiveArray"; } else if (TypeName.BOOLEAN.equals(typeName)) { return "getBooleansPrimitiveArray"; } } else { if (ClassName.get(String.class).equals(typeName)) { return "getStringsArray"; } else if (TypeName.INT.equals(typeName)) { return "getIntegersArray"; } else if (TypeName.LONG.equals(typeName)) { return "getLongsArray"; } else if (TypeName.FLOAT.equals(typeName)) { return "getFloatsArray"; } else if (TypeName.DOUBLE.equals(typeName)) { return "getDoublesArray"; } else if (TypeName.BOOLEAN.equals(typeName)) { return "getBooleansArray"; } } } else { if (ClassName.get(String.class).equals(typeName)) { return "getStrings"; } else if (TypeName.INT.equals(typeName)) { return "getIntegers"; } else if (TypeName.LONG.equals(typeName)) { return "getLongs"; } else if (TypeName.FLOAT.equals(typeName)) { return "getFloats"; } else if (TypeName.DOUBLE.equals(typeName)) { return "getDoubles"; } else if (TypeName.BOOLEAN.equals(typeName)) { return "getBooleans"; } } return null; } public static String addPrimitiveCursorHelperFunction(Element element) { TypeName typeName = getFieldClass(element); if (ClassName.get(String.class).equals(typeName)) { return "addStrings"; } else if (TypeName.INT.equals(typeName)) { return "addIntegers"; } else if (TypeName.LONG.equals(typeName)) { return "addLongs"; } else if (TypeName.FLOAT.equals(typeName)) { return "addFloats"; } else if (TypeName.DOUBLE.equals(typeName)) { return "addDoubles"; } else if (TypeName.BOOLEAN.equals(typeName)) { return "addBooleans"; } return null; } public static ClassName getSelectorName(Element element) { TypeName typeName = getFieldClass(element); if (isCollection(element)) { if (TypeName.INT.equals(typeName) || TypeName.LONG.equals(typeName) || TypeName.FLOAT.equals(typeName)) { return Constants.queryBuilder_ListNumberSelectorClassName; } if (TypeName.BOOLEAN.equals(typeName)) { return Constants.queryBuilder_ListBooleanSelectorClassName; } if (TypeName.get(String.class).equals(typeName)) { return Constants.queryBuilder_ListStringSelectorClassName; } } else { if (TypeName.INT.equals(typeName) || TypeName.LONG.equals(typeName) || TypeName.FLOAT.equals(typeName)) { return Constants.queryBuilder_NumberSelectorClassName; } if (TypeName.BOOLEAN.equals(typeName)) { return Constants.queryBuilder_BooleanSelectorClassName; } if (TypeName.get(String.class).equals(typeName)) { return Constants.queryBuilder_StringSelectorClassName; } if (isDate(typeName)) { return Constants.queryBuilder_DateSelectorClassName; } } return null; } public static TypeName getUnboxedClass(Element element) { TypeName typeName = getFieldClass(element); if (TypeName.INT.equals(typeName)) { return TypeName.get(Integer.class); } if (TypeName.LONG.equals(typeName)) { return TypeName.get(Long.class); } if (TypeName.FLOAT.equals(typeName)) { return TypeName.get(Float.class); } if (TypeName.DOUBLE.equals(typeName)) { return TypeName.get(Double.class); } if (TypeName.BOOLEAN.equals(typeName)) { return TypeName.get(Boolean.class); } if (TypeName.get(String.class).equals(typeName)) { return typeName; } return null; } public static boolean isDate(Element element) { return isDate(getFieldClass(element)); } public static boolean isDate(TypeName typeName) { return Constants.dateClassName.equals(typeName); } protected static List<String> getMethodsNames(TypeSpec typeSpec) { List<String> names = new ArrayList<>(); for (MethodSpec methodSpec : typeSpec.methodSpecs) { names.add(methodSpec.name + methodSpec.parameters.toString()); } return names; } public static TypeName observableOf(TypeName typeName){ return ParameterizedTypeName.get(Constants.RX_OBSERVABLE, typeName); } public static TypeName observableSourceOf(TypeName typeName){ return ParameterizedTypeName.get(Constants.RX_OBSERVABLE_SOURCE, typeName); } public static TypeName functionOf(TypeName...typeName){ return ParameterizedTypeName.get(Constants.RX_FUNCTION, typeName); } }