/* * The MIT License (MIT) * * Copyright (c) 2015 baoyongzhang <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.baoyz.airdata.creator; import com.baoyz.airdata.ColumnInfo; import com.baoyz.airdata.ContentValuesWrapper; import com.baoyz.airdata.CursorWrapper; import com.baoyz.airdata.TableInfo; import com.baoyz.airdata.utils.DataType; import com.baoyz.airdata.utils.LogUtils; import com.squareup.javapoet.ArrayTypeName; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; import javax.annotation.processing.Filer; import javax.lang.model.element.Modifier; /** * AirData * Created by baoyz on 15/7/6. */ public class DAOCreator { private TableInfo table; private Filer filer; private ClassName beanClassName; public DAOCreator(TableInfo table, Filer filer) { this.table = table; this.filer = filer; beanClassName = ClassName.get(table.getPackageName(), table.getClassName()); } public void create() { MethodSpec constructor = MethodSpec.constructorBuilder() .addModifiers(Modifier.PUBLIC) .addParameter(ClassName.get("android.database.sqlite", "SQLiteDatabase"), "db") .addStatement("this.$L = $L", "database", "db") .build(); String qualifiedName = table.getQualifiedName(); String packageName = qualifiedName .substring(0, qualifiedName.lastIndexOf(".")); String className = qualifiedName.substring(packageName.length() + 1) + "$$DAO"; FieldSpec tableNameField = FieldSpec .builder(ClassName.get(String.class), "TABLE_NAME", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .initializer("$S", table.getName()).build(); TypeSpec typeSpec = TypeSpec.classBuilder(className) .addModifiers(Modifier.PUBLIC) .addMethod(constructor) .addMethod(generatorInsertMethod(beanClassName)) .addMethod(generatorUpdateAllMethod(beanClassName)) .addMethod(generatorUpdateMethod()) .addMethod(generatorDeleteMethod()) .addMethod(generatorDeleteByIdMethod(beanClassName)) .addMethod(generatorQueryMethod()) .addMethod(generatorFillDataMethod()) .addMethod(generatorQueryAllMethod()) .addMethod(generatorRawQueryMethod()) .addField(tableNameField) .addField(ClassName.get("android.database.sqlite", "SQLiteDatabase"), "database", Modifier.PRIVATE) .build(); JavaFile javaFile = JavaFile.builder(table.getPackageName(), typeSpec) .build(); try { javaFile.writeTo(filer); } catch (Exception e) { e.printStackTrace(); } LogUtils.debug(javaFile.toString()); } private MethodSpec generatorInsertMethod(ClassName person) { MethodSpec.Builder insertBuilder = MethodSpec.methodBuilder("insert") .addModifiers(Modifier.PUBLIC) .returns(TypeName.LONG) .addParameter(person, "bean") .addStatement("$T values = new $T()", ClassName.get("android.content", "ContentValues"), ClassName.get("android.content", "ContentValues")) .addStatement("$T valuesWrapper = $T.wrap(values)", ClassName.get(ContentValuesWrapper.class), ClassName.get(ContentValuesWrapper.class)); List<ColumnInfo> columns = table.getColumns(); for (ColumnInfo column : columns) { if (column.isPrimaryKey() || !DataType.isSupport(column.getTypeMirror())) continue; insertBuilder.addStatement("valuesWrapper.put($S, bean.$L)", column.getName(), column.getGetter()); } insertBuilder.addStatement("return database.insert(TABLE_NAME, null, values)"); return insertBuilder.build(); } private MethodSpec generatorUpdateAllMethod(ClassName person) { MethodSpec.Builder updateBuilder = MethodSpec.methodBuilder("update") .addModifiers(Modifier.PUBLIC) .returns(TypeName.INT) .addParameter(person, "bean") .addStatement("$T values = new $T()", ClassName.get("android.content", "ContentValues"), ClassName.get("android.content", "ContentValues")) .addStatement("$T valuesWrapper = $T.wrap(values)", ClassName.get(ContentValuesWrapper.class), ClassName.get(ContentValuesWrapper.class)); List<ColumnInfo> columns = table.getColumns(); for (ColumnInfo column : columns) { if (column.isPrimaryKey() || !DataType.isSupport(column.getTypeMirror())) continue; updateBuilder.addStatement("valuesWrapper.put($S, bean.$L)", column.getName(), column.getGetter()); } updateBuilder.addStatement("return this.update(valuesWrapper, $S, new String[]{String.valueOf(bean.$L)})", table.getPrimaryKeyColumn().getName() + "=?", table.getPrimaryKeyColumn().getGetter()); return updateBuilder.build(); } private MethodSpec generatorUpdateMethod() { MethodSpec.Builder updateBuilder = MethodSpec.methodBuilder("update") .addModifiers(Modifier.PUBLIC) .returns(TypeName.INT) .addParameter(ClassName.get(ContentValuesWrapper.class), "valuesWrapper") .addParameter(ClassName.get(String.class), "where") .addParameter(ArrayTypeName.of(ClassName.get(String.class)), "whereArgs"); updateBuilder.addStatement("return database.update(TABLE_NAME, valuesWrapper.getValues(), where, whereArgs)"); return updateBuilder.build(); } private MethodSpec generatorDeleteByIdMethod(ClassName person) { MethodSpec.Builder insertBuilder = MethodSpec.methodBuilder("delete") .addModifiers(Modifier.PUBLIC) .returns(TypeName.INT) .addParameter(person, "bean") .addStatement("return this.delete($S, new String[]{String.valueOf(bean.$L)})", table.getPrimaryKeyColumn().getName() + "=?", table.getPrimaryKeyColumn().getGetter()); return insertBuilder.build(); } private MethodSpec generatorDeleteMethod() { MethodSpec.Builder insertBuilder = MethodSpec.methodBuilder("delete") .addModifiers(Modifier.PUBLIC) .returns(TypeName.INT) .addParameter(ClassName.get(String.class), "where") .addParameter(ArrayTypeName.of(ClassName.get(String.class)), "whereArgs") .addStatement("return database.delete(TABLE_NAME, where, whereArgs)"); return insertBuilder.build(); } private MethodSpec generatorQueryAllMethod() { MethodSpec.Builder queryBuilder = MethodSpec.methodBuilder("queryAll") .addModifiers(Modifier.PUBLIC) .returns(ClassName.get(List.class)) .addStatement("return this.query(false, null, null, null, null, null, null, null)"); return queryBuilder.build(); } /* boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit */ private MethodSpec generatorQueryMethod() { MethodSpec.Builder queryBuilder = MethodSpec.methodBuilder("query") .addModifiers(Modifier.PUBLIC) .returns(ClassName.get(List.class)) .addParameter(TypeName.BOOLEAN, "distinct") .addParameter(ArrayTypeName.of(ClassName.get(String.class)), "columns") .addParameter(ClassName.get(String.class), "selection") .addParameter(ArrayTypeName.of(ClassName.get(String.class)), "selectionArgs") .addParameter(ClassName.get(String.class), "groupBy") .addParameter(ClassName.get(String.class), "having") .addParameter(ClassName.get(String.class), "orderBy") .addParameter(ClassName.get(String.class), "limit") .addStatement("$T cursor = this.rawQuery(distinct, columns, selection, selectionArgs, groupBy, having, orderBy, limit)", ClassName.get("android.database", "Cursor")); queryBuilder.addStatement("$T list = new $T()", ArrayList.class, ArrayList.class); queryBuilder.addCode("if (cursor.moveToFirst()) {"); queryBuilder.addCode(" do {"); queryBuilder.addCode(" list.add(fillData(cursor));"); queryBuilder.addCode(" } while (cursor.moveToNext());"); queryBuilder.addCode("}"); queryBuilder.addStatement("return list"); return queryBuilder.build(); } private MethodSpec generatorRawQueryMethod() { MethodSpec.Builder queryBuilder = MethodSpec.methodBuilder("rawQuery") .addModifiers(Modifier.PUBLIC) .returns(ClassName.get("android.database", "Cursor")) .addParameter(TypeName.BOOLEAN, "distinct") .addParameter(ArrayTypeName.of(ClassName.get(String.class)), "columns") .addParameter(ClassName.get(String.class), "selection") .addParameter(ArrayTypeName.of(ClassName.get(String.class)), "selectionArgs") .addParameter(ClassName.get(String.class), "groupBy") .addParameter(ClassName.get(String.class), "having") .addParameter(ClassName.get(String.class), "orderBy") .addParameter(ClassName.get(String.class), "limit") .addStatement("return database.query(distinct, TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy, limit)"); return queryBuilder.build(); } private MethodSpec generatorFillDataMethod() { MethodSpec.Builder fillDataMethod = MethodSpec.methodBuilder("fillData") .addModifiers(Modifier.PUBLIC) .addParameter(ClassName.get("android.database", "Cursor"), "cursor") .returns(beanClassName) .addStatement("$T bean = new $T()", beanClassName, beanClassName) .addStatement("$T cursorWrapper = $T.wrap(cursor)", ClassName.get(CursorWrapper.class), ClassName.get(CursorWrapper.class)); List<ColumnInfo> columns = table.getColumns(); for (int i = 0; i < columns.size(); i++) { ColumnInfo column = columns.get(i); String cursorMethod = DataType.getCursorMethod(column.getTypeMirror()); if (cursorMethod == null) continue; fillDataMethod.addStatement("bean." + column.getSetter(), "cursorWrapper." + cursorMethod + "(" + i + ")"); } fillDataMethod.addStatement("return bean"); return fillDataMethod.build(); } }