Skip to content

Commit

Permalink
Merge pull request #32 from SchwarzIT/bugfix/ensureTypeConversion
Browse files Browse the repository at this point in the history
Bugfix/ensure type conversion
  • Loading branch information
sbra0902 authored Nov 25, 2020
2 parents 9f030f4 + c062168 commit 91c2967
Show file tree
Hide file tree
Showing 26 changed files with 214 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
public @interface MapWrapper {

Class<?> value() default Void.class;

boolean modifierOpen() default false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class CoachBaseBinderProcessor : AbstractProcessor() {
var mapWrapperStrings = mapWrappers.map { element -> element.toString() }
var generatedInterfaces = mutableSetOf<String>()

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? {
Expand Down Expand Up @@ -114,13 +114,14 @@ class CoachBaseBinderProcessor : AbstractProcessor() {
return true // no further processing of this annotation type
}

private fun validateAndCreateBaseModelMap(elements: Collection<Element>, wrapperString: List<String>) : Map<String, BaseModelHolder>{
private fun validateAndCreateBaseModelMap(elements: Collection<Element>, wrapperString: List<String>, generatedInterfaces: MutableSet<String>) : Map<String, BaseModelHolder>{
val result = HashMap<String, BaseModelHolder>()
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
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,23 @@ 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))
.addFunction(BuilderClassGeneration.generateBuilderFun())

for (baseModelHolder in holder.basedOn) {
typeBuilder.addSuperinterface(baseModelHolder.interfaceTypeName)
}

if(holder.modifierOpen){
typeBuilder.addModifiers(KModifier.OPEN)
}

for (fieldHolder in holder.allFields) {

fieldHolder.builderSetter(holder.dbName, holder.`package`, holder.entitySimpleName, true)?.let {
Expand Down Expand Up @@ -97,7 +106,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}"
Expand All @@ -106,7 +115,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())
Expand Down Expand Up @@ -139,7 +148,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<KModifier> {
Expand All @@ -152,8 +161,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()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,24 @@ 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())
.addFunction(constructorDefault())
.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())
Expand Down Expand Up @@ -92,7 +101,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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ object EntityFactory {

fun createEntityHolder(cblEntityElement: Element, allWrappers: List<String>, allBaseModels: Map<String, BaseModelHolder>): 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<String>): BaseModelHolder {
return create(cblEntityElement, BaseModelHolder(), allWrappers, emptyMap()) as BaseModelHolder
}

fun createChildEntityHolder(cblEntityElement: Element, allWrappers: List<String>, allBaseModels: Map<String, BaseModelHolder>): 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<String>, allBaseModels: Map<String, BaseModelHolder>): BaseEntityHolder {
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ abstract class BaseEntityHolder {

val generateAccessors : MutableList<CblGenerateAccessorHolder> = ArrayList()

val basedOn : MutableList<BaseModelHolder> = ArrayList()

val allFields: List<CblBaseFieldHolder>
get() {
val allField = ArrayList<CblBaseFieldHolder>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.kaufland.model.entity

class BaseModelHolder() : BaseEntityHolder()


Original file line number Diff line number Diff line change
Expand Up @@ -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()
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<String>, useMDocChanges: Boolean): PropertySpec

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ class CblFieldHolder(field: Field, allWrappers: List<String>) : 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"))
Expand Down
8 changes: 8 additions & 0 deletions couchbase-entity/src/main/java/com/kaufland/util/TypeUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down

This file was deleted.

Loading

0 comments on commit 91c2967

Please sign in to comment.