package com.github.florent37.rxandroidorm.generator; import com.github.florent37.rxandroidorm.Constants; import com.github.florent37.rxandroidorm.ProcessUtils; 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.HashSet; import java.util.List; import java.util.Set; import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; import io.reactivex.ObservableEmitter; /** * Created by florentchampigny on 08/01/2016. */ public class ModelORMGenerator { private final Element element; String modelName; String modelPackage; TypeName modelClassName; TypeName modelCursorHelperClassName; TypeName queryBuilderClassName; TypeName enumColums; String TABLE_NAME; TypeSpec queryBuilder; TypeSpec dao; Element fieldId; List<VariableElement> fields; List<VariableElement> otherClassFields; List<VariableElement> collections; public ModelORMGenerator(Element element) { this.element = element; this.modelName = ProcessUtils.getObjectName(element); this.modelPackage = ProcessUtils.getObjectPackage(element); this.modelClassName = TypeName.get(element.asType()); this.modelCursorHelperClassName = ProcessUtils.getCursorHelper(element); this.TABLE_NAME = ProcessUtils.getTableName(element); this.queryBuilderClassName = ProcessUtils.getQueryBuilder(element); this.enumColums = ProcessUtils.getElementEnumColumn(element); this.fields = ProcessUtils.getPrimitiveFields(element); this.otherClassFields = ProcessUtils.getNonPrimitiveClassFields(element); this.collections = ProcessUtils.getCollectionsOfPrimitiveFields(element); this.fieldId = ProcessUtils.getIdField(element); } public TypeSpec getDao() { return dao; } public TypeSpec getQueryBuilder() { return queryBuilder; } public ModelORMGenerator generate() { TypeName listObjectsClassName = ProcessUtils.listOf(modelClassName); this.queryBuilder = TypeSpec.classBuilder(ProcessUtils.getQueryBuilderName(modelName)) //UserQueryBuilder .addModifiers(Modifier.PUBLIC) .superclass(Constants.queryBuilderClassName) .addField(ProcessUtils.listOf(enumColums), "fields") .addMethod(MethodSpec.constructorBuilder() .addModifiers(Modifier.PUBLIC) .addStatement("super()") .build()) .addMethod(MethodSpec.constructorBuilder() .addModifiers(Modifier.PUBLIC) .addParameter(TypeName.BOOLEAN, "named") .addParameter(ClassName.get(Constants.DAO_PACKAGE, Constants.QUERY_LOGGER), "logger") .addStatement("this()") .addStatement("this.named = named") .addStatement("this.logger = logger") .build()) .addMethods(generateQueryMethods()) .addMethod(MethodSpec.methodBuilder("or") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addStatement("super.appendOr()") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("and") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addStatement("super.appendAnd()") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("beginGroup") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addStatement("super.appendBeginGroup()") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("endGroup") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addStatement("super.appendEndGroup()") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("limit") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(TypeName.INT, "start") .addParameter(TypeName.INT, "count") .addStatement("super.limitStartNumber(start, count)") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("asList") .returns(listObjectsClassName) .addModifiers(Modifier.PRIVATE) .addStatement("return execute()") .build()) .addMethod(MethodSpec.methodBuilder("asObservable") .returns(ProcessUtils.observableOf(listObjectsClassName)) .addModifiers(Modifier.PUBLIC) .addCode("return $T.create(new $T<$T>(){\n", Constants.RX_OBSERVABLE, Constants.RX_OBSERVABLE_ON_SUBSCRIBE, listObjectsClassName) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public void subscribe($T<$T> subscriber) {\n", ClassName.get(ObservableEmitter.class), listObjectsClassName) .addStatement("subscriber.onNext(asList())") .addStatement("subscriber.onComplete()") .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("first") .returns(ProcessUtils.observableOf(modelClassName)) .addModifiers(Modifier.PUBLIC) .addCode("return $T.create(new $T<$T>(){\n", Constants.RX_OBSERVABLE, Constants.RX_OBSERVABLE_ON_SUBSCRIBE, modelClassName) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public void subscribe($T<$T> subscriber) {\n", ClassName.get(ObservableEmitter.class), modelClassName) .addStatement("$T objects = asList()", listObjectsClassName) .addStatement("if(objects.isEmpty()) subscriber.onError(new Exception($S))", "empty") .addStatement("else subscriber.onNext(objects.get(0))") .addStatement("subscriber.onComplete()") .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("sortAsc") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(enumColums, "column") .addStatement("super.appendSortAsc($S,column.getName())", " " + TABLE_NAME + " .") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("sortDesc") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(enumColums, "column") .addStatement("super.appendSortDesc($S,column.getName())", " " + TABLE_NAME + " .") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("sum") .returns(TypeName.FLOAT) .addParameter(enumColums, "column") .addModifiers(Modifier.PUBLIC) .addStatement("$T db = $T.getInstance().open().getDatabase()", Constants.databaseClassName, Constants.daoClassName) .addStatement("$T cursor = db.rawQuery($S + column.getName() + $S + constructQuery(), constructArgs())", Constants.cursorClassName, String.format("select sum(%s.", TABLE_NAME), String.format(") from %s ", TABLE_NAME)) .addStatement("cursor.moveToNext()") .addStatement("float value = cursor.getFloat(0)") .addStatement("cursor.close()") .addStatement("$T.getInstance().close()", Constants.daoClassName) .addStatement("return value") .build()) .addMethod(MethodSpec.methodBuilder("min") .returns(TypeName.FLOAT) .addParameter(enumColums, "column") .addModifiers(Modifier.PUBLIC) .addStatement("$T db = $T.getInstance().open().getDatabase()", Constants.databaseClassName, Constants.daoClassName) .addStatement("$T cursor = db.rawQuery($S + column.getName() + $S + constructQuery(), constructArgs())", Constants.cursorClassName, String.format("select min(%s.", TABLE_NAME), String.format(") from %s ", TABLE_NAME)) .addStatement("cursor.moveToNext()") .addStatement("float value = cursor.getFloat(0)") .addStatement("cursor.close()") .addStatement("$T.getInstance().close()", Constants.daoClassName) .addStatement("return value") .build()) .addMethod(MethodSpec.methodBuilder("max") .returns(TypeName.FLOAT) .addParameter(enumColums, "column") .addModifiers(Modifier.PUBLIC) .addStatement("$T db = $T.getInstance().open().getDatabase()", Constants.databaseClassName, Constants.daoClassName) .addStatement("$T cursor = db.rawQuery($S + column.getName() + $S + constructQuery(), constructArgs())", Constants.cursorClassName, String.format("select max(%s.", TABLE_NAME), String.format(") from %s ", TABLE_NAME)) .addStatement("cursor.moveToNext()") .addStatement("float value = cursor.getFloat(0)") .addStatement("cursor.close()") .addStatement("$T.getInstance().close()", Constants.daoClassName) .addStatement("return value") .build()) .addMethod(MethodSpec.methodBuilder("average") .returns(TypeName.FLOAT) .addParameter(enumColums, "column") .addModifiers(Modifier.PUBLIC) .addStatement("$T db = $T.getInstance().open().getDatabase()", Constants.databaseClassName, Constants.daoClassName) .addStatement("$T cursor = db.rawQuery($S + column.getName() + $S + constructQuery(), constructArgs())", Constants.cursorClassName, String.format("select avg(%s.", TABLE_NAME), String.format(") from %s ", TABLE_NAME)) .addStatement("cursor.moveToNext()") .addStatement("float value = cursor.getFloat(0)") .addStatement("cursor.close()") .addStatement("$T.getInstance().close()", Constants.daoClassName) .addStatement("return value") .build()) .addMethod(MethodSpec.methodBuilder("count") .returns(TypeName.INT) .addModifiers(Modifier.PUBLIC) .addStatement("$T db = $T.getInstance().open().getDatabase()", Constants.databaseClassName, Constants.daoClassName) .addStatement("$T cursor = db.rawQuery($S + constructQuery(), constructArgs())", Constants.cursorClassName, String.format("select count(distinct(%s.%s)) from %s ", TABLE_NAME, Constants.FIELD_ID, TABLE_NAME)) .addStatement("cursor.moveToNext()") .addStatement("int value = cursor.getInt(0)") .addStatement("cursor.close()") .addStatement("$T.getInstance().close()", Constants.daoClassName) .addStatement("return value") .build()) .addMethod(MethodSpec.methodBuilder("fields") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(ArrayTypeName.of(enumColums), "fields") .varargs() .addStatement("this.fields = new $T<>()", TypeName.get(ArrayList.class)) .addStatement("this.fields.addAll($T.asList(fields))", TypeName.get(Arrays.class)) .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("fieldsWithout") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(ArrayTypeName.of(enumColums), "fields") .varargs() .addStatement("this.fields = new $T<>($T.asList($L.values()))", TypeName.get(ArrayList.class), TypeName.get(Arrays.class), enumColums) .addStatement("this.fields.removeAll($T.asList(fields))", TypeName.get(Arrays.class)) .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("field") .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(enumColums, "field") .addStatement("return this") .build()) .addMethod(MethodSpec.methodBuilder("execute") .returns(listObjectsClassName) .addModifiers(Modifier.PRIVATE) .addStatement("$T db = $T.getInstance().open().getDatabase()", Constants.databaseClassName, Constants.daoClassName) .addStatement("$T stringBuilder = new $T()", Constants.stringBuilderClassName, Constants.stringBuilderClassName) .addStatement("stringBuilder.append($S)", "select distinct ") .addStatement("if(fields == null) stringBuilder.append(\"$L.* \")", TABLE_NAME) .beginControlFlow("else") .addStatement("stringBuilder.append($S)", TABLE_NAME + "." + Constants.FIELD_ID) .addStatement("final int fieldsSize = fields.size()") .beginControlFlow("for(int i=0;i<fieldsSize;++i)") .addStatement("$T c = fields.get(i)", enumColums) .beginControlFlow("if(c.isPrimitive())") .addStatement("stringBuilder.append($S)", ", ") .addStatement("stringBuilder.append($S+fields.get(i))", TABLE_NAME + ".") .endControlFlow() .endControlFlow() .endControlFlow() .addStatement("stringBuilder.append($S)", String.format(" from %s ", TABLE_NAME)) .addStatement("stringBuilder.append(constructQuery())") .addStatement("$T query = stringBuilder.toString()", ClassName.get(String.class)) .addStatement("String[] args = constructArgs()") .addStatement("if(logger != null) logger.onQuery(query,args)") .addStatement("$T cursor = db.rawQuery(query, args)", Constants.cursorClassName) .addStatement("$T objects = $T.get(cursor,db)", listObjectsClassName, modelCursorHelperClassName) .addStatement("cursor.close()") .addStatement("$T.getInstance().close()", Constants.daoClassName) .addStatement("return objects") .build()) .build(); this.dao = TypeSpec.classBuilder(ProcessUtils.getModelDaoName(modelName)) //UserDatabase .addSuperinterface(ParameterizedTypeName.get((ClassName) Constants.databaseCommonInterfaceClassName, modelClassName)) .addModifiers(Modifier.PUBLIC) .addField(ClassName.get(Constants.DAO_PACKAGE, Constants.QUERY_LOGGER), "logger") .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).build()) .addMethod(MethodSpec.methodBuilder("create") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(ArrayTypeName.get(String[].class)) //for .addStatement("return new $T[]{$L}", ClassName.get(String.class), generateCreationString()) .build()) .addMethod(MethodSpec.methodBuilder("update") .returns(ClassName.get(String.class)) .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addStatement("return $S", "") .build()) //.addMethod(MethodSpec.methodBuilder("drop") // .addModifiers(Modifier.PUBLIC, Modifier.STATIC) // .returns(ArrayTypeName.get(String[].class)) // //for // .addStatement("return new $T[]{$L}", ClassName.get(String.class), generateDropString()) // .build()) .addMethod(MethodSpec.methodBuilder("select") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .returns(queryBuilderClassName) .addStatement("return new $T(false,logger)", queryBuilderClassName) .build()) .addMethod(MethodSpec.methodBuilder("where") .addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.STATIC) .returns(queryBuilderClassName) .addStatement("return new $T(true,null)", queryBuilderClassName) .build()) .addMethod(MethodSpec.methodBuilder("add") .addAnnotation(Override.class) .addParameter(modelClassName, "object", Modifier.FINAL) .returns(ProcessUtils.observableOf(modelClassName)) .addModifiers(Modifier.PUBLIC) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, modelClassName) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(modelClassName), Constants.databaseClassName) .addStatement("\tlong objectId = $T.insert(database,object)", modelCursorHelperClassName) .addStatement("\treturn $T.just(object)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("add") .addAnnotation(Override.class) .returns(ProcessUtils.observableOf(listObjectsClassName)) .addParameter(listObjectsClassName, "objects", Modifier.FINAL) .addModifiers(Modifier.PUBLIC) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, listObjectsClassName) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(listObjectsClassName), Constants.databaseClassName) .addStatement("database.beginTransaction()") .addStatement("for($T object : objects) $T.insert(database, object)", modelClassName, modelCursorHelperClassName) .addStatement("database.setTransactionSuccessful()") .addStatement("database.endTransaction()") .addStatement("\treturn $T.just(objects)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("update") .addAnnotation(Override.class) .addParameter(modelClassName, "object", Modifier.FINAL) .returns(ProcessUtils.observableOf(modelClassName)) .addModifiers(Modifier.PUBLIC) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, modelClassName) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(modelClassName), Constants.databaseClassName) .addStatement("\tlong objectId = $T.update(database,object)", modelCursorHelperClassName) .addStatement("\treturn $T.just(object)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("update") .addAnnotation(Override.class) .returns(ProcessUtils.observableOf(listObjectsClassName)) .addParameter(listObjectsClassName, "objects", Modifier.FINAL) .addModifiers(Modifier.PUBLIC) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, listObjectsClassName) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(listObjectsClassName), Constants.databaseClassName) .addStatement("database.beginTransaction()") .addStatement("for($T object : objects) $T.update(database, object)", modelClassName, modelCursorHelperClassName) .addStatement("database.setTransactionSuccessful()") .addStatement("database.endTransaction()") .addStatement("\treturn $T.just(objects)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("exists") .addParameter(Constants.databaseClassName, "db") .addParameter(modelClassName, "object", Modifier.FINAL) .addModifiers(Modifier.PUBLIC) .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box())) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, TypeName.BOOLEAN.box()) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(TypeName.BOOLEAN.box()), Constants.databaseClassName) .addStatement(ProcessUtils.getModelId(element, "object", "id")) .addStatement("\treturn $T.just(id != null)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("delete") .addParameter(Constants.databaseClassName, "db") .addParameter(modelClassName, "object", Modifier.FINAL) .addModifiers(Modifier.PRIVATE) .returns(TypeName.VOID) .addStatement(ProcessUtils.getModelId(element, "object", "id")) .addStatement("db.delete($S, $S, new String[]{String.valueOf(id)})", TABLE_NAME, "_id = ?") .build()) .addMethod(MethodSpec.methodBuilder("delete") .addAnnotation(Override.class) .addParameter(modelClassName, "object", Modifier.FINAL) .addModifiers(Modifier.PUBLIC) .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box())) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, TypeName.BOOLEAN.box()) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(TypeName.BOOLEAN.box()), Constants.databaseClassName) .addStatement("delete(database,object)") .addStatement("return $T.just(true)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("delete") .addAnnotation(Override.class) .addParameter(listObjectsClassName, "objects", Modifier.FINAL) .addModifiers(Modifier.PUBLIC) .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box())) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, TypeName.BOOLEAN.box()) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(TypeName.BOOLEAN.box()), Constants.databaseClassName) .beginControlFlow("for($T object : objects)", modelClassName) .addStatement("delete(database,object)") .endControlFlow() .addStatement("return $T.just(true)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("deleteAll") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .returns(ProcessUtils.observableOf(TypeName.BOOLEAN.box())) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, TypeName.BOOLEAN.box()) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(TypeName.BOOLEAN.box()), Constants.databaseClassName) .addStatement("database.execSQL($S)", "delete from " + TABLE_NAME) .addStatement("return $T.just(true)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("count") .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC) .returns(ProcessUtils.observableOf(TypeName.INT.box())) .addCode("return $T.getInstance().database()\n", Constants.daoClassName) .addCode(".flatMap(new $T<$T,$T<$T>>() {\n", Constants.RX_FUNCTION, Constants.databaseClassName, Constants.RX_OBSERVABLE_SOURCE, TypeName.INT.box()) .addCode("@$T\n", ClassName.get(Override.class)) .addCode("public $T apply($T database) throws Exception {\n", ProcessUtils.observableSourceOf(TypeName.INT.box()), Constants.databaseClassName) .addStatement("$T cursor = database.rawQuery($S,null)", Constants.cursorClassName, "select count(*) from " + TABLE_NAME) .addStatement("cursor.moveToFirst()") .addStatement("int recCount = cursor.getInt(0)") .addStatement("cursor.close()") .addStatement("return $T.just(recCount)", Constants.RX_OBSERVABLE) .addCode("}\n") .addCode("});\n") .build()) .addMethod(MethodSpec.methodBuilder("logQueries") .addModifiers(Modifier.PUBLIC) .addParameter(ClassName.get(Constants.DAO_PACKAGE, Constants.QUERY_LOGGER), "logger") .addStatement("this.logger = logger") .build()) .build(); return this; } protected List<MethodSpec> generateQueryMethods() { List<MethodSpec> methodSpecs = new ArrayList<>(); for (VariableElement variableElement : fields) { ClassName className = ProcessUtils.getSelectorName(variableElement); if (className != null) { TypeName selector = null; if (className == Constants.queryBuilder_NumberSelectorClassName) { selector = ParameterizedTypeName.get(className, queryBuilderClassName, ProcessUtils.getUnboxedClass(variableElement)); } else { selector = ParameterizedTypeName.get(className, queryBuilderClassName); } methodSpecs.add(MethodSpec.methodBuilder(variableElement.getSimpleName().toString()) .returns(selector) .addModifiers(Modifier.PUBLIC) .addStatement("return new $T(this, $T.$L.getName())", selector, enumColums, variableElement.getSimpleName()) .build()); } } for (VariableElement variableElement : collections) { ClassName className = ProcessUtils.getSelectorName(variableElement); if (className != null) { TypeName selector = null; if (className == Constants.queryBuilder_ListNumberSelectorClassName) { selector = ParameterizedTypeName.get(className, queryBuilderClassName, ProcessUtils.getUnboxedClass(variableElement)); } else { selector = ParameterizedTypeName.get(className, queryBuilderClassName); } methodSpecs.add(MethodSpec.methodBuilder(variableElement.getSimpleName().toString()) .returns(selector) .addModifiers(Modifier.PUBLIC) .addStatement("return new $T(this, $T.$L.getName())", selector, enumColums, variableElement.getSimpleName()) .build()); } } for (VariableElement variableElement : otherClassFields) { String JOINTABLE = ProcessUtils.getTableName(modelName) + "_" + ProcessUtils.getTableName(variableElement); methodSpecs.add(MethodSpec.methodBuilder(variableElement.getSimpleName().toString()) .returns(queryBuilderClassName) .addModifiers(Modifier.PUBLIC) .addParameter(ProcessUtils.getFieldQueryBuilderClass(variableElement), "query") .addStatement("queryBuilder.append('(').append(query.query($S,getTableId($S),$S,$S,getTableId($S),$S,args)).append(')')", TABLE_NAME, JOINTABLE, ProcessUtils.getKeyName(modelName), ProcessUtils.getKeyName(variableElement), ProcessUtils.getTableName(variableElement), ProcessUtils.getObjectName(variableElement)) .addStatement("return this") .build()); } return methodSpecs; } protected String generateCreationString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append('"').append("create table ").append(TABLE_NAME).append(" (_id integer primary key autoincrement, ").append(generateTableCreate()).append(")").append('"'); Set<String> addedTables = new HashSet<>(); for (VariableElement variableElement : otherClassFields) { String table = TABLE_NAME + "_" + ProcessUtils.getTableName(variableElement); if (!addedTables.contains(table)) { stringBuilder .append(",\n") .append('"') .append("create table ").append(table) .append(" ( _id integer primary key autoincrement, ") .append(ProcessUtils.getKeyName(modelName)).append(" integer, ") .append(ProcessUtils.getKeyName(variableElement)).append(" integer, ") .append(Constants.FIELD_NAME).append(" text )") .append('"'); addedTables.add(table); } } return stringBuilder.toString(); } //protected String generateDropString() { // StringBuilder stringBuilder = new StringBuilder(); // stringBuilder.append('"').append("drop table ").append(TABLE_NAME).append(")").append('"'); // Set<String> dropTables = new HashSet<>(); // for (VariableElement variableElement : otherClassFields) { // String table = TABLE_NAME + "_" + ProcessUtils.getTableName(variableElement); // if (!dropTables.contains(table)) { // stringBuilder // .append(",\n") // .append('"') // .append("drop table ").append(table) // .append('"'); // dropTables.add(table); // } // } // return stringBuilder.toString(); //} protected String generateTableCreate() { StringBuilder stringBuilder = new StringBuilder(); //filter / remove fieldId List<Element> elements = new ArrayList<>(); for (VariableElement variableElement : fields) { if (variableElement != fieldId) { elements.add(variableElement); } } for (int i = 0; i < elements.size(); ++i) { Element variableElement = elements.get(i); if (!Constants.FIELD_ID.equals(variableElement.getSimpleName().toString())) { stringBuilder .append(variableElement.getSimpleName()) .append(" ") .append(ProcessUtils.getFieldTableType(variableElement)); if (i < elements.size() - 1) { stringBuilder.append(", "); } } } return stringBuilder.toString(); } }