Skip to content

Commit

Permalink
Merge pull request #85 from cyrillhalter/ensure-types-fix
Browse files Browse the repository at this point in the history
Fix defaults and ensureTypes generation
  • Loading branch information
cyrillhalter authored Jul 30, 2024
2 parents 254af7b + b0b5d02 commit edde4bd
Show file tree
Hide file tree
Showing 11 changed files with 592 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,32 @@ object CrystalWrap {
}
}

inline fun <T> getList(
inline fun <reified T> getList(
changes: MutableMap<String, Any?>,
doc: MutableMap<String, out Any?>,
fieldName: String,
mapper: ((List<MutableMap<String, Any?>>?) -> List<T>)
mapper: ((MutableMap<String, Any?>?) -> T?)
): List<T>? = (changes[fieldName] ?: doc[fieldName])?.let { value ->
catchTypeConversionError(fieldName, value) {
mapper.invoke(value as List<MutableMap<String, Any?>>)
(value as List<Any>).mapNotNull {
catchTypeConversionError(fieldName, it) {
mapper.invoke(it as MutableMap<String, Any?>)
}
}
}
}

inline fun <T, reified U> getList(
inline fun <reified T, reified U> getList(
changes: MutableMap<String, Any?>,
doc: MutableMap<String, out Any?>,
fieldName: String,
typeConverter: ITypeConverter<T, U>
): List<T>? = (changes[fieldName] ?: doc[fieldName])?.let { value ->
catchTypeConversionError(fieldName, value) {
((value as List<Any>).map { it as U }).mapNotNull {
typeConverter.read(it)
(value as List<Any>).mapNotNull {
catchTypeConversionError(fieldName, it) {
typeConverter.read(it as U)
}
}
}
}
Expand All @@ -69,7 +75,11 @@ object CrystalWrap {
fieldName: String
): List<T>? = (changes[fieldName] ?: doc[fieldName])?.let { value ->
catchTypeConversionError(fieldName, value) {
(value as List<Any>).map { it as T }
(value as List<Any>).mapNotNull {
catchTypeConversionError(fieldName, it) {
it as T
}
}
}
}

Expand Down Expand Up @@ -134,12 +144,50 @@ object CrystalWrap {
}
}

inline fun <reified T> catchTypeConversionError(fieldName: String, value: Any, task: () -> T): T? = try {
inline fun <reified DomainType> ensureType(
map: HashMap<String, in Any>,
key: String,
typeConverter: ITypeConverter<DomainType, *>
) {
val value = map[key]
catchTypeConversionError(key, value) {
if (value != null && value is DomainType) {
val converted = typeConverter.write(value)
converted?.let { map.replace(key, it) }
}
}
}

inline fun <reified DomainType, reified MapType> ensureListType(
map: HashMap<String, in Any>,
key: String,
typeConverter: ITypeConverter<DomainType, MapType>
) {
val value = map[key]
if (value != null && value is List<*>) {
val converted = value.map {
if (it != null && it is DomainType) {
catchTypeConversionError<MapType?>(key, it) {
typeConverter.write(it)
}
} else {
it
}
}
map.replace(key, converted)
}
}

inline fun <reified T> catchTypeConversionError(
fieldName: String,
value: Any?,
task: () -> T
): T? = try {
task()
} catch (cce: ClassCastException) {
} catch (e: Exception) {
PersistenceConfig.onTypeConversionError(
com.schwarz.crystalapi.TypeConversionErrorWrapper(
cce,
e,
fieldName,
value,
T::class
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.schwarz.crystalprocessor.generation.model

import com.schwarz.crystalprocessor.model.entity.BaseEntityHolder
import com.schwarz.crystalprocessor.model.typeconverter.TypeConverterHolderForEntityGeneration
import com.schwarz.crystalprocessor.util.ConversionUtil
import com.schwarz.crystalprocessor.util.TypeUtil
import com.squareup.kotlinpoet.CodeBlock
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.TypeName

object CblDefaultGeneration {

fun addDefaults(holder: BaseEntityHolder, useNullableMap: Boolean): FunSpec {
fun addDefaults(holder: BaseEntityHolder, useNullableMap: Boolean, typeConvertersByConvertedClass: Map<TypeName, TypeConverterHolderForEntityGeneration>): FunSpec {
val type =
if (useNullableMap) TypeUtil.mutableMapStringAnyNullable() else TypeUtil.mutableMapStringAny()
val valueType =
Expand All @@ -19,23 +21,35 @@ object CblDefaultGeneration {
if (useNullableMap) TypeUtil.anyNullable() else TypeUtil.any()

val builder =
FunSpec.builder("addDefaults").addModifiers(KModifier.PRIVATE)
FunSpec.builder("addDefaults").addModifiers(KModifier.PRIVATE).addParameter("map", type)

builder.addStatement("val result = mutableMapOf<String, Any?>()")

for (fieldHolder in holder.fields.values) {
if (fieldHolder.isDefault) {
builder.addStatement(
"this.%N = ${ConversionUtil.convertStringToDesiredFormat(
fieldHolder.crystalWrapSetStatement(
builder,
"result",
typeConvertersByConvertedClass,
ConversionUtil.convertStringToDesiredFormat(
fieldHolder.typeMirror,
fieldHolder.defaultValue
)}",
fieldHolder.accessorSuffix()
)
)
}
}

builder.addCode(
CodeBlock.builder()
.beginControlFlow("result.forEach")
.beginControlFlow("if(it.value != null)").addStatement("map[it.key] = it.value!!").endControlFlow()
.endControlFlow()
.build()
)
return builder.build()
}

fun addAddCall(): CodeBlock {
return CodeBlock.builder().addStatement("addDefaults()").build()
fun addAddCall(nameOfMap: String): CodeBlock {
return CodeBlock.builder().addStatement("addDefaults(%N)", nameOfMap).build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,63 +19,25 @@ object EnsureTypesGeneration {
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 %N = %T()", RESULT_VAL_NAME, explicitType)
ensureTypes.addStatement("%N.putAll(doc)", RESULT_VAL_NAME)

for (field in holder.fields.values) {
if (field.isNonConvertibleClass) {
if (field.isIterable) {
ensureTypes.addStatement(
"%T.getList<%T>(mutableMapOf(), %N, %N)",
CrystalWrap::class,
field.fieldType,
RESULT_VAL_NAME,
field.constantName
)
} else {
ensureTypes.addStatement(
"%T.get<%T>(mutableMapOf(), %N, %N)",
CrystalWrap::class,
field.fieldType,
RESULT_VAL_NAME,
field.constantName
)
}
} else if (field.isTypeOfSubEntity) {
if (field.isIterable) {
ensureTypes.addStatement(
"%T.getList(mutableMapOf(), %N, %N, {%T.fromMap(it) ?: emptyList()})",
CrystalWrap::class,
RESULT_VAL_NAME,
field.constantName,
field.subEntityTypeName
)
} else {
ensureTypes.addStatement(
"%T.get(mutableMapOf(), %N, %N, {%T.fromMap(it)})",
CrystalWrap::class,
RESULT_VAL_NAME,
field.constantName,
field.subEntityTypeName
)
}
} else {
if (!field.isNonConvertibleClass && !field.isTypeOfSubEntity) {
val typeConverterHolder =
typeConvertersByConvertedClass.get(field.fieldType)!!
if (field.isIterable) {
ensureTypes.addStatement(
"%T.getList(mutableMapOf(), %N, %N, %T)",
"%T.ensureListType(%N, %N, %T)",
CrystalWrap::class,
RESULT_VAL_NAME,
field.constantName,
typeConverterHolder.instanceClassTypeName
)
} else {
ensureTypes.addStatement(
"%T.get(mutableMapOf(), %N, %N, %T)",
"%T.ensureType(%N, %N, %T)",
CrystalWrap::class,
RESULT_VAL_NAME,
field.constantName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class EntityGeneration {
.addSuperinterface(MandatoryCheck::class)
.addProperty(holder.dbNameProperty())
.addFunction(EnsureTypesGeneration.ensureTypes(holder, false, typeConvertersByConvertedClass))
.addFunction(CblDefaultGeneration.addDefaults(holder, false))
.addFunction(CblDefaultGeneration.addDefaults(holder, false, typeConvertersByConvertedClass))
.addFunction(CblConstantGeneration.addConstants(holder, false))
.addFunction(ValidateMethodGeneration.generate(holder, true))
.addProperty(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class RebindMethodGeneration {
val type = if (clearMDocChanges) TypeUtil.mapStringAny() else TypeUtil.mapStringAnyNullable()
val rebind = FunSpec.builder("rebind").addParameter("doc", type)
.addStatement("mDoc = %T()", explicitType)
.addCode(CblDefaultGeneration.addAddCall())
.addCode(CblDefaultGeneration.addAddCall("mDoc"))
.addCode(
CodeBlock.builder()
.beginControlFlow("if(doc != null)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class WrapperGeneration {
.addSuperinterface(holder.interfaceTypeName)
.addSuperinterface(MandatoryCheck::class)
.addFunction(EnsureTypesGeneration.ensureTypes(holder, true, typeConvertersByConvertedClass))
.addFunction(CblDefaultGeneration.addDefaults(holder, true))
.addFunction(CblDefaultGeneration.addDefaults(holder, true, typeConvertersByConvertedClass))
.addFunction(CblConstantGeneration.addConstants(holder, true))
.addFunction(SetAllMethodGeneration().generate(holder, false))
.addFunction(MapSupportGeneration.toMap(holder))
Expand Down
Loading

0 comments on commit edde4bd

Please sign in to comment.