Skip to content

Commit

Permalink
Merge pull request #34 from SchwarzIT/feature/add-kdoc-comments
Browse files Browse the repository at this point in the history
Add KDoc comments and ensure deterministic field order
  • Loading branch information
michael-spiegel-ergon authored Feb 15, 2021
2 parents 737f4dd + c8ab054 commit ad317e8
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,17 @@ class EntityGeneration {
.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(contructor(holder))
.addFunction(setAll(holder))
.addFunctions(TypeConversionMethodsGeneration(useSuspend).generate())
.addFunction(id).superclass(holder.sourceElement!!.asType().asTypeName())
.addFunction(toMap(holder, useSuspend))
.addFunction(BuilderClassGeneration.generateBuilderFun())

if (holder.comment.isNotEmpty()) {
typeBuilder.addKdoc(holder.comment.joinToString(separator = "\n"))
}

for (baseModelHolder in holder.basedOn) {
typeBuilder.addSuperinterface(baseModelHolder.interfaceTypeName)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class RebindMethodGeneration {

fun generate(clearMDocChanges: Boolean): FunSpec {

val explicitType = if (clearMDocChanges) TypeUtil.hashMapStringAny() else TypeUtil.hashMapStringAnyNullable()
val explicitType = if (clearMDocChanges) TypeUtil.hashMapStringAny() else TypeUtil.linkedHashMapStringAnyNullable()
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)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class WrapperGeneration {

fun generateModel(holder: WrapperEntityHolder, useSuspend: Boolean): FileSpec {

var companionSpec = TypeSpec.companionObjectBuilder()
val companionSpec = TypeSpec.companionObjectBuilder()

var builderBuilder = BuilderClassGeneration.generateBaseBuilder(holder)
val builderBuilder = BuilderClassGeneration.generateBaseBuilder(holder)

val typeBuilder = TypeSpec.classBuilder(holder.entitySimpleName)
.addSuperinterface(TypeUtil.mapSupport())
Expand All @@ -22,12 +22,16 @@ class WrapperGeneration {
.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())
.addProperty(PropertySpec.builder("mDoc", TypeUtil.mutableMapStringAnyNullable()).addModifiers(KModifier.PRIVATE).mutable().initializer("%T()", TypeUtil.linkedHashMapStringAnyNullable()).build())
.addFunction(constructorMap())
.addFunction(constructorDefault())
.superclass(holder.sourceElement!!.asType().asTypeName())
.addFunction(BuilderClassGeneration.generateBuilderFun())

if (holder.comment.isNotEmpty()) {
typeBuilder.addKdoc(holder.comment.joinToString(separator = "\n"))
}

for (baseModelHolder in holder.basedOn) {
typeBuilder.addSuperinterface(baseModelHolder.interfaceTypeName)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import javax.lang.model.element.Element

abstract class BaseEntityHolder {

val fields: MutableMap<String, CblFieldHolder> = HashMap()
val fields: MutableMap<String, CblFieldHolder> = mutableMapOf()

var abstractParts: Set<String> = HashSet()
var abstractParts: Set<String> = mutableSetOf()

val fieldConstants: MutableMap<String, CblConstantHolder> = HashMap()
val fieldConstants: MutableMap<String, CblConstantHolder> = mutableMapOf()

var sourceElement: Element? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class CblConstantHolder(field: Field) : CblBaseFieldHolder(field.name, field) {

val builder = PropertySpec.builder(accessorSuffix(), returnType, KModifier.PUBLIC, KModifier.OVERRIDE)
.getter(FunSpec.getterBuilder().addStatement("return " + TypeConversionMethodsGeneration.READ_METHOD_NAME + "(mDoc.get(%N), %T::class)!!", constantName, returnType).build())

if (comment.isNotEmpty()) {
builder.addKdoc(comment.joinToString(separator = "\n"))
}

return builder.build()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,15 @@ class CblFieldHolder(field: Field, allWrappers: List<String>) : CblBaseFieldHold
}

override fun interfaceProperty(): PropertySpec {
var returnType = TypeUtil.parseMetaType(typeMirror, isIterable, subEntitySimpleName).copy(nullable = true)
val returnType = TypeUtil.parseMetaType(typeMirror, isIterable, subEntitySimpleName).copy(nullable = true)
return PropertySpec.builder(accessorSuffix(), returnType.copy(true), KModifier.PUBLIC).mutable(true).build()
}

override fun property(dbName: String?, possibleOverrides: Set<String>, useMDocChanges: Boolean): PropertySpec {
var returnType = TypeUtil.parseMetaType(typeMirror, isIterable, subEntitySimpleName).copy(nullable = true)
val returnType = TypeUtil.parseMetaType(typeMirror, isIterable, subEntitySimpleName).copy(nullable = true)

val propertyBuilder = PropertySpec.builder(accessorSuffix(), returnType.copy(true), KModifier.PUBLIC, KModifier.OVERRIDE).mutable(true)


val getter = FunSpec.getterBuilder()
val setter = FunSpec.setterBuilder().addParameter("value", String::class)

Expand Down Expand Up @@ -90,6 +89,10 @@ class CblFieldHolder(field: Field, allWrappers: List<String>) : CblBaseFieldHold

}

if (comment.isNotEmpty()) {
propertyBuilder.addKdoc(comment.joinToString(separator = "\n"))
}

return propertyBuilder.setter(setter.build()).getter(getter.build()).build()
}

Expand All @@ -98,9 +101,16 @@ class CblFieldHolder(field: Field, allWrappers: List<String>) : CblBaseFieldHold
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? {
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"))
val builder = FunSpec.builder("set" + accessorSuffix().capitalize())
.addModifiers(KModifier.PUBLIC)
.addParameter("value", fieldType)
.returns(ClassName(packageName, "${entitySimpleName}.Builder"))

if (this.comment.isNotEmpty()) {
builder.addKdoc(this.comment.joinToString(separator = "\n"))
}

builder.addStatement("obj.${accessorSuffix()} = value")
builder.addStatement("return this")
Expand Down
4 changes: 4 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,6 +32,10 @@ object TypeUtil {
return ClassName("kotlin.collections", "HashMap").parameterizedBy(string(), anyNullable())
}

fun linkedHashMapStringAnyNullable(): ParameterizedTypeName {
return ClassName("kotlin.collections", "LinkedHashMap").parameterizedBy(string(), anyNullable())
}

fun hashMapStringAny(): ParameterizedTypeName {
return ClassName("kotlin.collections", "HashMap").parameterizedBy(string(), any())
}
Expand Down
12 changes: 5 additions & 7 deletions demo/src/main/java/kaufland/com/demo/entity/Product.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package kaufland.com.demo.entity

import com.couchbase.lite.Blob
import kaufland.com.coachbasebinderapi.Comment
import kaufland.com.coachbasebinderapi.Entity
import kaufland.com.coachbasebinderapi.Field
import kaufland.com.coachbasebinderapi.Fields
import kaufland.com.coachbasebinderapi.*
import kaufland.com.coachbasebinderapi.query.Queries
import kaufland.com.coachbasebinderapi.query.Query

@Entity(database = "mydb_db")
@MapWrapper
@Comment(["Hey, I just met you and this is crazy", "But here's my documentation, so read it maybe"])
@Fields(
Field(name = "type", type = String::class, defaultValue = "product", readonly = true),
Field(name = "name", type = String::class, comment = ["contains the product name", "and other infos"]),
Field(name = "type", type = String::class, defaultValue = "product", readonly = true, comment = ["Document type"]),
Field(name = "name", type = String::class, comment = ["contains the product name.", "and other infos"]),
Field(name = "comments", type = UserComment::class, list = true),
Field(name = "image", type = Blob::class),
Field(name = "identifiers", type = String::class, list = true)
)
@Queries(
Query(fields = ["type"])
)
open class Product
open class Product
53 changes: 53 additions & 0 deletions demo/src/test/java/kaufland/com/demo/entity/ProductWrapperTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package kaufland.com.demo.entity

import kaufland.com.coachbasebinderapi.PersistenceConfig
import kaufland.com.coachbasebinderapi.TypeConversion
import org.junit.Assert.*
import org.junit.BeforeClass
import org.junit.Test
import kotlin.reflect.KClass

class ProductWrapperTest {
companion object {
@BeforeClass
@JvmStatic
fun beforeClass() {
PersistenceConfig.configure(object : PersistenceConfig.Connector {
override val typeConversions: Map<KClass<*>, TypeConversion> = mapOf()

override fun getDocument(id: String, dbName: String): Map<String, Any>? {
TODO("Not yet implemented")
}

override fun queryDoc(dbName: String, queryParams: Map<String, Any>): List<Map<String, Any>> {
TODO("Not yet implemented")
}

override fun deleteDocument(id: String, dbName: String) {
TODO("Not yet implemented")
}

override fun upsertDocument(document: MutableMap<String, Any>, id: String?, dbName: String) {
TODO("Not yet implemented")
}
})
}
}

@Test
fun `toMap should preserve field order`() {
val product = ProductWrapper.create().builder()
.setName("name")
.setComments(emptyList())
.setIdentifiers(listOf("1", "2"))
.exit()

val map = product.toMap()
map.remove(ProductWrapper.TYPE)
assertEquals(mapOf(
ProductWrapper.NAME to "name",
ProductWrapper.COMMENTS to listOf<UserCommentWrapper>(),
ProductWrapper.IDENTIFIERS to listOf("1", "2")
), map)
}
}

0 comments on commit ad317e8

Please sign in to comment.