Skip to content

Commit

Permalink
- added scheme builder
Browse files Browse the repository at this point in the history
  • Loading branch information
MatrixDev committed Dec 20, 2018
1 parent be53b2d commit d0145b6
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ 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

/**
* @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")
Expand All @@ -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<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() {
// 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()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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) {
Expand All @@ -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))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ data class Index(
val unique: Boolean,

@SerializedName("createSql")
val createSql: String,
val createSqlTemplate: String,

@SerializedName("columnNames")
val columns: List<String>)
val columns: List<String>) {

fun createSql(tableName: String) = createSqlTemplate.replace("\${TABLE_NAME}", tableName)

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ data class Table(
val name: String,

@SerializedName("createSql")
val createSql: String,
val createSqlTemplate: String,

@SerializedName("primaryKey")
val primaryKey: PrimaryKey,
Expand All @@ -22,10 +22,11 @@ data class Table(
val indices: List<Index>) {

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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.matrix.roomigrant.compiler.utils

/**
* @author matrixdev
*/

fun String.asVarName() = "`$this`"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package dev.matrix.roomigrant.model

/**
* @author matrixdev
*/
data class IndexInfo(
val table: TableInfo,
val name: String,
val createSql: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.matrix.roomigrant.model

/**
* @author matrixdev
*/
data class SchemeInfo(
val version: Int,
val tables: Map<String, TableInfo>)
Original file line number Diff line number Diff line change
@@ -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<String, IndexInfo>)

0 comments on commit d0145b6

Please sign in to comment.