From 2a1b8128f0062cbf80248dc8e1f621545bb0994f Mon Sep 17 00:00:00 2001 From: Sven Braun Date: Tue, 24 Nov 2020 13:54:31 +0100 Subject: [PATCH 1/4] # fixed missing type conversion when initialising with map # fixed mssing type conversion for complex default values # added example + test to demo project --- .../com/coachbasebinderapi/MapSupport.kt | 2 +- .../generation/CblConstantGeneration.kt | 6 +- .../generation/CblDefaultGeneration.kt | 10 ++- .../generation/EnsureTypesGeneration.kt | 28 +++++++++ .../kaufland/generation/EntityGeneration.kt | 17 ++--- .../generation/RebindMethodGeneration.kt | 4 +- .../kaufland/generation/WrapperGeneration.kt | 7 ++- .../model/field/CblBaseFieldHolder.kt | 4 +- .../kaufland/model/field/CblFieldHolder.kt | 5 ++ .../main/java/com/kaufland/util/TypeUtil.kt | 8 +++ .../com/demo/ExampleInstrumentedTest.java | 26 -------- .../java/kaufland/com/demo/Application.kt | 12 ++++ .../com/demo/customtypes/GenerateClassName.kt | 6 ++ .../GenerateClassNameConversion.kt | 23 +++++++ .../com/demo/entity/AnotherBaseModel.kt | 6 +- .../kaufland/com/demo/ExampleUnitTest.java | 17 ----- .../kaufland/com/demo/TypeConversionTest.kt | 63 +++++++++++++++++++ 17 files changed, 180 insertions(+), 64 deletions(-) create mode 100644 couchbase-entity/src/main/java/com/kaufland/generation/EnsureTypesGeneration.kt delete mode 100644 demo/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java create mode 100644 demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassName.kt create mode 100644 demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassNameConversion.kt delete mode 100644 demo/src/test/java/kaufland/com/demo/ExampleUnitTest.java create mode 100644 demo/src/test/java/kaufland/com/demo/TypeConversionTest.kt diff --git a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt index db0bd40b..8c15d005 100644 --- a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt +++ b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt @@ -2,5 +2,5 @@ package kaufland.com.coachbasebinderapi interface MapSupport { - fun toMap(): Map + fun toMap(): Map } \ No newline at end of file diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/CblConstantGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/CblConstantGeneration.kt index 2b59404b..406ad13b 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/CblConstantGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/CblConstantGeneration.kt @@ -8,8 +8,10 @@ import com.squareup.kotlinpoet.KModifier object CblConstantGeneration { - fun addConstants(holder: BaseEntityHolder): FunSpec { - val builder = FunSpec.builder("addConstants").addModifiers(KModifier.PRIVATE).addParameter("map", TypeUtil.mutableMapStringAnyNullable()) + fun addConstants(holder: BaseEntityHolder, useNullableMap: Boolean): FunSpec { + + val type = if (useNullableMap) TypeUtil.mutableMapStringAnyNullable() else TypeUtil.mutableMapStringAny() + val builder = FunSpec.builder("addConstants").addModifiers(KModifier.PRIVATE).addParameter("map", type) for (fieldHolder in holder.fieldConstants.values) { diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/CblDefaultGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/CblDefaultGeneration.kt index 8b70650b..10e8fa22 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/CblDefaultGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/CblDefaultGeneration.kt @@ -12,13 +12,17 @@ import javax.lang.model.type.TypeMirror object CblDefaultGeneration { - fun addDefaults(holder: BaseEntityHolder): FunSpec { - val builder = FunSpec.builder("addDefaults").addModifiers(KModifier.PRIVATE).addParameter( "map", TypeUtil.mutableMapStringAnyNullable()) + fun addDefaults(holder: BaseEntityHolder, useNullableMap : Boolean): FunSpec { + + val type = if (useNullableMap) TypeUtil.mutableMapStringAnyNullable() else TypeUtil.mutableMapStringAny() + val typeConversionReturnType = if (useNullableMap) TypeUtil.anyNullable() else TypeUtil.any() + + val builder = FunSpec.builder("addDefaults").addModifiers(KModifier.PRIVATE).addParameter( "map", type) for (fieldHolder in holder.fields.values) { if (fieldHolder.isDefault) { - builder.addStatement("map.put(%N, " + ConversionUtil.convertStringToDesiredFormat(fieldHolder.typeMirror, fieldHolder.defaultValue) + ")", fieldHolder.constantName) + builder.addStatement("map.put(%N, " + fieldHolder.ensureType(typeConversionReturnType, ConversionUtil.convertStringToDesiredFormat(fieldHolder.typeMirror, fieldHolder.defaultValue)) + "!!)", fieldHolder.constantName) } } return builder.build() diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/EnsureTypesGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/EnsureTypesGeneration.kt new file mode 100644 index 00000000..c452e5c5 --- /dev/null +++ b/couchbase-entity/src/main/java/com/kaufland/generation/EnsureTypesGeneration.kt @@ -0,0 +1,28 @@ +package com.kaufland.generation + +import com.kaufland.model.entity.BaseEntityHolder +import com.kaufland.util.TypeUtil +import com.squareup.kotlinpoet.FunSpec + +object EnsureTypesGeneration { + + fun ensureTypes(holder: BaseEntityHolder, useNullableMap: Boolean): FunSpec { + + val explicitType = if (useNullableMap) TypeUtil.hashMapStringAnyNullable() else TypeUtil.hashMapStringAny() + val type = if (useNullableMap) TypeUtil.mapStringAnyNullable() else TypeUtil.mapStringAny() + val typeConversionReturnType = if (useNullableMap) TypeUtil.anyNullable() else TypeUtil.any() + val ensureTypes = FunSpec.builder("ensureTypes").addParameter( "doc", type).returns(type) + ensureTypes.addStatement("val result = %T()", explicitType) + ensureTypes.addStatement("result.putAll(doc)") + + for (field in holder.fields.values) { + ensureTypes.beginControlFlow("${field.ensureType(typeConversionReturnType,"doc[%N]", field.constantName).toString()}?.let") + ensureTypes.addStatement("result[%N] = it", field.constantName) + ensureTypes.endControlFlow() + } + + ensureTypes.addStatement("return result") + return ensureTypes.build() + } + +} diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt index 5b3d41a7..7bc71b17 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt @@ -43,9 +43,10 @@ class EntityGeneration { .addModifiers(KModifier.PUBLIC) .addSuperinterface(TypeUtil.mapSupport()) .addSuperinterface(holder.interfaceTypeName) - .addFunction(CblDefaultGeneration.addDefaults(holder)) - .addFunction(CblConstantGeneration.addConstants(holder)) - .addProperty(PropertySpec.builder("mDoc", TypeUtil.mutableMapStringAnyNullable(), KModifier.PRIVATE).mutable().initializer("%T()", TypeUtil.hashMapStringAnyNullable()).build()) + .addFunction(EnsureTypesGeneration.ensureTypes(holder, false)) + .addFunction(CblDefaultGeneration.addDefaults(holder, false)) + .addFunction(CblConstantGeneration.addConstants(holder, false)) + .addProperty(PropertySpec.builder("mDoc", TypeUtil.mutableMapStringAny(), KModifier.PRIVATE).mutable().initializer("%T()", TypeUtil.hashMapStringAny()).build()) .addProperty(PropertySpec.builder("mDocChanges", TypeUtil.mutableMapStringAnyNullable(), KModifier.PRIVATE).mutable().initializer("%T()", TypeUtil.hashMapStringAnyNullable()).build()) .addFunction(contructor(holder)).addFunction(setAll(holder)).addFunctions(TypeConversionMethodsGeneration(useSuspend).generate()).addFunction(id).superclass(holder.sourceElement!!.asType().asTypeName()) .addFunction(toMap(holder, useSuspend)) @@ -97,7 +98,7 @@ class EntityGeneration { private fun toMap(holder: EntityHolder, useSuspend: Boolean): FunSpec { - var refreshDoc = "getId()?.let{%T.${getDocumentMethod(useSuspend)}(it, %S)} ?: mapOf()" + var refreshDoc = "getId()?.let{%T.${getDocumentMethod(useSuspend)}(it, %S)} ?: mDoc" if(useSuspend){ refreshDoc = "kotlinx.coroutines.runBlocking{$refreshDoc}" @@ -106,7 +107,7 @@ class EntityGeneration { val toMapBuilder = FunSpec.builder("toMap").addModifiers(KModifier.OVERRIDE).returns(TypeUtil.mutableMapStringAny()).addStatement("val doc = $refreshDoc", PersistenceConfig::class, holder.dbName) for (constantField in holder.fieldConstants.values) { - toMapBuilder.addStatement("mDocChanges.put(%S, %S)", constantField.dbField, constantField.constantValue) + toMapBuilder.addStatement("mDocChanges.put(%S, %N)", constantField.dbField, constantField.constantValueAccessorName) } toMapBuilder.addStatement("var temp = mutableMapOf<%T, %T>()", TypeUtil.string(), TypeUtil.any()) @@ -139,7 +140,7 @@ class EntityGeneration { } private fun contructor(holder: EntityHolder): FunSpec { - return FunSpec.constructorBuilder().addModifiers(KModifier.PUBLIC).addParameter("doc", TypeUtil.mapStringAnyNullable()).addStatement("rebind(doc)").build() + return FunSpec.constructorBuilder().addModifiers(KModifier.PUBLIC).addParameter("doc", TypeUtil.mapStringAny()).addStatement("rebind(ensureTypes(doc))").build() } private fun evaluateModifiers(useSuspend: Boolean): List { @@ -152,8 +153,8 @@ class EntityGeneration { FunSpec.builder("create").addModifiers(evaluateModifiers(useSuspend)).addParameter("id", String::class).addAnnotation(JvmStatic::class).addStatement("return %N(%T.${getDocumentMethod(useSuspend)}(id, %S) ?: mutableMapOf(_ID to id))", holder.entitySimpleName, PersistenceConfig::class, holder.dbName).returns(holder.entityTypeName).build(), FunSpec.builder("create").addModifiers(evaluateModifiers(useSuspend)).addAnnotation(JvmStatic::class).addStatement("return %N(%T())", - holder.entitySimpleName, TypeUtil.hashMapStringAnyNullable()).returns(holder.entityTypeName).build(), - FunSpec.builder("create").addModifiers(KModifier.PUBLIC).addParameter("map", TypeUtil.mutableMapStringAnyNullable()).addAnnotation(JvmStatic::class).addStatement("return %N(map)", + holder.entitySimpleName, TypeUtil.hashMapStringAny()).returns(holder.entityTypeName).build(), + FunSpec.builder("create").addModifiers(KModifier.PUBLIC).addParameter("map", TypeUtil.mutableMapStringAny()).addAnnotation(JvmStatic::class).addStatement("return %N(map)", holder.entitySimpleName).returns(holder.entityTypeName).build() ) } diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/RebindMethodGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/RebindMethodGeneration.kt index 1f70c595..48bb01a0 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/RebindMethodGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/RebindMethodGeneration.kt @@ -8,7 +8,9 @@ class RebindMethodGeneration { fun generate(clearMDocChanges: Boolean): FunSpec { - val rebind = FunSpec.builder("rebind").addParameter( "doc", TypeUtil.mapStringAnyNullable()).addStatement("mDoc = %T()", TypeUtil.hashMapStringAnyNullable()).addCode(CblDefaultGeneration.addAddCall("mDoc")).addCode(CodeBlock.builder() + val explicitType = if (clearMDocChanges) TypeUtil.hashMapStringAny() else TypeUtil.hashMapStringAnyNullable() + val type = if (clearMDocChanges) TypeUtil.mapStringAny() else TypeUtil.mapStringAnyNullable() + val rebind = FunSpec.builder("rebind").addParameter( "doc", type).addStatement("mDoc = %T()", explicitType).addCode(CblDefaultGeneration.addAddCall("mDoc")).addCode(CodeBlock.builder() .beginControlFlow("if(doc != null)") .addStatement("mDoc.putAll(doc)") .endControlFlow().build()).addCode(CblConstantGeneration.addAddCall("mDoc")) diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt index 4b09c2ff..6326151b 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt @@ -18,8 +18,9 @@ class WrapperGeneration { .addSuperinterface(TypeUtil.mapSupport()) .addModifiers(KModifier.PUBLIC) .addSuperinterface(holder.interfaceTypeName) - .addFunction(CblDefaultGeneration.addDefaults(holder)) - .addFunction(CblConstantGeneration.addConstants(holder)) + .addFunction(EnsureTypesGeneration.ensureTypes(holder, true)) + .addFunction(CblDefaultGeneration.addDefaults(holder, true)) + .addFunction(CblConstantGeneration.addConstants(holder, true)) .addFunction(MapSupportGeneration.toMap(holder)) .addProperty(PropertySpec.builder("mDoc", TypeUtil.mutableMapStringAnyNullable()).addModifiers(KModifier.PRIVATE).mutable().initializer("%T()", TypeUtil.hashMapStringAnyNullable()).build()) .addFunction(constructorMap()) @@ -92,7 +93,7 @@ class WrapperGeneration { } private fun constructorMap(): FunSpec { - return FunSpec.constructorBuilder().addModifiers(KModifier.PUBLIC).addParameter("doc", TypeUtil.mutableMapStringAnyNullable()).addStatement("rebind(doc)").build() + return FunSpec.constructorBuilder().addModifiers(KModifier.PUBLIC).addParameter("doc", TypeUtil.mutableMapStringAnyNullable()).addStatement("rebind(ensureTypes(doc))").build() } private fun constructorDefault(): FunSpec { diff --git a/couchbase-entity/src/main/java/com/kaufland/model/field/CblBaseFieldHolder.kt b/couchbase-entity/src/main/java/com/kaufland/model/field/CblBaseFieldHolder.kt index e32486c3..0a36603c 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/field/CblBaseFieldHolder.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/field/CblBaseFieldHolder.kt @@ -1,8 +1,10 @@ package com.kaufland.model.field +import com.kaufland.generation.TypeConversionMethodsGeneration import com.kaufland.util.ConversionUtil import com.kaufland.util.FieldExtractionUtil import com.kaufland.util.TypeUtil +import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeName @@ -41,7 +43,7 @@ abstract class CblBaseFieldHolder(val dbField: String, private val mField: Field return WordUtils.uncapitalize(WordUtils.capitalize(dbField.replace("_".toRegex(), " ")).replace(" ".toRegex(), "")) } - abstract fun interfaceProperty() : PropertySpec + abstract fun interfaceProperty(): PropertySpec abstract fun property(dbName: String?, possibleOverrides: Set, useMDocChanges: Boolean): PropertySpec diff --git a/couchbase-entity/src/main/java/com/kaufland/model/field/CblFieldHolder.kt b/couchbase-entity/src/main/java/com/kaufland/model/field/CblFieldHolder.kt index 429434ed..52703220 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/field/CblFieldHolder.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/field/CblFieldHolder.kt @@ -93,6 +93,11 @@ class CblFieldHolder(field: Field, allWrappers: List) : CblBaseFieldHold return propertyBuilder.setter(setter.build()).getter(getter.build()).build() } + fun ensureType(resultType: TypeName, format: String, vararg args: Any?): CodeBlock { + val forTypeConversion = evaluateClazzForTypeConversion() + return CodeBlock.of("${TypeConversionMethodsGeneration.WRITE_METHOD_NAME}<%T>($format, %T::class)", resultType, *args, forTypeConversion) + } + override fun builderSetter(dbName: String?, packageName: String, entitySimpleName: String, useMDocChanges: Boolean): FunSpec? { val fieldType = TypeUtil.parseMetaType(typeMirror, isIterable, subEntitySimpleName) val builder = FunSpec.builder("set" + accessorSuffix().capitalize()).addModifiers(KModifier.PUBLIC).addParameter("value", fieldType).returns(ClassName(packageName, "${entitySimpleName}.Builder")) diff --git a/couchbase-entity/src/main/java/com/kaufland/util/TypeUtil.kt b/couchbase-entity/src/main/java/com/kaufland/util/TypeUtil.kt index 35089e23..fbaa23bd 100644 --- a/couchbase-entity/src/main/java/com/kaufland/util/TypeUtil.kt +++ b/couchbase-entity/src/main/java/com/kaufland/util/TypeUtil.kt @@ -32,10 +32,18 @@ object TypeUtil { return ClassName("kotlin.collections", "HashMap").parameterizedBy(string(), anyNullable()) } + fun hashMapStringAny(): ParameterizedTypeName { + return ClassName("kotlin.collections", "HashMap").parameterizedBy(string(), any()) + } + fun mapStringAnyNullable(): ParameterizedTypeName { return map().parameterizedBy(string(), anyNullable()) } + fun mapStringAny(): ParameterizedTypeName { + return map().parameterizedBy(string(), any()) + } + fun mutableMapStringAnyNullable(): ParameterizedTypeName { return ClassName("kotlin.collections", "MutableMap").parameterizedBy(string(), anyNullable()) } diff --git a/demo/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java b/demo/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java deleted file mode 100644 index 6babf302..00000000 --- a/demo/src/androidTest/java/kaufland/com/demo/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package kaufland.com.demo; - -import android.content.Context; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("kaufland.com.demo", appContext.getPackageName()); - } -} diff --git a/demo/src/main/java/kaufland/com/demo/Application.kt b/demo/src/main/java/kaufland/com/demo/Application.kt index ac9f40c5..18632374 100755 --- a/demo/src/main/java/kaufland/com/demo/Application.kt +++ b/demo/src/main/java/kaufland/com/demo/Application.kt @@ -7,9 +7,13 @@ import com.couchbase.lite.Database import com.couchbase.lite.DatabaseConfiguration import kaufland.com.coachbasebinderapi.PersistenceConfig import kaufland.com.coachbasebinderapi.PersistenceException +import kaufland.com.coachbasebinderapi.TypeConversion import kaufland.com.couchbaseentityconnector.Couchbase2Connector +import kaufland.com.demo.customtypes.GenerateClassName +import kaufland.com.demo.customtypes.GenerateClassNameConversion import kaufland.com.demo.entity.ProductEntity import kaufland.com.demo.entity.UserCommentWrapper +import kotlin.reflect.KClass class Application : android.app.Application() { @@ -41,6 +45,13 @@ class Application : android.app.Application() { } throw RuntimeException("wrong db name defined!!") } + + override val typeConversions: Map, TypeConversion> + get() { + val mutableMapOf = mutableMapOf, TypeConversion>(GenerateClassName::class to GenerateClassNameConversion()) + mutableMapOf.putAll(super.typeConversions) + return mutableMapOf + } }) createMockArticle() } @@ -73,6 +84,7 @@ class Application : android.app.Application() { private val TAG = Application::class.java.name + @JvmField val DB = "mydb_db" } diff --git a/demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassName.kt b/demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassName.kt new file mode 100644 index 00000000..31d3b41c --- /dev/null +++ b/demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassName.kt @@ -0,0 +1,6 @@ +package kaufland.com.demo.customtypes + +class GenerateClassName(val name: String = GenerateClassName::class.simpleName ?: "") { + + override fun toString() = name +} \ No newline at end of file diff --git a/demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassNameConversion.kt b/demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassNameConversion.kt new file mode 100644 index 00000000..dfca659c --- /dev/null +++ b/demo/src/main/java/kaufland/com/demo/customtypes/GenerateClassNameConversion.kt @@ -0,0 +1,23 @@ +package kaufland.com.demo.customtypes + +import kaufland.com.coachbasebinderapi.TypeConversion + +class GenerateClassNameConversion : TypeConversion { + + override fun write(value: Any?): Any? { + return when (value) { + is GenerateClassName -> { + value.toString() + } + else -> value + } + } + + override fun read(value: Any?): GenerateClassName = + when (value) { + is String -> { + GenerateClassName(value) + } + else -> GenerateClassName() + } +} diff --git a/demo/src/main/java/kaufland/com/demo/entity/AnotherBaseModel.kt b/demo/src/main/java/kaufland/com/demo/entity/AnotherBaseModel.kt index 47cb9d06..c4181894 100644 --- a/demo/src/main/java/kaufland/com/demo/entity/AnotherBaseModel.kt +++ b/demo/src/main/java/kaufland/com/demo/entity/AnotherBaseModel.kt @@ -3,9 +3,11 @@ package kaufland.com.demo.entity import kaufland.com.coachbasebinderapi.BaseModel import kaufland.com.coachbasebinderapi.Field import kaufland.com.coachbasebinderapi.Fields +import kaufland.com.demo.customtypes.GenerateClassName @BaseModel @Fields( - Field(name = "anotherBaseThing", type = String::class) + Field(name = "anotherBaseThing", type = String::class), + Field(name = "clazzName", type = GenerateClassName::class, defaultValue = "GenerateClassName(this::class.simpleName ?: \"\")") ) -class AnotherBaseModel \ No newline at end of file +class AnotherBaseModel diff --git a/demo/src/test/java/kaufland/com/demo/ExampleUnitTest.java b/demo/src/test/java/kaufland/com/demo/ExampleUnitTest.java deleted file mode 100644 index d1453ffa..00000000 --- a/demo/src/test/java/kaufland/com/demo/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package kaufland.com.demo; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/demo/src/test/java/kaufland/com/demo/TypeConversionTest.kt b/demo/src/test/java/kaufland/com/demo/TypeConversionTest.kt new file mode 100644 index 00000000..8be8a0fd --- /dev/null +++ b/demo/src/test/java/kaufland/com/demo/TypeConversionTest.kt @@ -0,0 +1,63 @@ +package kaufland.com.demo + +import kaufland.com.coachbasebinderapi.PersistenceConfig +import kaufland.com.coachbasebinderapi.TypeConversion +import kaufland.com.demo.customtypes.GenerateClassName +import kaufland.com.demo.customtypes.GenerateClassNameConversion +import kaufland.com.demo.entity.TestClassEntity +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import kotlin.reflect.KClass + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see [Testing documentation](http://d.android.com/tools/testing) + */ +class TypeConversionTest { + + @Before + fun init(){ + PersistenceConfig.configure(object : PersistenceConfig.Connector{ + + + override val typeConversions: Map, TypeConversion> + get() { + val mutableMapOf = mutableMapOf, TypeConversion>(GenerateClassName::class to GenerateClassNameConversion()) + return mutableMapOf + } + + override fun getDocument(id: String, dbName: String): Map? { + return emptyMap() + } + + override fun queryDoc(dbName: String, queryParams: Map): List> { + throw Exception("should not called") + } + + override fun deleteDocument(id: String, dbName: String) { + throw Exception("should not called") + } + + override fun upsertDocument(document: MutableMap, id: String?, dbName: String) { + throw Exception("should not called") + } + }) + } + + @Test + @Throws(Exception::class) + fun testCustomTypeConversion() { + + val test = mapOf(TestClassEntity.CLAZZ_NAME to TypeConversionTest::class.simpleName!!) + + val testWithPreFill = TestClassEntity(test) + + Assert.assertEquals(TypeConversionTest::class.simpleName!!, testWithPreFill.toMap()[TestClassEntity.CLAZZ_NAME]) + + val testClassEntity1 = TestClassEntity.create() + + Assert.assertEquals(TestClassEntity::class.simpleName!!, testClassEntity1.toMap()[TestClassEntity.CLAZZ_NAME]) + } +} \ No newline at end of file From b4ac55db8f34626b5aef876db935d3384be1fdfd Mon Sep 17 00:00:00 2001 From: Sven Braun Date: Wed, 25 Nov 2020 09:58:32 +0100 Subject: [PATCH 2/4] # implemented possibility to generate open entities --- .../main/java/kaufland/com/coachbasebinderapi/Entity.java | 2 ++ .../main/java/com/kaufland/generation/EntityGeneration.kt | 4 ++++ .../src/main/java/com/kaufland/model/EntityFactory.kt | 2 +- .../src/main/java/com/kaufland/model/entity/EntityHolder.kt | 2 +- demo/src/main/java/kaufland/com/demo/entity/TestClass.kt | 5 +---- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/Entity.java b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/Entity.java index 75e8a5f2..e97230e4 100644 --- a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/Entity.java +++ b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/Entity.java @@ -17,6 +17,8 @@ enum Type { Class value() default Void.class; + boolean modifierOpen() default false; + Type type() default Type.READ_AND_WRITE; String database() default ""; diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt index 7bc71b17..dee01f8e 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt @@ -52,6 +52,10 @@ class EntityGeneration { .addFunction(toMap(holder, useSuspend)) .addFunction(BuilderClassGeneration.generateBuilderFun()) + if(holder.modifierOpen){ + typeBuilder.addModifiers(KModifier.OPEN) + } + for (fieldHolder in holder.allFields) { fieldHolder.builderSetter(holder.dbName, holder.`package`, holder.entitySimpleName, true)?.let { diff --git a/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt b/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt index d4f7a85c..5b8bc5af 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt @@ -22,7 +22,7 @@ object EntityFactory { fun createEntityHolder(cblEntityElement: Element, allWrappers: List, allBaseModels: Map): EntityHolder { val annotation = cblEntityElement.getAnnotation(Entity::class.java) - return create(cblEntityElement, EntityHolder(annotation.database, annotation.type), allWrappers, allBaseModels) as EntityHolder + return create(cblEntityElement, EntityHolder(annotation.database, annotation.modifierOpen, annotation.type), allWrappers, allBaseModels) as EntityHolder } fun createBaseModelHolder(cblEntityElement: Element, allWrappers: List): BaseModelHolder { diff --git a/couchbase-entity/src/main/java/com/kaufland/model/entity/EntityHolder.kt b/couchbase-entity/src/main/java/com/kaufland/model/entity/EntityHolder.kt index 7ef1877a..9e0d8e54 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/entity/EntityHolder.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/entity/EntityHolder.kt @@ -2,4 +2,4 @@ package com.kaufland.model.entity import kaufland.com.coachbasebinderapi.Entity -class EntityHolder(val dbName: String, val entityType : Entity.Type) : BaseEntityHolder() +class EntityHolder(val dbName: String, val modifierOpen: Boolean, val entityType : Entity.Type) : BaseEntityHolder() diff --git a/demo/src/main/java/kaufland/com/demo/entity/TestClass.kt b/demo/src/main/java/kaufland/com/demo/entity/TestClass.kt index ca7884d0..d0fbf5df 100644 --- a/demo/src/main/java/kaufland/com/demo/entity/TestClass.kt +++ b/demo/src/main/java/kaufland/com/demo/entity/TestClass.kt @@ -2,11 +2,8 @@ package kaufland.com.demo.entity import com.couchbase.lite.Blob import kaufland.com.coachbasebinderapi.* -import kaufland.com.coachbasebinderapi.query.Queries -import kaufland.com.coachbasebinderapi.query.Query -import kaufland.com.demo.MainActivity -@Entity(database = "mydb_db") +@Entity(database = "mydb_db", modifierOpen = true) @MapWrapper @Fields( Field(name = "type", type = String::class, defaultValue = "something", readonly = true), From 497e740b5ac0ae98203564360f65b3a0fb09d971 Mon Sep 17 00:00:00 2001 From: Sven Braun Date: Wed, 25 Nov 2020 14:09:28 +0100 Subject: [PATCH 3/4] # implemented possibility to generate open wrappers # generate interface for basedOn Models --- .../java/kaufland/com/coachbasebinderapi/MapWrapper.java | 2 ++ .../main/java/com/kaufland/CoachBaseBinderProcessor.kt | 5 +++-- .../main/java/com/kaufland/generation/EntityGeneration.kt | 4 ++++ .../java/com/kaufland/generation/WrapperGeneration.kt | 8 ++++++++ .../src/main/java/com/kaufland/model/EntityFactory.kt | 5 +++-- .../java/com/kaufland/model/entity/BaseEntityHolder.kt | 2 ++ .../java/com/kaufland/model/entity/BaseModelHolder.kt | 2 ++ .../java/com/kaufland/model/entity/WrapperEntityHolder.kt | 2 +- .../java/kaufland/com/demo/tesst/article/BaseArticle.kt | 2 +- 9 files changed, 26 insertions(+), 6 deletions(-) diff --git a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapWrapper.java b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapWrapper.java index bcd1ef3f..47b0c816 100644 --- a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapWrapper.java +++ b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapWrapper.java @@ -11,4 +11,6 @@ public @interface MapWrapper { Class value() default Void.class; + + boolean modifierOpen() default false; } diff --git a/couchbase-entity/src/main/java/com/kaufland/CoachBaseBinderProcessor.kt b/couchbase-entity/src/main/java/com/kaufland/CoachBaseBinderProcessor.kt index e956380a..086bf1a5 100644 --- a/couchbase-entity/src/main/java/com/kaufland/CoachBaseBinderProcessor.kt +++ b/couchbase-entity/src/main/java/com/kaufland/CoachBaseBinderProcessor.kt @@ -76,7 +76,7 @@ class CoachBaseBinderProcessor : AbstractProcessor() { var mapWrapperStrings = mapWrappers.map { element -> element.toString() } var generatedInterfaces = mutableSetOf() - var baseModels = validateAndCreateBaseModelMap(roundEnv.getElementsAnnotatedWith(BaseModel::class.java), mapWrapperStrings) + var baseModels = validateAndCreateBaseModelMap(roundEnv.getElementsAnnotatedWith(BaseModel::class.java), mapWrapperStrings, generatedInterfaces) validateAndProcess(roundEnv.getElementsAnnotatedWith(Entity::class.java), object : EntityProcessor { override fun process(element: Element): FileSpec? { @@ -114,13 +114,14 @@ class CoachBaseBinderProcessor : AbstractProcessor() { return true // no further processing of this annotation type } - private fun validateAndCreateBaseModelMap(elements: Collection, wrapperString: List) : Map{ + private fun validateAndCreateBaseModelMap(elements: Collection, wrapperString: List, generatedInterfaces: MutableSet) : Map{ val result = HashMap() for (elem in elements) { validator.preValidate(elem, mLogger) if (!mLogger.hasErrors()) { val baseModel = EntityFactory.createBaseModelHolder(elem, wrapperString) if(postValidate(baseModel)){ + generateInterface(generatedInterfaces, baseModel) result["${baseModel.`package`}.${baseModel.sourceClazzSimpleName}"] = baseModel } } diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt index dee01f8e..a551068b 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/EntityGeneration.kt @@ -52,6 +52,10 @@ class EntityGeneration { .addFunction(toMap(holder, useSuspend)) .addFunction(BuilderClassGeneration.generateBuilderFun()) + for (baseModelHolder in holder.basedOn) { + typeBuilder.addSuperinterface(baseModelHolder.interfaceTypeName) + } + if(holder.modifierOpen){ typeBuilder.addModifiers(KModifier.OPEN) } diff --git a/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt b/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt index 6326151b..90ba85cf 100644 --- a/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt +++ b/couchbase-entity/src/main/java/com/kaufland/generation/WrapperGeneration.kt @@ -28,6 +28,14 @@ class WrapperGeneration { .superclass(holder.sourceElement!!.asType().asTypeName()) .addFunction(BuilderClassGeneration.generateBuilderFun()) + for (baseModelHolder in holder.basedOn) { + typeBuilder.addSuperinterface(baseModelHolder.interfaceTypeName) + } + + if(holder.modifierOpen){ + typeBuilder.addModifiers(KModifier.OPEN) + } + for (fieldHolder in holder.allFields) { companionSpec.addProperties(fieldHolder.createFieldConstant()) diff --git a/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt b/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt index 5b8bc5af..72359df8 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt @@ -30,8 +30,8 @@ object EntityFactory { } fun createChildEntityHolder(cblEntityElement: Element, allWrappers: List, allBaseModels: Map): WrapperEntityHolder { - - return create(cblEntityElement, WrapperEntityHolder(), allWrappers, allBaseModels) as WrapperEntityHolder + val annotation = cblEntityElement.getAnnotation(MapWrapper::class.java) + return create(cblEntityElement, WrapperEntityHolder(annotation.modifierOpen), allWrappers, allBaseModels) as WrapperEntityHolder } private fun create(cblEntityElement: Element, content: BaseEntityHolder, allWrappers: List, allBaseModels: Map): BaseEntityHolder { @@ -44,6 +44,7 @@ object EntityFactory { basedOnValue?.forEach { type -> allBaseModels[type.toString()]?.let { + content.basedOn.add(it) content.fieldConstants.putAll(it.fieldConstants) content.fields.putAll(it.fields) content.generateAccessors.addAll(it.generateAccessors) diff --git a/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseEntityHolder.kt b/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseEntityHolder.kt index 0af0444e..7d46cb62 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseEntityHolder.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseEntityHolder.kt @@ -30,6 +30,8 @@ abstract class BaseEntityHolder { val generateAccessors : MutableList = ArrayList() + val basedOn : MutableList = ArrayList() + val allFields: List get() { val allField = ArrayList() diff --git a/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseModelHolder.kt b/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseModelHolder.kt index 8eaf8b0e..9b0db40b 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseModelHolder.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/entity/BaseModelHolder.kt @@ -1,3 +1,5 @@ package com.kaufland.model.entity class BaseModelHolder() : BaseEntityHolder() + + diff --git a/couchbase-entity/src/main/java/com/kaufland/model/entity/WrapperEntityHolder.kt b/couchbase-entity/src/main/java/com/kaufland/model/entity/WrapperEntityHolder.kt index 294c6362..8fab46cc 100644 --- a/couchbase-entity/src/main/java/com/kaufland/model/entity/WrapperEntityHolder.kt +++ b/couchbase-entity/src/main/java/com/kaufland/model/entity/WrapperEntityHolder.kt @@ -1,6 +1,6 @@ package com.kaufland.model.entity -class WrapperEntityHolder : BaseEntityHolder() { +class WrapperEntityHolder(val modifierOpen: Boolean) : BaseEntityHolder() { override val entitySimpleName: String get() = sourceClazzSimpleName + "Wrapper" diff --git a/demo/src/main/java/kaufland/com/demo/tesst/article/BaseArticle.kt b/demo/src/main/java/kaufland/com/demo/tesst/article/BaseArticle.kt index 28b4d1bf..f5bdf61d 100644 --- a/demo/src/main/java/kaufland/com/demo/tesst/article/BaseArticle.kt +++ b/demo/src/main/java/kaufland/com/demo/tesst/article/BaseArticle.kt @@ -6,7 +6,7 @@ import kaufland.com.coachbasebinderapi.MapWrapper import schwarz.fwws.shared.model.DWG import schwarz.fwws.shared.model.Model -@MapWrapper +@MapWrapper(modifierOpen = true) @Fields( Field(name = "country", type = String::class), Field(name = "type", type = String::class, defaultValue = BaseArticle.TYPE, readonly = true), From c062168186c76e2c76ad3c15da105666c7f3f214 Mon Sep 17 00:00:00 2001 From: Sven Braun Date: Wed, 25 Nov 2020 18:19:52 +0100 Subject: [PATCH 4/4] # implemented possibility to generate open wrappers # generate interface for basedOn Models --- .../src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt index 8c15d005..db0bd40b 100644 --- a/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt +++ b/couchbase-entity-api/src/main/java/kaufland/com/coachbasebinderapi/MapSupport.kt @@ -2,5 +2,5 @@ package kaufland.com.coachbasebinderapi interface MapSupport { - fun toMap(): Map + fun toMap(): Map } \ No newline at end of file