Skip to content

Commit

Permalink
Merge pull request #12 from MatrixDev/bugfix/buildScheme-64kb-limit
Browse files Browse the repository at this point in the history
fixed issue #9
  • Loading branch information
MatrixDev authored Sep 21, 2020
2 parents dbf1cf0 + d65582b commit f6afcfc
Showing 1 changed file with 103 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,102 +17,113 @@ import javax.tools.StandardLocation
@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "FunctionName", "DEPRECATION")
class Database(val environment: ProcessingEnvironment, element: TypeElement) {

val migrationType = ClassName("android.arch.persistence.room.migration", "Migration")
val sqLiteDatabaseType = ClassName("android.arch.persistence.db", "SupportSQLiteDatabase")
val migrationListType = ArrayList::class.asClassName().parameterizedBy(migrationType)
val migrationArrayType = ClassName("kotlin", "Array").parameterizedBy(migrationType)

val packageName = element.asClassName().packageName
val elementClassName = element.asClassName().simpleName
val migrationListClassName = ClassName(packageName, "${elementClassName}_Migrations")

val rules = Rules(this, element)
val schemes = ArrayList<Scheme>()
val migrations = ArrayList<Migration>()

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() {
val typeSpec = TypeSpec.objectBuilder(migrationListClassName)
.addProperties(generate_rules())
.addFunction(generate_build())
.addFunction(generate_buildScheme())

val fileSpec = FileSpec.builder(packageName, migrationListClassName.simpleName)
.addType(typeSpec.build())
.build()

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()")
return funcSpec.build()
}

private fun generate_buildScheme(): FunSpec {
val code = FunSpec.builder("buildScheme")
.returns(Map::class.parameterizedBy(Int::class, SchemeInfo::class))

var varIndex = 0

val schemesVar = "schemes"
val schemesType = HashMap::class.parameterizedBy(Int::class, SchemeInfo::class)
code.addStatement("val %L = %T()", schemesVar, schemesType)

val schemeVar = "scheme"
val schemeType = SchemeInfo::class
code.addStatement("var %L: %T", schemeVar, schemeType)

val tablesVar = "tables"
val tablesType = HashMap::class.parameterizedBy(String::class, TableInfo::class)
code.addStatement("var %L: %T", tablesVar, tablesType)

val tableVar = "table"
val tableType = TableInfo::class
code.addStatement("var %L: %T", tableVar, tableType)

val indicesVar = "indices"
val indicesType = HashMap::class.parameterizedBy(String::class, IndexInfo::class)
code.addStatement("var %L: %T", indicesVar, indicesType)

for (scheme in schemes) {
code.addStatement("%L = %T()", tablesVar, tablesType)
code.addStatement("%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) {
code.addStatement("%L = %T()", indicesVar, indicesType)
code.addStatement("%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))
}
val migrationType = ClassName("android.arch.persistence.room.migration", "Migration")
val sqLiteDatabaseType = ClassName("android.arch.persistence.db", "SupportSQLiteDatabase")
val migrationListType = ArrayList::class.asClassName().parameterizedBy(migrationType)
val migrationArrayType = ClassName("kotlin", "Array").parameterizedBy(migrationType)

val packageName = element.asClassName().packageName
val elementClassName = element.asClassName().simpleName
val migrationListClassName = ClassName(packageName, "${elementClassName}_Migrations")

val rules = Rules(this, element)
val schemes = ArrayList<Scheme>()
val migrations = ArrayList<Migration>()

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() {
val typeSpec = TypeSpec.objectBuilder(migrationListClassName)
.addProperties(generate_rules())
.addFunction(generate_build())
.addFunction(generate_buildScheme())

for (scheme in schemes) {
typeSpec.addFunction(generate_buildSchemeInfo(scheme))
}

val fileSpec = FileSpec.builder(packageName, migrationListClassName.simpleName)
.addType(typeSpec.build())
.build()

val fileName = "${migrationListClassName.simpleName}.kt"
environment.filer.createResource(StandardLocation.SOURCE_OUTPUT, packageName, fileName)
.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()")
return funcSpec.build()
}

private fun generate_buildScheme(): FunSpec {
val code = FunSpec.builder("buildScheme")
.returns(Map::class.parameterizedBy(Int::class, SchemeInfo::class))

val schemesMap = "schemesMap"
val schemesType = HashMap::class.parameterizedBy(Int::class, SchemeInfo::class)
code.addStatement("val %L = %T()", schemesMap, schemesType)

for (scheme in schemes) {
val funName = "buildSchemeInfo_${scheme.version}"
code.addStatement("%L.put(%L, %L())", schemesMap, scheme.version, funName)
}

code.addStatement("return %L", schemesMap)

return code.build()
}

private fun generate_buildSchemeInfo(scheme: Scheme): FunSpec {
val code = FunSpec.builder("buildSchemeInfo_${scheme.version}")
.addModifiers(KModifier.PRIVATE)
.returns(SchemeInfo::class)

val tablesMap = "tables"
val tablesType = HashMap::class.parameterizedBy(String::class, TableInfo::class)
code.addStatement("val %L = %T()", tablesMap, tablesType)

val schemeInfo = "schemeInfo"
code.addStatement("val %L = %T(%L, %L)", schemeInfo, SchemeInfo::class, scheme.version, tablesMap)

code.addStatement("")

for (table in scheme.tables) {
val tableInfo = "tableInfo_${table.name}"
val indices = "indices_${table.name}"

val indicesType = HashMap::class.parameterizedBy(String::class, IndexInfo::class)
code.addStatement("val %L = %T()", indices, indicesType)
code.addStatement("")

code.addStatement("val %L = %T(%L, %S, %S, %L)", tableInfo, TableInfo::class, schemeInfo, table.name, table.createSql(), indices)
code.addStatement("%L.put(%S, %L)", tablesMap, table.name, tableInfo)
code.addStatement("")

for (index in table.indices) {
code.addStatement("%L.put(%S, %T(%L, %S, %S))", indices, index.name, IndexInfo::class, tableInfo, index.name, index.createSql(table.name))
}
}

code.addStatement("return %L", schemesVar)
code.addStatement("return %L", schemeInfo)

return code.build()
}

}

0 comments on commit f6afcfc

Please sign in to comment.