Skip to content

Commit

Permalink
Working on generating views
Browse files Browse the repository at this point in the history
  • Loading branch information
kurbaniec committed Dec 16, 2023
1 parent d851e83 commit 5cc1df1
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,72 +10,72 @@ import java.util.*
* @version 2023-12-16
*/

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
open class Composer(
@Id
val id: UUID,
val name: String
)

@Entity
data class AiComposer(
override val id: UUID,
override val name: String,
val model: String,
@Embedded
val params: AiParams,
@Column(name = "ai_data_id")
val aiDataId: UUID? = null,
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ai_data_id", insertable = false, updatable = false)
val aiData: AiData? = null
) : Composer(id, name)

@Entity
data class AiData(
@Id
val id: UUID,
val data: String
)

@Embeddable
data class AiParams(
val z1: String,
val z2: String
)

@Entity
data class HumanComposer(
override val id: UUID,
override val name: String,
val lastname: String,
@Column(name = "human_data_id")
val humanDataId: UUID? = null,
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "human_data_id", insertable = false, updatable = false)
val humanData: HumanData? = null
) : Composer(id, name)

@Entity
data class HumanData(
@Id
val id: UUID,
val data: String
)

@Entity
data class ComposerContainer(
@Id
val id: UUID,
@Column(name = "c1_id")
val c1Id: UUID,
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "c1_id", insertable = false, updatable = false)
val c1: Composer?,
@Column(name = "c2_id")
val c2Id: UUID,
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "c2_id", insertable = false, updatable = false)
val c2: Composer?
)
// @Entity
// @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
// open class Composer(
// @Id
// val id: UUID,
// val name: String
// )
//
// @Entity
// data class AiComposer(
// override val id: UUID,
// override val name: String,
// val model: String,
// @Embedded
// val params: AiParams,
// @Column(name = "ai_data_id")
// val aiDataId: UUID? = null,
// @OneToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "ai_data_id", insertable = false, updatable = false)
// val aiData: AiData? = null
// ) : Composer(id, name)
//
// @Entity
// data class AiData(
// @Id
// val id: UUID,
// val data: String
// )
//
// @Embeddable
// data class AiParams(
// val z1: String,
// val z2: String
// )
//
// @Entity
// data class HumanComposer(
// override val id: UUID,
// override val name: String,
// val lastname: String,
// @Column(name = "human_data_id")
// val humanDataId: UUID? = null,
// @OneToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "human_data_id", insertable = false, updatable = false)
// val humanData: HumanData? = null
// ) : Composer(id, name)
//
// @Entity
// data class HumanData(
// @Id
// val id: UUID,
// val data: String
// )
//
// @Entity
// data class ComposerContainer(
// @Id
// val id: UUID,
// @Column(name = "c1_id")
// val c1Id: UUID,
// @OneToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "c1_id", insertable = false, updatable = false)
// val c1: Composer?,
// @Column(name = "c2_id")
// val c2Id: UUID,
// @OneToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "c2_id", insertable = false, updatable = false)
// val c2: Composer?
// )
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.beeproduced.bee.generative.BeeGenerativeInput
import com.beeproduced.bee.generative.Shared
import com.beeproduced.bee.generative.processor.Options
import com.beeproduced.bee.generative.util.resolveTypeAlias
import com.beeproduced.bee.persistent.blaze.processor.codegen.BeePersistentBlazeConfig
import com.beeproduced.bee.persistent.blaze.processor.codegen.BeePersistentViewCodegen
import com.beeproduced.bee.persistent.blaze.processor.info.*
import com.beeproduced.bee.persistent.blaze.processor.info.AnnotationInfo.ANNOTATIONS_RELATION
import com.beeproduced.bee.persistent.blaze.processor.info.AnnotationInfo.ANNOTATION_EMBEDDED_ID
Expand Down Expand Up @@ -144,6 +146,16 @@ class BeePersistentBlazeFeature : BeeGenerativeFeature {
throw IllegalArgumentException("Entity [${entityInfo.simpleName}] has no ID")
}
}

val config = BeePersistentBlazeConfig(
"com.beeproduced.persistent.generated",
2
)
val viewCodeGen = BeePersistentViewCodegen(
input.codeGenerator, input.dependencies, input.logger,
inheritedEntities.values.toList(), config
)
viewCodeGen.processEntities()
}

private fun resolveAnnotations(annotations: Sequence<KSAnnotation>): List<ResolvedAnnotation> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.symbol.KSType
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.TypeSpec
import com.squareup.kotlinpoet.ksp.writeTo

/**
Expand All @@ -27,6 +28,7 @@ class BeePersistentViewCodegen(
private val packageName: String = "com.beeproduced.bee.persistent.generated"
private val fileName: String = "GeneratedViews"

private val entitiesMap = entities.associateBy { it.qualifiedName!! }

private val poetMap: PoetMap = mutableMapOf()
private fun FunSpec.Builder.addNStatement(format: String)
Expand All @@ -36,15 +38,106 @@ class BeePersistentViewCodegen(

}

private val viewCount: MutableMap<String, Int> = entities
private fun viewCount(): MutableMap<String, Int> = entities
.map { it.qualifiedName!! }
.associateWithTo(HashMap()) { 0 }

private fun MutableMap<String, Int>.viewCountReached(entity: EntityInfo): Boolean {
val count = this[entity.qualifiedName!!] ?: return true
return count >= config.depth
}

private fun MutableMap<String, Int>.incrementViewCount(entity: EntityInfo) {
val count = this[entity.qualifiedName!!] ?: config.depth
this[entity.qualifiedName!!] = count + 1
}

private fun MutableMap<String, Int>.viewName(entity: EntityInfo, parent: EntityInfo?): String {
val count = this[entity.qualifiedName!!] ?: config.depth
return "${entity.simpleName}__View__${parent?.simpleName ?: "Root"}__$count"
}

fun processEntities() {
FileSpec
.builder(packageName, fileName)
.also {
entities.forEach { entity ->
it.processEntity(entity, viewCount())
}
for ((info, props) in debugInfo) {
logger.info(info)
for (p in props) {
logger.info(" $p")
}
}
}
.build()
.writeTo(codeGenerator, dependencies)
}

}

private val debugInfo = mutableMapOf<String, MutableSet<String>>()

private fun FileSpec.Builder.processEntity(
entity: EntityInfo, viewCount: ViewCount
): String {
val viewName = viewCount.viewName(entity, null)

if (!debugInfo.containsKey(viewName)) {
debugInfo[viewName] = mutableSetOf()
}

//logger.info("View $viewName")
for (relation in entity.relations) {

// logger.info(relation.toString())
// logger.info("${relation.simpleName} X ${relation.qualifiedName}")

val relationEntity = entitiesMap[relation.qualifiedName!!] ?: continue
val relationView = processEntity(relationEntity, viewCount.toMutableMap(), entity)
//logger.info(" View $viewName | ${relation.simpleName} => $relationView")

if (relationView != null)
debugInfo[viewName]?.add(relationView)
}

return viewName
}

private fun FileSpec.Builder.processEntity(
entity: EntityInfo, viewCount: ViewCount, root: EntityInfo
): String? {
if (viewCount.viewCountReached(entity)) return null
viewCount.incrementViewCount(entity)
val viewName = viewCount.viewName(entity, root)

if (!debugInfo.containsKey(viewName)) {
debugInfo[viewName] = mutableSetOf()
}

//logger.info("View $viewName")
for (relation in entity.relations) {

// logger.info(relation.toString())
// logger.info("${relation.simpleName} X ${relation.qualifiedName}")

val relationEntity = entitiesMap[relation.qualifiedName!!] ?: continue
val relationView = processEntity(relationEntity, viewCount.toMutableMap(), root)
//logger.info(" View $viewName | ${relation.simpleName} => $relationView")

if (relationView != null)
debugInfo[viewName]?.add(relationView)
}

return viewName
}

private fun TypeSpec.Builder.buildEntityView(entity: EntityInfo): TypeSpec.Builder {


return this
}

}

typealias ViewCount = MutableMap<String, Int>
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ data class ResolvedValue(
interface AbstractProperty {
val declaration: KSPropertyDeclaration
val type: KSType
val nonCollectionType: KSType
val annotations: List<ResolvedAnnotation>
val simpleName: String get() = declaration.simpleName.asString()
val qualifiedName: String? get() = nonCollectionType.declaration.qualifiedName?.asString()
}

interface ValueClassProperty {
Expand All @@ -59,7 +61,9 @@ data class EntityProperty(
override val declaration: KSPropertyDeclaration,
override val type: KSType,
override val annotations: List<ResolvedAnnotation>
) : AbstractProperty
) : AbstractProperty {
override val nonCollectionType: KSType = getNonNullableSingleRepresentation(type)
}

data class IdProperty(
override val declaration: KSPropertyDeclaration,
Expand All @@ -69,9 +73,11 @@ data class IdProperty(
val isGenerated: Boolean,
val isEmbedded: Boolean,
) : AbstractProperty, ValueClassProperty {
override val nonCollectionType: KSType = getNonNullableSingleRepresentation(type)

fun generatedDefaultValueLiteral(): String {
val typeName = declaration.simpleName.asString()
if (type.isMarkedNullable) return "null"
val typeName = nonCollectionType.declaration.simpleName.asString()
return when (typeName) {
"Double" -> "-1.0"
"Float" -> "-1.0F"
Expand Down Expand Up @@ -100,4 +106,26 @@ data class ColumnProperty(
override val type: KSType,
override val annotations: List<ResolvedAnnotation>,
override val innerValue: ResolvedValue?,
) : AbstractProperty, ValueClassProperty
) : AbstractProperty, ValueClassProperty {
override val nonCollectionType: KSType = getNonNullableSingleRepresentation(type)
}

fun getNonNullableSingleRepresentation(type: KSType): KSType {
// Check if the type is a generic type with type arguments (like Set<T>)
if (type.arguments.isNotEmpty()) {
// Get the first type argument, e.g., T in Set<T>
val typeArgument = type.arguments.first().type

// Check if the type argument is non-null
return typeArgument?.resolve()?.let { typeArg ->
if (typeArg.isMarkedNullable) {
// If typeArg is nullable, get its non-nullable counterpart
typeArg.makeNotNullable()
} else {
// If typeArg is already non-nullable, return it as is
typeArg
}
} ?: type
}
return type
}

0 comments on commit 5cc1df1

Please sign in to comment.