Skip to content

Commit

Permalink
Merge pull request #18 from SchwarzIT/feature/query
Browse files Browse the repository at this point in the history
New Query Feature and Accessor to static methods from parent
  • Loading branch information
sbra0902 authored Jun 23, 2020
2 parents b5f69f8 + 9541bdb commit e157385
Show file tree
Hide file tree
Showing 24 changed files with 354 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package kaufland.com.coachbasebinderapi;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.CLASS)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface GenerateAccessor {

Class<?> value() default Void.class;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import java.util.HashMap;
import java.util.List;
import java.util.Map;

import kotlin.reflect.KClass;
Expand All @@ -22,6 +23,8 @@ public interface Connector {

Map<String, Object> getDocument(String id, String dbName);

List<Map<String, Object>> queryDoc(String dbName, Map<String, Object> queryParams);

void deleteDocument(String id, String dbName) throws PersistenceException;

void upsertDocument(Map<String, Object> document, String id, String dbName) throws PersistenceException;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package kaufland.com.coachbasebinderapi.query;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import kaufland.com.coachbasebinderapi.Field;

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE})
public @interface Queries {

Query[] value() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package kaufland.com.coachbasebinderapi.query

@Retention(AnnotationRetention.BINARY)
annotation class Query(val fields: Array<String>)
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package kaufland.com.couchbaseentityconnector

import com.couchbase.lite.CouchbaseLiteException
import com.couchbase.lite.Database
import com.couchbase.lite.Document
import com.couchbase.lite.MutableDocument

import java.util.ArrayList
import java.util.HashMap

import com.couchbase.lite.*
import kaufland.com.coachbasebinderapi.PersistenceConfig
import kaufland.com.coachbasebinderapi.PersistenceException
import kaufland.com.coachbasebinderapi.TypeConversion
import java.util.*
import kotlin.reflect.KClass

abstract class Couchbase2Connector : PersistenceConfig.Connector {
Expand Down Expand Up @@ -102,6 +96,56 @@ abstract class Couchbase2Connector : PersistenceConfig.Connector {

}

@Throws(PersistenceException::class)
override fun queryDoc(dbName: String, queryParams: Map<String, Any>): List<Map<String, Any>> {
try {

val builder = QueryBuilder.select(SelectResult.expression(Meta.id), SelectResult.all())
.from(DataSource.database(getDatabase(dbName)))

parseExpressions(queryParams)?.let {
builder.where(it)
}

return queryResultToMap(builder.execute())
} catch (e: CouchbaseLiteException) {
throw PersistenceException(e)
}
}

private fun queryResultToMap(execute : ResultSet) : List<Map<String, Any>>{
val parsed: MutableList<Map<String, Any>> =
ArrayList()
if (execute != null) {
for (result in execute) {
val item: MutableMap<String, Any> =
HashMap()
item["_id"] = result.getString(0)
item.putAll(result.getDictionary(1).toMap())
parsed.add(item)
}
}
return parsed
}

private fun parseExpressions(queryParams: Map<String, Any>): Expression? {

var result: Expression? = null

for (queryParam in queryParams) {

val equalTo = Expression.property(queryParam.key).equalTo(
Expression.value(queryParam.value))
result = if (result == null) {
equalTo
} else {
result.and(equalTo)
}
}

return result
}

@Throws(PersistenceException::class)
override fun upsertDocument(upsert: MutableMap<String, Any>, docId: String, name: String) {
if (upsert["_id"] == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ import com.kaufland.generation.CodeGenerator
import com.kaufland.generation.EntityGeneration
import com.kaufland.generation.WrapperGeneration
import com.kaufland.model.EntityFactory
import com.kaufland.model.accessor.CblGenerateAccessorHolder
import com.kaufland.validation.PreValidator
import com.squareup.kotlinpoet.FileSpec
import kaufland.com.coachbasebinderapi.Entity
import kaufland.com.coachbasebinderapi.Field
import kaufland.com.coachbasebinderapi.GenerateAccessor
import kaufland.com.coachbasebinderapi.MapWrapper
import kaufland.com.coachbasebinderapi.query.Queries
import kaufland.com.coachbasebinderapi.query.Query
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement
import javax.swing.UIManager.put



@SupportedAnnotationTypes("kaufland.com.coachbasebinderapi.Field", "kaufland.com.coachbasebinderapi.Entity", "kaufland.com.coachbasebinderapi.MapWrapper")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor::class)
class CoachBaseBinderProcessor : AbstractProcessor() {
Expand All @@ -39,12 +43,12 @@ class CoachBaseBinderProcessor : AbstractProcessor() {

override fun process(set: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {


var mapWrappers = roundEnv.getElementsAnnotatedWith(MapWrapper::class.java)
var mapWrapperStrings = mapWrappers.map { element -> element.toString() }

validateAndProcess(roundEnv.getElementsAnnotatedWith(Entity::class.java), object : EntityProcessor {
override fun process(element: Element): FileSpec {

val holder = EntityFactory.createEntityHolder(element, mapWrapperStrings)
return EntityGeneration().generateModel(holder)
}
Expand Down Expand Up @@ -81,5 +85,9 @@ class CoachBaseBinderProcessor : AbstractProcessor() {
}
}

override fun getSupportedAnnotationTypes(): MutableSet<String> {
return setOf(Field::class.java.canonicalName, Entity::class.java.canonicalName, MapWrapper::class.java.canonicalName, Queries::class.java.canonicalName, Query::class.java.canonicalName, GenerateAccessor::class.java.canonicalName).toMutableSet()
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ object CblConstantGeneration {
fun addConstants(holder: BaseEntityHolder): FunSpec {
val builder = FunSpec.builder("addConstants").addModifiers(KModifier.PRIVATE).addParameter("map", TypeUtil.mutableMapStringObject())

for (fieldHolder in holder.fieldConstants) {
for (fieldHolder in holder.fieldConstants.values) {

if (fieldHolder.isConstant) {
builder.addStatement("map.put(%N, DOC_%N)", fieldHolder.constantName, fieldHolder.constantName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object CblDefaultGeneration {
fun addDefaults(holder: BaseEntityHolder): FunSpec {
val builder = FunSpec.builder("addDefaults").addModifiers(KModifier.PRIVATE).addParameter( "map", TypeUtil.mutableMapStringObject())

for (fieldHolder in holder.fields) {
for (fieldHolder in holder.fields.values) {

if (fieldHolder.isDefault) {
builder.addStatement("map.put(%N, " + getConvertedValue(fieldHolder.typeMirror!!, fieldHolder.defaultValue) + ")", fieldHolder.constantName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ class EntityGeneration {
companionSpec.addProperty(idConstant())
companionSpec.addFunctions(create(holder))

for (query in holder.queries) {
query.queryFun(holder.dbName, holder)?.let {
companionSpec.addFunction(it)
}
}

for (generateAccessor in holder.generateAccessors) {
generateAccessor.accessorFunSpec()?.let {
companionSpec.addFunction(it)
}
generateAccessor.accessorPropertySpec()?.let {
companionSpec.addProperty(it)
}
}

val builderBuilder = BuilderClassGeneration.generateBaseBuilder(holder)

val typeBuilder = TypeSpec.classBuilder(holder.entitySimpleName).addModifiers(KModifier.PUBLIC).addSuperinterface(TypeUtil.mapSupport())
Expand Down Expand Up @@ -69,7 +84,7 @@ class EntityGeneration {

val toMapBuilder = FunSpec.builder("toMap").addModifiers(KModifier.OVERRIDE).returns(TypeUtil.mutableMapStringObject()).addStatement("val doc = %T.$GET_DOCUMENT_METHOD(getId(), %S)", PersistenceConfig::class, holder.dbName)

for (constantField in holder.fieldConstants) {
for (constantField in holder.fieldConstants.values) {
toMapBuilder.addStatement("mDocChanges.put(%S, %S)", constantField.dbField, constantField.constantValue)
}

Expand Down
50 changes: 47 additions & 3 deletions couchbase-entity/src/main/java/com/kaufland/model/EntityFactory.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.kaufland.model

import com.kaufland.model.accessor.CblGenerateAccessorHolder
import com.kaufland.model.entity.BaseEntityHolder
import com.kaufland.model.entity.EntityHolder
import com.kaufland.model.entity.WrapperEntityHolder
import com.kaufland.model.field.CblConstantHolder
import com.kaufland.model.field.CblFieldHolder
import com.kaufland.model.query.CblQueryHolder

import javax.lang.model.element.Element

import kaufland.com.coachbasebinderapi.Entity
import kaufland.com.coachbasebinderapi.Fields
import kaufland.com.coachbasebinderapi.GenerateAccessor
import kaufland.com.coachbasebinderapi.query.Queries
import org.apache.commons.lang3.text.WordUtils
import javax.lang.model.element.ElementKind
import javax.lang.model.element.Modifier
Expand All @@ -30,6 +34,15 @@ object EntityFactory {
content.abstractParts = findPossibleOverrides(cblEntityElement)
content.sourceElement = cblEntityElement

parseQueries(cblEntityElement, content)
parseFields(cblEntityElement, content, allWrappers)
parseGenerateAccessors(cblEntityElement, content)

return content

}

private fun parseFields(cblEntityElement: Element, content: BaseEntityHolder, allWrappers: List<String>) {
val fields = cblEntityElement.getAnnotation(Fields::class.java)


Expand All @@ -40,15 +53,46 @@ object EntityFactory {
}

if (cblField!!.readonly) {
content.fieldConstants.add(CblConstantHolder(cblField))
content.fieldConstants[cblField.name] = CblConstantHolder(cblField)
} else {
val cblFieldHolder = CblFieldHolder(cblField, allWrappers)
content.fields.add(cblFieldHolder)
content.fields[cblField.name] = cblFieldHolder
}
}
}

return content
private fun parseGenerateAccessors(cblEntityElement: Element, content: BaseEntityHolder){

for (childElement in cblEntityElement.enclosedElements) {
if(childElement.modifiers.contains(Modifier.STATIC)){
if(childElement.kind == ElementKind.CLASS && childElement.simpleName.toString() == "Companion"){
for (companionMembers in childElement.enclosedElements) {
addIfAnnotationIsPresent(content.sourceClazzSimpleName, companionMembers, content.generateAccessors)
}
continue
}
addIfAnnotationIsPresent(content.sourceClazzSimpleName, childElement, content.generateAccessors)
}
}
}

private fun addIfAnnotationIsPresent(className: String, companionMembers: Element, generateAccessors: MutableList<CblGenerateAccessorHolder>) {
if (companionMembers.getAnnotation(GenerateAccessor::class.java) != null) {
generateAccessors.add(CblGenerateAccessorHolder(className, companionMembers))
}
}

private fun parseQueries(cblEntityElement: Element, content: BaseEntityHolder) {
val queries = cblEntityElement.getAnnotation(Queries::class.java) ?: return

for (cblQuery in queries.value) {

if (cblQuery == null) {
continue
}

content.queries.add(CblQueryHolder(cblQuery))
}
}

private fun findPossibleOverrides(cblEntityElement: Element): HashSet<String> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.kaufland.model.accessor

import com.kaufland.javaToKotlinType
import com.kaufland.util.ConversionUtil
import com.kaufland.util.FieldExtractionUtil
import com.kaufland.util.TypeUtil
import com.squareup.kotlinpoet.*
import kaufland.com.coachbasebinderapi.Field
import org.apache.commons.lang3.text.WordUtils
import javax.lang.model.element.Element
import javax.lang.model.element.ElementKind
import javax.lang.model.element.ExecutableElement
import javax.lang.model.type.TypeMirror

class CblGenerateAccessorHolder(private val className: String, val element: Element) {

fun accessorFunSpec(): FunSpec? {

if(element.kind == ElementKind.METHOD){
var methodBuilder = FunSpec.builder(element.simpleName.toString()).addAnnotation(JvmStatic::class)

(element as ExecutableElement)?.apply {
parameters.forEach {
methodBuilder.addParameter(it.simpleName.toString(), it.asType().asTypeName().javaToKotlinType())
}
methodBuilder.addStatement("%N.%N(${parameters.joinToString { it.simpleName.toString() }})", className, element.simpleName.toString())
}
return methodBuilder.build()
}
return null
}


fun accessorPropertySpec(): PropertySpec? {
if(element.kind == ElementKind.FIELD){
return PropertySpec.builder(element.simpleName.toString(), element.asType().asTypeName().javaToKotlinType()).addAnnotation(JvmField::class).initializer("%N.%N", className, element.simpleName.toString()).build()
}
return null
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
package com.kaufland.model.entity

import com.kaufland.model.accessor.CblGenerateAccessorHolder
import com.kaufland.model.field.CblBaseFieldHolder
import com.kaufland.model.field.CblConstantHolder
import com.kaufland.model.field.CblFieldHolder
import com.kaufland.model.query.CblQueryHolder
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.TypeName
import com.sun.tools.javac.code.Symbol
import kaufland.com.coachbasebinderapi.query.Query

import java.util.ArrayList

import javax.lang.model.element.Element

abstract class BaseEntityHolder {

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

var abstractParts: Set<String> = HashSet()

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

var sourceElement: Element? = null

val queries : MutableList<CblQueryHolder> = ArrayList()

val generateAccessors : MutableList<CblGenerateAccessorHolder> = ArrayList()

val allFields: List<CblBaseFieldHolder>
get() {
val allField = ArrayList<CblBaseFieldHolder>()
allField.addAll(fields)
allField.addAll(fieldConstants)
allField.addAll(fields.values)
allField.addAll(fieldConstants.values)
return allField
}

Expand Down
Loading

0 comments on commit e157385

Please sign in to comment.