From d0145b64f89cea4bd88f35f70429c6c572d3be75 Mon Sep 17 00:00:00 2001 From: Rostyslav Lesovyi Date: Thu, 20 Dec 2018 15:07:52 +0200 Subject: [PATCH] - added scheme builder --- .../matrix/roomigrant/compiler/Database.kt | 81 +++++++++++++++---- .../matrix/roomigrant/compiler/Migration.kt | 8 +- .../matrix/roomigrant/compiler/Processor.kt | 3 + .../matrix/roomigrant/compiler/data/Index.kt | 8 +- .../matrix/roomigrant/compiler/data/Table.kt | 5 +- .../compiler/rules/RulesProviderField.kt | 8 +- .../matrix/roomigrant/compiler/utils/Utils.kt | 7 ++ .../dev/matrix/roomigrant/model/IndexInfo.kt | 9 +++ .../dev/matrix/roomigrant/model/SchemeInfo.kt | 8 ++ .../dev/matrix/roomigrant/model/TableInfo.kt | 10 +++ 10 files changed, 116 insertions(+), 31 deletions(-) create mode 100644 RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/utils/Utils.kt create mode 100644 RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/IndexInfo.kt create mode 100644 RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/SchemeInfo.kt create mode 100644 RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/TableInfo.kt diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Database.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Database.kt index 1c851f8..d101547 100644 --- a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Database.kt +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Database.kt @@ -3,6 +3,9 @@ package dev.matrix.roomigrant.compiler import com.squareup.kotlinpoet.* import dev.matrix.roomigrant.compiler.data.Scheme import dev.matrix.roomigrant.compiler.rules.Rules +import dev.matrix.roomigrant.model.IndexInfo +import dev.matrix.roomigrant.model.SchemeInfo +import dev.matrix.roomigrant.model.TableInfo import javax.annotation.processing.ProcessingEnvironment import javax.lang.model.element.TypeElement import javax.tools.StandardLocation @@ -10,7 +13,7 @@ import javax.tools.StandardLocation /** * @author matrixdev */ -@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") +@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "FunctionName") class Database(val environment: ProcessingEnvironment, element: TypeElement) { val migrationType = ClassName("android.arch.persistence.room.migration", "Migration") @@ -23,37 +26,85 @@ class Database(val environment: ProcessingEnvironment, element: TypeElement) { val migrationListClassName = ClassName(packageName, "${elementClassName}_Migrations") val rules = Rules(this, element) + val schemes = ArrayList() val migrations = ArrayList() + fun addScheme(scheme: Scheme) { + schemes.add(scheme) + } + fun addMigration(database1: Scheme, database2: Scheme): Migration { return Migration(this, database1, database2).also { migrations.add(it) } } fun generate() { - // migration class val typeSpec = TypeSpec.objectBuilder(migrationListClassName) + .addProperties(generate_rules()) + .addFunction(generate_build()) + .addFunction(generate_buildScheme()) - // "rules" fields - for (holder in rules.getProvidersFields()) { - typeSpec.addProperty(holder.propertySpec) - } + val fileSpec = FileSpec.builder(packageName, migrationListClassName.simpleName()) + .addType(typeSpec.build()) + .build() - // "build" function + environment.filer.createResource(StandardLocation.SOURCE_OUTPUT, packageName, "${migrationListClassName.simpleName()}.kt") + .openWriter() + .use { fileSpec.writeTo(it) } + } + + private fun generate_rules() = rules.getProvidersFields().map { + PropertySpec.builder(it.name, it.type) + .initializer("%T()", it.type) + .build() + } + + private fun generate_build(): FunSpec { val funcSpec = FunSpec.builder("build").addStatement("val list = %T()", migrationListType) for (migration in migrations) { funcSpec.addStatement("list.add(%T)", migration.className) } funcSpec.returns(migrationArrayType).addStatement("return list.toTypedArray()") - typeSpec.addFunction(funcSpec.build()) + return funcSpec.build() + } - // writing to file - val fileSpec = FileSpec.builder(packageName, migrationListClassName.simpleName()) - .addType(typeSpec.build()) - .build() + private fun generate_buildScheme(): FunSpec { + val code = FunSpec.builder("buildScheme") + .returns(ParameterizedTypeName.get(Map::class, Int::class, SchemeInfo::class)) - environment.filer.createResource(StandardLocation.SOURCE_OUTPUT, packageName, "${migrationListClassName.simpleName()}.kt") - .openWriter() - .use { fileSpec.writeTo(it) } + var varIndex = 0 + fun generateVarName() = "var${++varIndex}" + + val schemesVar = generateVarName() + val schemesType = ParameterizedTypeName.get(HashMap::class, Int::class, SchemeInfo::class) + code.addStatement("val %L = %T()", schemesVar, schemesType) + + for (scheme in schemes) { + val tablesVar = generateVarName() + val tablesType = ParameterizedTypeName.get(HashMap::class, String::class, TableInfo::class) + code.addStatement("val %L = %T()", tablesVar, tablesType) + + val schemeVar = generateVarName() + code.addStatement("val %L = %T(%L, %L)", schemeVar, SchemeInfo::class, scheme.version, tablesVar) + code.addStatement("%L.put(%L, %L)", schemesVar, scheme.version, schemeVar) + + for (table in scheme.tables) { + val indicesVar = generateVarName() + val indicesType = ParameterizedTypeName.get(HashMap::class, String::class, IndexInfo::class) + code.addStatement("val %L = %T()", indicesVar, indicesType) + + val tableVar = generateVarName() + code.addStatement("val %L = %T(%L, %S, %S, %L)", tableVar, TableInfo::class, schemeVar, table.name, table.createSql(), indicesVar) + code.addStatement("%L.put(%S, %L)", tablesVar, table.name, tableVar) + + for (index in table.indices) { + code.addStatement("%L.put(%S, %T(%L, %S, %S))", indicesVar, index.name, IndexInfo::class, tableVar, index.name, index.createSql(table.name)) + } + } + } + + code.addStatement("return %L", schemesVar) + + return code.build() } } diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Migration.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Migration.kt index 16d9720..938c35e 100644 --- a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Migration.kt +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Migration.kt @@ -58,9 +58,7 @@ class Migration( fun generate() { state.environment.filer.createResource(StandardLocation.SOURCE_OUTPUT, state.packageName, "${className.simpleName()}.kt") .openWriter() - .use { - fileSpec.writeTo(it) - } + .use { fileSpec.writeTo(it) } } private fun migrate() { @@ -168,7 +166,7 @@ class Migration( } private fun createTable(table: Table) { - execSql(table.createSql.replace("\${TABLE_NAME}", table.name)) + execSql(table.createSql(table.name)) } private fun dropTableIndex(index: Index) { @@ -180,6 +178,6 @@ class Migration( } private fun createTableIndex(table: Table, index: Index) { - execSql(index.createSql.replace("\${TABLE_NAME}", table.name)) + execSql(index.createSql(table.name)) } } \ No newline at end of file diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Processor.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Processor.kt index ae9f3cc..19d357c 100644 --- a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Processor.kt +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/Processor.kt @@ -39,6 +39,9 @@ class Processor : AbstractProcessor() { val schemes = folder.listFiles().mapNotNull { readScheme(it) }.sortedBy { it.version } val database = Database(processingEnv, element) + for (scheme in schemes) { + database.addScheme(scheme) + } for (index in 1 until schemes.size) { database.addMigration(schemes[index - 1], schemes[index]).generate() } diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Index.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Index.kt index c20b63d..f12ee0e 100644 --- a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Index.kt +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Index.kt @@ -13,7 +13,11 @@ data class Index( val unique: Boolean, @SerializedName("createSql") - val createSql: String, + val createSqlTemplate: String, @SerializedName("columnNames") - val columns: List) \ No newline at end of file + val columns: List) { + + fun createSql(tableName: String) = createSqlTemplate.replace("\${TABLE_NAME}", tableName) + +} \ No newline at end of file diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Table.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Table.kt index 4ffb469..9bac8b1 100644 --- a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Table.kt +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/data/Table.kt @@ -10,7 +10,7 @@ data class Table( val name: String, @SerializedName("createSql") - val createSql: String, + val createSqlTemplate: String, @SerializedName("primaryKey") val primaryKey: PrimaryKey, @@ -22,10 +22,11 @@ data class Table( val indices: List) { val fieldsMap by lazy { fields.associateBy { it.name } } + fun createSql(tableName: String = name) = createSqlTemplate.replace("\${TABLE_NAME}", tableName) constructor(table: Table, name: String) : this( name = name, - createSql = table.createSql, + createSqlTemplate = table.createSqlTemplate, primaryKey = table.primaryKey, fields = table.fields, indices = table.indices) diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/rules/RulesProviderField.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/rules/RulesProviderField.kt index c1b3745..01eb458 100644 --- a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/rules/RulesProviderField.kt +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/rules/RulesProviderField.kt @@ -1,6 +1,5 @@ package dev.matrix.roomigrant.compiler.rules -import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeName import dev.matrix.roomigrant.compiler.Database @@ -10,9 +9,4 @@ import dev.matrix.roomigrant.compiler.Database data class RulesProviderField( val database: Database, val name: String, - val type: TypeName) { - - val propertySpec = PropertySpec.builder(name, type) - .initializer("%T()", type) - .build() -} + val type: TypeName) diff --git a/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/utils/Utils.kt b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/utils/Utils.kt new file mode 100644 index 0000000..813b33c --- /dev/null +++ b/RoomigrantCompiler/src/main/java/dev/matrix/roomigrant/compiler/utils/Utils.kt @@ -0,0 +1,7 @@ +package dev.matrix.roomigrant.compiler.utils + +/** + * @author matrixdev + */ + +fun String.asVarName() = "`$this`" \ No newline at end of file diff --git a/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/IndexInfo.kt b/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/IndexInfo.kt new file mode 100644 index 0000000..be495dd --- /dev/null +++ b/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/IndexInfo.kt @@ -0,0 +1,9 @@ +package dev.matrix.roomigrant.model + +/** + * @author matrixdev + */ +data class IndexInfo( + val table: TableInfo, + val name: String, + val createSql: String) diff --git a/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/SchemeInfo.kt b/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/SchemeInfo.kt new file mode 100644 index 0000000..fda5ef1 --- /dev/null +++ b/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/SchemeInfo.kt @@ -0,0 +1,8 @@ +package dev.matrix.roomigrant.model + +/** + * @author matrixdev + */ +data class SchemeInfo( + val version: Int, + val tables: Map) diff --git a/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/TableInfo.kt b/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/TableInfo.kt new file mode 100644 index 0000000..81984ab --- /dev/null +++ b/RoomigrantLib/src/main/java/dev/matrix/roomigrant/model/TableInfo.kt @@ -0,0 +1,10 @@ +package dev.matrix.roomigrant.model + +/** + * @author matrixdev + */ +data class TableInfo( + val scheme: SchemeInfo, + val name: String, + val createSql: String, + val indices: Map)