From e1666dd5b4c145ad0d88e2cc2d872dfc770c8d65 Mon Sep 17 00:00:00 2001 From: geralt-encore Date: Mon, 23 Oct 2017 15:56:48 +0300 Subject: [PATCH 1/2] Initial implementation --- build.gradle | 2 +- .../annotations/processor/Extensions.kt | 14 +++ .../processor/StorIOAnnotationsProcessor.kt | 4 + .../processor/introspection/JavaType.kt | 18 ++++ .../processor/introspection/StorIOTypeMeta.kt | 6 +- .../StorIOContentResolverProcessor.kt | 2 + .../StorIOContentResolverTypeMeta.kt | 6 +- .../processor/StorIOSQLiteProcessor.kt | 7 +- .../processor/generate/TableGenerator.kt | 99 +++++++++++++++++++ .../introspection/StorIOSQLiteTypeMeta.kt | 6 +- .../annotations/StorIOSQLiteColumn.java | 50 ++++++---- .../sqlite/annotations/StorIOSQLiteType.java | 19 ++-- 12 files changed, 199 insertions(+), 34 deletions(-) create mode 100644 storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt diff --git a/build.gradle b/build.gradle index 0e1a09284..b04ba76e0 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ import org.gradle.internal.jvm.Jvm // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.1.3-2' + ext.kotlin_version = '1.1.51' repositories { jcenter() } diff --git a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt index 3c4a56311..197b7b0f2 100644 --- a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt +++ b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt @@ -2,3 +2,17 @@ package com.pushtorefresh.storio2.common.annotations.processor fun String.startsWithIs(): Boolean = this.startsWith("is") && this.length > 2 && Character.isUpperCase(this[2]) + +fun String.toUpperCaseSnakeCase(): String { + val builder = StringBuilder() + + this.forEachIndexed { index, char -> + when { + char.isDigit() -> builder.append("_$char") + char.isUpperCase() -> if (index == 0) builder.append(char) else builder.append("_$char") + char.isLowerCase() -> builder.append(char.toUpperCase()) + } + } + + return builder.toString() +} diff --git a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/StorIOAnnotationsProcessor.kt b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/StorIOAnnotationsProcessor.kt index e79f20f78..84c42da7a 100644 --- a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/StorIOAnnotationsProcessor.kt +++ b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/StorIOAnnotationsProcessor.kt @@ -221,12 +221,14 @@ abstract class StorIOAnnotationsProcessor, out C val getResolverGenerator = createGetResolver() val deleteResolverGenerator = createDeleteResolver() val mappingGenerator = createMapping() + val tableGenerator = createTableGenerator() annotatedClasses.values.forEach { putResolverGenerator.generateJavaFile(it).writeTo(filer) getResolverGenerator.generateJavaFile(it).writeTo(filer) deleteResolverGenerator.generateJavaFile(it).writeTo(filer) mappingGenerator.generateJavaFile(it).writeTo(filer) + if (it.generateTableClass) tableGenerator?.generateJavaFile(it)?.writeTo(filer) } } catch (e: ProcessingException) { messager.printMessage(ERROR, e.message, e.element) @@ -290,4 +292,6 @@ abstract class StorIOAnnotationsProcessor, out C protected abstract fun createDeleteResolver(): Generator protected abstract fun createMapping(): Generator + + protected abstract fun createTableGenerator(): Generator? } diff --git a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/JavaType.kt b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/JavaType.kt index b891b365f..8a01925c3 100644 --- a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/JavaType.kt +++ b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/JavaType.kt @@ -51,4 +51,22 @@ enum class JavaType { } } } + + val sqliteType: String + get() = when (this) { + BOOLEAN, + BOOLEAN_OBJECT, + SHORT, + SHORT_OBJECT, + INTEGER, + INTEGER_OBJECT, + LONG, + LONG_OBJECT -> "INTEGER" + FLOAT, + FLOAT_OBJECT, + DOUBLE, + DOUBLE_OBJECT -> "REAL" + STRING -> "TEXT" + BYTE_ARRAY -> "BLOB" + } } \ No newline at end of file diff --git a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMeta.kt b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMeta.kt index d2b418149..02d5a409d 100644 --- a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMeta.kt +++ b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMeta.kt @@ -2,7 +2,7 @@ package com.pushtorefresh.storio2.common.annotations.processor.introspection import javax.lang.model.element.ExecutableElement -open class StorIOTypeMeta> +abstract class StorIOTypeMeta> @JvmOverloads constructor( val simpleName: String, val packageName: String, @@ -22,7 +22,7 @@ open class StorIOTypeMeta().apply { - (0..columns.size - 1).forEach { add(null) } + (0 until columns.size).forEach { add(null) } } columns.values.forEach { orderedColumns[params.indexOf(it.realElementName)] = it } orderedColumns.map { it as ColumnMeta } @@ -44,6 +44,8 @@ open class StorIOTypeMeta = DeleteResolverGenerator override fun createMapping(): Generator = MappingGenerator + + override fun createTableGenerator(): Generator? = null } \ No newline at end of file diff --git a/storio-content-resolver-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/contentresolver/annotations/processor/introspection/StorIOContentResolverTypeMeta.kt b/storio-content-resolver-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/contentresolver/annotations/processor/introspection/StorIOContentResolverTypeMeta.kt index 59af47a5f..2acf948e3 100644 --- a/storio-content-resolver-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/contentresolver/annotations/processor/introspection/StorIOContentResolverTypeMeta.kt +++ b/storio-content-resolver-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/contentresolver/annotations/processor/introspection/StorIOContentResolverTypeMeta.kt @@ -12,4 +12,8 @@ class StorIOContentResolverTypeMeta( simpleName, packageName, storIOType, - needsCreator) \ No newline at end of file + needsCreator) { + + override val generateTableClass: Boolean + get() = false +} \ No newline at end of file diff --git a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/StorIOSQLiteProcessor.kt b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/StorIOSQLiteProcessor.kt index 8b3283afa..899226c84 100644 --- a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/StorIOSQLiteProcessor.kt +++ b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/StorIOSQLiteProcessor.kt @@ -8,10 +8,7 @@ import com.pushtorefresh.storio2.common.annotations.processor.introspection.Java import com.pushtorefresh.storio2.sqlite.annotations.StorIOSQLiteColumn import com.pushtorefresh.storio2.sqlite.annotations.StorIOSQLiteCreator import com.pushtorefresh.storio2.sqlite.annotations.StorIOSQLiteType -import com.pushtorefresh.storio2.sqlite.annotations.processor.generate.DeleteResolverGenerator -import com.pushtorefresh.storio2.sqlite.annotations.processor.generate.GetResolverGenerator -import com.pushtorefresh.storio2.sqlite.annotations.processor.generate.MappingGenerator -import com.pushtorefresh.storio2.sqlite.annotations.processor.generate.PutResolverGenerator +import com.pushtorefresh.storio2.sqlite.annotations.processor.generate.* import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteCreatorMeta import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteTypeMeta @@ -217,4 +214,6 @@ open class StorIOSQLiteProcessor : StorIOAnnotationsProcessor = DeleteResolverGenerator override fun createMapping(): Generator = MappingGenerator + + override fun createTableGenerator(): Generator = TableGenerator } diff --git a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt new file mode 100644 index 000000000..e58a5606b --- /dev/null +++ b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt @@ -0,0 +1,99 @@ +package com.pushtorefresh.storio2.sqlite.annotations.processor.generate + +import com.pushtorefresh.storio2.common.annotations.processor.generate.Common.INDENT +import com.pushtorefresh.storio2.common.annotations.processor.generate.Generator +import com.pushtorefresh.storio2.common.annotations.processor.toUpperCaseSnakeCase +import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta +import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteTypeMeta +import com.squareup.javapoet.* +import javax.lang.model.element.Modifier.* + +private const val ANDROID_NON_NULL_ANNOTATION = "android.support.annotation.NonNull" +private const val DB_PARAM = "db" +private const val OLD_VERSION_PARAM = "oldVersion" + +object TableGenerator : Generator { + + private val sqliteDatabase = ClassName.get("android.database.sqlite", "SQLiteDatabase") + + override fun generateJavaFile(typeMeta: StorIOSQLiteTypeMeta): JavaFile { + val tableSpec = TypeSpec.classBuilder("${typeMeta.simpleName}Table") + .addModifiers(PUBLIC, FINAL) + .addMethod(generatePrivateConstructor()) + .addFields(generateFields(typeMeta.storIOType.table, typeMeta.columns.values)) + .addMethod(generateCreateMethod(typeMeta.storIOType.table, typeMeta.columns.values)) + .addMethod(generateUpdateMethod(typeMeta.storIOType.table, typeMeta.columns.values)) + .build() + + return JavaFile.builder(typeMeta.packageName, tableSpec) + .indent(INDENT) + .build() + } + + private fun generateFields(table: String, columns: Collection): Iterable { + val list = mutableListOf() + + list += FieldSpec.builder(String::class.java, "NAME") + .initializer("\$S", table) + .addModifiers(PUBLIC, STATIC, FINAL) + .build() + + columns.forEach { column -> + list += FieldSpec.builder(String::class.java, "${column.elementName.toUpperCaseSnakeCase()}_COLUMN") + .initializer("\$S", column.storIOColumn.name) + .addModifiers(PUBLIC, STATIC, FINAL) + .build() + } + + return list + } + + private fun generateCreateMethod(table: String, columns: Collection): MethodSpec { + val builder = StringBuilder() + + builder.append("CREATE TABLE $table (") + + columns.forEachIndexed { index, column -> + builder.append("${column.storIOColumn.name} ${column.javaType.sqliteType}") + if (column.isNotNull()) builder.append(" NOT NULL") + if (column.storIOColumn.key) builder.append(" PRIMARY KEY") + if (index != columns.size - 1) builder.append(".\n") + } + + builder.append(");") + + return MethodSpec.methodBuilder("createTable") + .addModifiers(PUBLIC, STATIC) + .addParameter(ParameterSpec.builder(sqliteDatabase, DB_PARAM).build()) + .addStatement("$DB_PARAM.execSQL(\$S)", builder.toString()) + .build() + } + + private fun generateUpdateMethod(table: String, columns: Collection): MethodSpec { + val builder = MethodSpec.methodBuilder("updateTable") + .addModifiers(PUBLIC, STATIC) + .addParameter(ParameterSpec.builder(sqliteDatabase, DB_PARAM).build()) + .addParameter(ParameterSpec.builder(TypeName.INT, OLD_VERSION_PARAM).build()) + + val columnsToUpdate = columns + .filter { it.storIOColumn.version > 1 } + .sortedBy { it.storIOColumn.version } + + columnsToUpdate.forEach { column -> + builder.beginControlFlow("if ($OLD_VERSION_PARAM < ${column.storIOColumn.version})") + builder.addCode("$DB_PARAM.execSQL(ALTER TABLE $table ADD COLUMN ${column.storIOColumn.name} ${column.javaType.sqliteType}) ${if (column.isNotNull()) "NOT NULL" else ""});") + builder.endControlFlow() + } + + return builder.build() + } + + private fun generatePrivateConstructor() = MethodSpec.constructorBuilder().addModifiers(PRIVATE).build() + + private fun StorIOSQLiteColumnMeta.isNotNull(): Boolean { + this.element.annotationMirrors.forEach { + if (it.annotationType.toString() == ANDROID_NON_NULL_ANNOTATION) return true + } + return false + } +} \ No newline at end of file diff --git a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/introspection/StorIOSQLiteTypeMeta.kt b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/introspection/StorIOSQLiteTypeMeta.kt index 0c5f73279..5baf0dc1d 100644 --- a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/introspection/StorIOSQLiteTypeMeta.kt +++ b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/introspection/StorIOSQLiteTypeMeta.kt @@ -12,4 +12,8 @@ class StorIOSQLiteTypeMeta( simpleName, packageName, storIOType, - needsCreator) \ No newline at end of file + needsCreator) { + + override val generateTableClass: Boolean + get() = storIOType.generateTableClass +} \ No newline at end of file diff --git a/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteColumn.java b/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteColumn.java index b6766b580..2c1f28f21 100644 --- a/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteColumn.java +++ b/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteColumn.java @@ -14,25 +14,37 @@ @Retention(RUNTIME) // we allow users to write reflection based code to work with annotation public @interface StorIOSQLiteColumn { - /** - * Required: specifies column name - * - * @return non-null column name - */ - String name(); + /** + * Required: specifies column name + * + * @return non-null column name + */ + String name(); - /** - * Optional: marks column as key, so it will be used to identify rows for Put and Delete Operations - * - * @return true if column is key, false otherwise - */ - boolean key() default false; + /** + * Optional: marks column as key, so it will be used to identify rows for Put and Delete + * Operations + * + * @return true if column is key, false otherwise + */ + boolean key() default false; - /** - * Optional: indicates that field should not be serialized when its value is {@code null} - * Should be used for not primitive types only - * - * @return true if column with {@code null} value should be ignored, false otherwise - */ - boolean ignoreNull() default false; + /** + * Optional: indicates that field should not be serialized when its value is {@code null} + * Should be used for not primitive types only + * + * @return true if column with {@code null} value should be ignored, false otherwise + */ + boolean ignoreNull() default false; + + /** + * Optional: Indicates database version when a column was added. It is used for generation of + * CREATE_TABLE and UPDATE_TABLE SQL statements. If version is 1 (default value) then the code + * for creating a column will be generated in createTable method. Otherwise, it will be + * generated in updateTable method only for databases which versions are lower than + * specified for this fiels. + * + * @return version of database when a column was added. + */ + int version() default 1; } diff --git a/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteType.java b/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteType.java index b1e739c66..276486f91 100644 --- a/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteType.java +++ b/storio-sqlite-annotations/src/main/java/com/pushtorefresh/storio2/sqlite/annotations/StorIOSQLiteType.java @@ -13,10 +13,17 @@ @Retention(RUNTIME) // we allow users to write reflection based code to work with annotation public @interface StorIOSQLiteType { - /** - * Required: Specifies table name - * - * @return table name - */ - String table(); + /** + * Required: Specifies table name + * + * @return table name + */ + String table(); + + /** + * Flag to opt out from generating table class based on field annotations. + * + * @return flag that shows if table class should be generated or not. + */ + boolean generateTableClass() default true; } From 29699183e0be5454d5e5b507465d7817c64fe942 Mon Sep 17 00:00:00 2001 From: geralt-encore Date: Tue, 24 Oct 2017 12:59:14 +0300 Subject: [PATCH 2/2] Add tests and adjust samples --- .../storio2/basic_sample/DbOpenHelper.java | 4 +- .../storio2/basic_sample/MainActivity.java | 2 +- .../storio2/basic_sample/Tweet.java | 8 +-- .../storio2/basic_sample/TweetQueries.java | 21 ++++++++ .../storio2/basic_sample/TweetsTable.java | 48 ----------------- .../annotations/processor/Extensions.kt | 2 +- .../introspection/StorIOTypeMetaTest.kt | 6 ++- .../storio2/sample/db/DbOpenHelper.java | 4 +- .../storio2/sample/db/entities/Tweet.java | 2 +- .../storio2/sample/db/entities/User.java | 2 +- .../ManyToManyActivity.java | 6 +-- .../many_to_many_sample/entities/Car.java | 6 +-- .../entities/CarTable.java | 30 ----------- .../many_to_many_sample/entities/Person.java | 6 +-- .../entities/PersonTable.java | 30 ----------- .../resolvers/CarRelationsGetResolver.java | 6 +-- .../resolvers/PersonRelationsGetResolver.java | 6 +-- .../StorIOSQLiteAnnotationsProcessorTest.java | 39 +++++++++++--- .../test/resources/WithGeneratedTable.java | 38 +++++++++++++ .../resources/WithGeneratedTableTable.java | 53 +++++++++++++++++++ .../test/resources/WithoutGeneratedTable.java | 31 +++++++++++ .../processor/generate/TableGenerator.kt | 8 +-- 22 files changed, 212 insertions(+), 146 deletions(-) create mode 100644 storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetQueries.java delete mode 100644 storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetsTable.java delete mode 100644 storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/CarTable.java delete mode 100644 storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/PersonTable.java create mode 100644 storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTable.java create mode 100644 storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTableTable.java create mode 100644 storio-sqlite-annotations-processor-test/src/test/resources/WithoutGeneratedTable.java diff --git a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/DbOpenHelper.java b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/DbOpenHelper.java index d3ba39f2d..e9649c270 100644 --- a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/DbOpenHelper.java +++ b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/DbOpenHelper.java @@ -13,11 +13,11 @@ public DbOpenHelper(@NonNull Context context) { @Override public void onCreate(@NonNull SQLiteDatabase db) { - db.execSQL(TweetsTable.getCreateTableQuery()); + TweetTable.createTable(db); } @Override public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) { - // no impl + TweetTable.updateTable(db, oldVersion); } } diff --git a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/MainActivity.java b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/MainActivity.java index 6f590cddf..e9e97974a 100644 --- a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/MainActivity.java +++ b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/MainActivity.java @@ -67,7 +67,7 @@ void addTweets() { List receivedTweets = storIOSQLite .get() .listOfObjects(Tweet.class) - .withQuery(TweetsTable.QUERY_ALL) + .withQuery(TweetQueries.QUERY_ALL) .prepare() .executeAsBlocking(); diff --git a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/Tweet.java b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/Tweet.java index 21ae2193d..bdaddf255 100644 --- a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/Tweet.java +++ b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/Tweet.java @@ -12,22 +12,22 @@ // This annotation will trigger annotation processor // Which will generate type mapping code in compile time, // You just need to link it in your code. -@StorIOSQLiteType(table = TweetsTable.TABLE) +@StorIOSQLiteType(table = "tweets") public class Tweet { /** * If object was not inserted into db, id will be null */ @Nullable - @StorIOSQLiteColumn(name = TweetsTable.COLUMN_ID, key = true) + @StorIOSQLiteColumn(name = "_id", key = true) Long id; @NonNull - @StorIOSQLiteColumn(name = TweetsTable.COLUMN_AUTHOR) + @StorIOSQLiteColumn(name = "author") String author; @NonNull - @StorIOSQLiteColumn(name = TweetsTable.COLUMN_CONTENT) + @StorIOSQLiteColumn(name = "content") String content; // leave default constructor for AutoGenerated code! diff --git a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetQueries.java b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetQueries.java new file mode 100644 index 000000000..9b9731137 --- /dev/null +++ b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetQueries.java @@ -0,0 +1,21 @@ +package com.pushtorefresh.storio2.basic_sample; + +import android.support.annotation.NonNull; + +import com.pushtorefresh.storio2.sqlite.queries.Query; + +// We suggest to store table meta such as table name, columns names, queries, etc in separate class +// Because it makes code of the Entity itself cleaner and easier to read/understand/support +public class TweetQueries { + + // This is just class with Meta Data, we don't need instances + private TweetQueries() { + throw new IllegalStateException("No instances please"); + } + + // Yep, with StorIO you can safely store queries as objects and reuse them, they are immutable + @NonNull + public static final Query QUERY_ALL = Query.builder() + .table(TweetTable.NAME) + .build(); +} diff --git a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetsTable.java b/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetsTable.java deleted file mode 100644 index 59046ba4c..000000000 --- a/storio-basic-sample-app/src/main/java/com/pushtorefresh/storio2/basic_sample/TweetsTable.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.pushtorefresh.storio2.basic_sample; - -import android.support.annotation.NonNull; - -import com.pushtorefresh.storio2.sqlite.queries.Query; - -// We suggest to store table meta such as table name, columns names, queries, etc in separate class -// Because it makes code of the Entity itself cleaner and easier to read/understand/support -public class TweetsTable { - - @NonNull - public static final String TABLE = "tweets"; - - @NonNull - public static final String COLUMN_ID = "_id"; - - /** - * For example: "artem_zin" without "@" - */ - @NonNull - public static final String COLUMN_AUTHOR = "author"; - - /** - * For example: "Check out StorIO — modern API for SQLiteDatabase & ContentResolver #androiddev" - */ - @NonNull - public static final String COLUMN_CONTENT = "content"; - - // Yep, with StorIO you can safely store queries as objects and reuse them, they are immutable - @NonNull - public static final Query QUERY_ALL = Query.builder() - .table(TABLE) - .build(); - - // This is just class with Meta Data, we don't need instances - private TweetsTable() { - throw new IllegalStateException("No instances please"); - } - - @NonNull - public static String getCreateTableQuery() { - return "CREATE TABLE " + TABLE + "(" - + COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY, " - + COLUMN_AUTHOR + " TEXT NOT NULL, " - + COLUMN_CONTENT + " TEXT NOT NULL" - + ");"; - } -} diff --git a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt index 197b7b0f2..2909202ae 100644 --- a/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt +++ b/storio-common-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/common/annotations/processor/Extensions.kt @@ -3,7 +3,7 @@ package com.pushtorefresh.storio2.common.annotations.processor fun String.startsWithIs(): Boolean = this.startsWith("is") && this.length > 2 && Character.isUpperCase(this[2]) -fun String.toUpperCaseSnakeCase(): String { +fun String.toUpperSnakeCase(): String { val builder = StringBuilder() this.forEachIndexed { index, char -> diff --git a/storio-common-annotations-processor/src/test/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMetaTest.kt b/storio-common-annotations-processor/src/test/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMetaTest.kt index af2bf7cd7..b002c2441 100644 --- a/storio-common-annotations-processor/src/test/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMetaTest.kt +++ b/storio-common-annotations-processor/src/test/kotlin/com/pushtorefresh/storio2/common/annotations/processor/introspection/StorIOTypeMetaTest.kt @@ -74,4 +74,8 @@ class StorIOTestTypeMeta(simpleName: String, simpleName, packageName, storIOType, - needCreator) \ No newline at end of file + needCreator) { + + override val generateTableClass: Boolean + get() = false +} \ No newline at end of file diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/DbOpenHelper.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/DbOpenHelper.java index 01706bc59..6ffc274a2 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/DbOpenHelper.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/DbOpenHelper.java @@ -23,8 +23,8 @@ public void onCreate(@NonNull SQLiteDatabase db) { db.execSQL(TweetsTable.getCreateTableQuery()); db.execSQL(UsersTable.getCreateTableQuery()); - db.execSQL(CarTable.getCreateTableQuery()); - db.execSQL(PersonTable.getCreateTableQuery()); + CarTable.createTable(db); + PersonTable.createTable(db); db.execSQL(PersonCarRelationTable.getCreateTableQuery()); db.execSQL(Customer.CREATE_TABLE); diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/Tweet.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/Tweet.java index e203c0b0e..cbff648c6 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/Tweet.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/Tweet.java @@ -16,7 +16,7 @@ // This annotation will trigger annotation processor // Which will generate type mapping code in compile time, // You just need to link it in your code. -@StorIOSQLiteType(table = TweetsTable.TABLE) +@StorIOSQLiteType(table = TweetsTable.TABLE, generateTableClass = false) @StorIOContentResolverType(uri = TweetMeta.URI_STRING) public class Tweet { diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/User.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/User.java index a8aaea1a2..280c9098c 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/User.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/db/entities/User.java @@ -10,7 +10,7 @@ // This annotation will trigger annotation processor // Which will generate type mapping code in compile time, // You just need to link it in your code. -@StorIOSQLiteType(table = UsersTable.TABLE) +@StorIOSQLiteType(table = UsersTable.TABLE, generateTableClass = false) public class User { /** diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/ManyToManyActivity.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/ManyToManyActivity.java index cb7c074b0..a968afd47 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/ManyToManyActivity.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/ManyToManyActivity.java @@ -83,8 +83,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { @NonNull Subscription subscribeToPersonsAndCars() { Set tables = new HashSet(3); - tables.add(PersonTable.TABLE); - tables.add(CarTable.TABLE); + tables.add(PersonTable.NAME); + tables.add(CarTable.NAME); tables.add(PersonCarRelationTable.TABLE); return Observable.merge( storIOSQLite.observeChangesInTables(tables), @@ -95,7 +95,7 @@ Subscription subscribeToPersonsAndCars() { public List call(Changes changes) { return storIOSQLite.get() .listOfObjects(Person.class) - .withQuery(Query.builder().table(PersonTable.TABLE).build()) + .withQuery(Query.builder().table(PersonTable.NAME).build()) .prepare() .executeAsBlocking(); } diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Car.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Car.java index 903fc080c..bd35898c6 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Car.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Car.java @@ -8,14 +8,14 @@ import java.util.List; -@StorIOSQLiteType(table = CarTable.TABLE) +@StorIOSQLiteType(table = "cars") public class Car { - @StorIOSQLiteColumn(key = true, name = CarTable.COLUMN_ID) + @StorIOSQLiteColumn(key = true, name = "_car_id") @Nullable Long id; - @StorIOSQLiteColumn(name = CarTable.COLUMN_MODEL) + @StorIOSQLiteColumn(name = "model") @NonNull String model; diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/CarTable.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/CarTable.java deleted file mode 100644 index 87aed186a..000000000 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/CarTable.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.pushtorefresh.storio2.sample.many_to_many_sample.entities; - -import android.support.annotation.NonNull; - -public class CarTable { - - @NonNull - public static final String TABLE = "cars"; - - @NonNull - public static final String COLUMN_ID = "_car_id"; - - @NonNull - public static final String COLUMN_MODEL = "model"; - - // This is just class with Meta Data, we don't need instances - private CarTable() { - throw new IllegalStateException("No instances please"); - } - - // Better than static final field -> allows VM to unload useless String - // Because you need this string only once per application life on the device - @NonNull - public static String getCreateTableQuery() { - return "CREATE TABLE " + TABLE + "(" - + COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY, " - + COLUMN_MODEL + " TEXT NOT NULL" - + ");"; - } -} diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Person.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Person.java index f64e06d43..5d0bd268b 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Person.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/Person.java @@ -8,14 +8,14 @@ import java.util.List; -@StorIOSQLiteType(table = PersonTable.TABLE) +@StorIOSQLiteType(table = "persons") public class Person { - @StorIOSQLiteColumn(key = true, name = PersonTable.COLUMN_ID) + @StorIOSQLiteColumn(key = true, name = "_person_id") @Nullable Long id; - @StorIOSQLiteColumn(name = PersonTable.COLUMN_NAME) + @StorIOSQLiteColumn(name = "name") @NonNull String name; diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/PersonTable.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/PersonTable.java deleted file mode 100644 index f5efdc7b8..000000000 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/entities/PersonTable.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.pushtorefresh.storio2.sample.many_to_many_sample.entities; - -import android.support.annotation.NonNull; - -public class PersonTable { - - @NonNull - public static final String TABLE = "persons"; - - @NonNull - public static final String COLUMN_ID = "_person_id"; - - @NonNull - public static final String COLUMN_NAME = "name"; - - // This is just class with Meta Data, we don't need instances - private PersonTable() { - throw new IllegalStateException("No instances please"); - } - - // Better than static final field -> allows VM to unload useless String - // Because you need this string only once per application life on the device - @NonNull - public static String getCreateTableQuery() { - return "CREATE TABLE " + TABLE + "(" - + COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY, " - + COLUMN_NAME + " TEXT NOT NULL UNIQUE" - + ");"; - } -} diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/CarRelationsGetResolver.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/CarRelationsGetResolver.java index 1945245ce..a9247cc16 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/CarRelationsGetResolver.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/CarRelationsGetResolver.java @@ -33,10 +33,10 @@ public Car mapFromCursor(@NonNull StorIOSQLite storIOSQLite, @NonNull Cursor cur .listOfObjects(Person.class) .withQuery(RawQuery.builder() .query("SELECT " - + PersonTable.TABLE + ".*" - + " FROM " + PersonTable.TABLE + + PersonTable.NAME + ".*" + + " FROM " + PersonTable.NAME + " JOIN " + PersonCarRelationTable.TABLE - + " ON " + PersonTable.COLUMN_ID + " = " + PersonCarRelationTable.COLUMN_PERSON_ID + + " ON " + PersonTable.ID_COLUMN + " = " + PersonCarRelationTable.COLUMN_PERSON_ID + " AND " + PersonCarRelationTable.COLUMN_CAR_ID + " = ?") .args(car.id()) .build()) diff --git a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/PersonRelationsGetResolver.java b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/PersonRelationsGetResolver.java index 11764ba17..892976d98 100644 --- a/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/PersonRelationsGetResolver.java +++ b/storio-sample-app/src/main/java/com/pushtorefresh/storio2/sample/many_to_many_sample/resolvers/PersonRelationsGetResolver.java @@ -33,10 +33,10 @@ public Person mapFromCursor(@NonNull StorIOSQLite storIOSQLite, @NonNull Cursor .listOfObjects(Car.class) .withQuery(RawQuery.builder() .query("SELECT " - + CarTable.TABLE + ".*" - + " FROM " + CarTable.TABLE + + CarTable.NAME + ".*" + + " FROM " + CarTable.NAME + " JOIN " + PersonCarRelationTable.TABLE - + " ON " + CarTable.COLUMN_ID + " = " + PersonCarRelationTable.COLUMN_CAR_ID + + " ON " + CarTable.ID_COLUMN + " = " + PersonCarRelationTable.COLUMN_CAR_ID + " AND " + PersonCarRelationTable.COLUMN_PERSON_ID + " = ?") .args(person.id()) .build()) diff --git a/storio-sqlite-annotations-processor-test/src/test/java/com/pushtorefresh/storio2/sqlite/annotations/processor/test/StorIOSQLiteAnnotationsProcessorTest.java b/storio-sqlite-annotations-processor-test/src/test/java/com/pushtorefresh/storio2/sqlite/annotations/processor/test/StorIOSQLiteAnnotationsProcessorTest.java index 0bdda194c..92127973a 100644 --- a/storio-sqlite-annotations-processor-test/src/test/java/com/pushtorefresh/storio2/sqlite/annotations/processor/test/StorIOSQLiteAnnotationsProcessorTest.java +++ b/storio-sqlite-annotations-processor-test/src/test/java/com/pushtorefresh/storio2/sqlite/annotations/processor/test/StorIOSQLiteAnnotationsProcessorTest.java @@ -1,14 +1,14 @@ package com.pushtorefresh.storio2.sqlite.annotations.processor.test; +import static com.google.common.truth.Truth.assert_; +import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; +import static javax.tools.StandardLocation.SOURCE_OUTPUT; +import static javax.tools.StandardLocation.SOURCE_PATH; + import com.google.testing.compile.JavaFileObjects; import com.pushtorefresh.storio2.sqlite.annotations.processor.StorIOSQLiteProcessor; - -import org.junit.Test; - import javax.tools.JavaFileObject; - -import static com.google.common.truth.Truth.assert_; -import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; +import org.junit.Test; @SuppressWarnings("ResultOfMethodCallIgnored") public class StorIOSQLiteAnnotationsProcessorTest { @@ -578,4 +578,31 @@ public void shouldNotCompileWithPrivateFieldsdWithoutCreator() { .failsToCompile() .withErrorContaining("Class marked with StorIOSQLiteType annotation needs factory method or constructor marked with StorIOSQLiteCreator annotation: PrivateFieldsWithoutCreator"); } + + @Test + public void shouldGenerateTableClass() { + JavaFileObject model = JavaFileObjects.forResource("WithGeneratedTable.java"); + + JavaFileObject generatedTableClass = JavaFileObjects.forResource("WithGeneratedTableTable.java"); + + assert_().about(javaSource()) + .that(model) + .processedWith(new StorIOSQLiteProcessor()) + .compilesWithoutError() + .and() + .generatesSources(generatedTableClass); + } + + // ¯\_(ツ)_/¯ + @Test(expected = AssertionError.class) + public void shouldNotGenerateTableClassIfDisabled() { + JavaFileObject model = JavaFileObjects.forResource("WithoutGeneratedTable.java"); + + assert_().about(javaSource()) + .that(model) + .processedWith(new StorIOSQLiteProcessor()) + .compilesWithoutError() + .and() + .generatesFileNamed(SOURCE_OUTPUT, "com.pushtorefresh.storio2.sqlite.annotations", "WithoutGeneratedTableTable.java"); + } } diff --git a/storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTable.java b/storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTable.java new file mode 100644 index 000000000..73f72eef6 --- /dev/null +++ b/storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTable.java @@ -0,0 +1,38 @@ +package com.pushtorefresh.storio2.sqlite.annotations; + +import android.support.annotation.NonNull; + +@StorIOSQLiteType(table = "table") +public class WithGeneratedTable { + + @StorIOSQLiteColumn(name = "field1") + boolean field1; + + @StorIOSQLiteColumn(name = "field2") + short field2; + + @StorIOSQLiteColumn(name = "field3") + int field3; + + @StorIOSQLiteColumn(name = "field4", key = true) + long field4; + + @StorIOSQLiteColumn(name = "field5") + float field5; + + @StorIOSQLiteColumn(name = "field6") + double field6; + + @StorIOSQLiteColumn(name = "field7") + String field7; + + @StorIOSQLiteColumn(name = "field8") + byte[] field8; + + @StorIOSQLiteColumn(name = "new_field_1", version = 2) + int newField1; + + @NonNull + @StorIOSQLiteColumn(name = "new_field_2", version = 3) + String newField2; +} \ No newline at end of file diff --git a/storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTableTable.java b/storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTableTable.java new file mode 100644 index 000000000..d35e42c39 --- /dev/null +++ b/storio-sqlite-annotations-processor-test/src/test/resources/WithGeneratedTableTable.java @@ -0,0 +1,53 @@ +package com.pushtorefresh.storio2.sqlite.annotations; + +import android.database.sqlite.SQLiteDatabase; +import java.lang.String; + +public final class WithGeneratedTableTable { + public static final String NAME = "table"; + + public static final String FIELD_1_COLUMN = "field1"; + + public static final String FIELD_2_COLUMN = "field2"; + + public static final String FIELD_3_COLUMN = "field3"; + + public static final String FIELD_4_COLUMN = "field4"; + + public static final String FIELD_5_COLUMN = "field5"; + + public static final String FIELD_6_COLUMN = "field6"; + + public static final String FIELD_7_COLUMN = "field7"; + + public static final String FIELD_8_COLUMN = "field8"; + + public static final String NEW_FIELD_1_COLUMN = "new_field_1"; + + public static final String NEW_FIELD_2_COLUMN = "new_field_2"; + + private WithGeneratedTableTable() { + } + + public static void createTable(SQLiteDatabase db) { + db.execSQL("CREATE TABLE table (field1 INTEGER,\n" + + "field2 INTEGER,\n" + + "field3 INTEGER,\n" + + "field4 INTEGER PRIMARY KEY,\n" + + "field5 REAL,\n" + + "field6 REAL,\n" + + "field7 TEXT,\n" + + "field8 BLOB,\n" + + "new_field_1 INTEGER,\n" + + "new_field_2 TEXT NOT NULL);"); + } + + public static void updateTable(SQLiteDatabase db, int oldVersion) { + if (oldVersion < 2) { + db.execSQL("ALTER TABLE table ADD COLUMN new_field_1 INTEGER"); + } + if (oldVersion < 3) { + db.execSQL("ALTER TABLE table ADD COLUMN new_field_2 TEXT NOT NULL"); + } + } +} \ No newline at end of file diff --git a/storio-sqlite-annotations-processor-test/src/test/resources/WithoutGeneratedTable.java b/storio-sqlite-annotations-processor-test/src/test/resources/WithoutGeneratedTable.java new file mode 100644 index 000000000..a921bd249 --- /dev/null +++ b/storio-sqlite-annotations-processor-test/src/test/resources/WithoutGeneratedTable.java @@ -0,0 +1,31 @@ +package com.pushtorefresh.storio2.sqlite.annotations; + +import android.support.annotation.NonNull; + +@StorIOSQLiteType(table = "table", generateTableClass = false) +public class WithoutGeneratedTable { + + @StorIOSQLiteColumn(name = "field1") + boolean field1; + + @StorIOSQLiteColumn(name = "field2") + short field2; + + @StorIOSQLiteColumn(name = "field3") + int field3; + + @StorIOSQLiteColumn(name = "field4", key = true) + long field4; + + @StorIOSQLiteColumn(name = "field5") + float field5; + + @StorIOSQLiteColumn(name = "field6") + double field6; + + @StorIOSQLiteColumn(name = "field7") + String field7; + + @StorIOSQLiteColumn(name = "field8") + byte[] field8; +} \ No newline at end of file diff --git a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt index e58a5606b..a57e8790b 100644 --- a/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt +++ b/storio-sqlite-annotations-processor/src/main/kotlin/com/pushtorefresh/storio2/sqlite/annotations/processor/generate/TableGenerator.kt @@ -2,7 +2,7 @@ package com.pushtorefresh.storio2.sqlite.annotations.processor.generate import com.pushtorefresh.storio2.common.annotations.processor.generate.Common.INDENT import com.pushtorefresh.storio2.common.annotations.processor.generate.Generator -import com.pushtorefresh.storio2.common.annotations.processor.toUpperCaseSnakeCase +import com.pushtorefresh.storio2.common.annotations.processor.toUpperSnakeCase import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta import com.pushtorefresh.storio2.sqlite.annotations.processor.introspection.StorIOSQLiteTypeMeta import com.squareup.javapoet.* @@ -39,7 +39,7 @@ object TableGenerator : Generator { .build() columns.forEach { column -> - list += FieldSpec.builder(String::class.java, "${column.elementName.toUpperCaseSnakeCase()}_COLUMN") + list += FieldSpec.builder(String::class.java, "${column.elementName.toUpperSnakeCase()}_COLUMN") .initializer("\$S", column.storIOColumn.name) .addModifiers(PUBLIC, STATIC, FINAL) .build() @@ -57,7 +57,7 @@ object TableGenerator : Generator { builder.append("${column.storIOColumn.name} ${column.javaType.sqliteType}") if (column.isNotNull()) builder.append(" NOT NULL") if (column.storIOColumn.key) builder.append(" PRIMARY KEY") - if (index != columns.size - 1) builder.append(".\n") + if (index != columns.size - 1) builder.append(",\n") } builder.append(");") @@ -81,7 +81,7 @@ object TableGenerator : Generator { columnsToUpdate.forEach { column -> builder.beginControlFlow("if ($OLD_VERSION_PARAM < ${column.storIOColumn.version})") - builder.addCode("$DB_PARAM.execSQL(ALTER TABLE $table ADD COLUMN ${column.storIOColumn.name} ${column.javaType.sqliteType}) ${if (column.isNotNull()) "NOT NULL" else ""});") + builder.addCode("$DB_PARAM.execSQL(\$S);\n", "ALTER TABLE $table ADD COLUMN ${column.storIOColumn.name} ${column.javaType.sqliteType}${if (column.isNotNull()) " NOT NULL" else ""}") builder.endControlFlow() }