From 71d16dd569e5b362de3f3e8733ecdd1ed0fca46b Mon Sep 17 00:00:00 2001 From: slon565 Date: Wed, 9 Aug 2023 13:11:07 +0400 Subject: [PATCH] Info generator structure --- build.gradle.kts | 10 ++ .../ru/sicamp/sicamphelper/db/entity/Room.kt | 4 + .../ru/sicamp/sicamphelper/db/entity/User.kt | 8 ++ .../sicamphelper/generator/InfoGenerator.kt | 95 +++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 src/main/kotlin/ru/sicamp/sicamphelper/generator/InfoGenerator.kt diff --git a/build.gradle.kts b/build.gradle.kts index 70e5b08..ce5683e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,6 +16,7 @@ java.sourceCompatibility = JavaVersion.VERSION_17 repositories { mavenCentral() maven { url = uri("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven") } + maven { url = uri("https://jitpack.io") } } val exposedVersion = "0.41.1" @@ -54,10 +55,19 @@ dependencies { implementation("io.github.microutils:kotlin-logging-jvm:$loggingVersion") implementation("org.postgresql:postgresql:$postgresVersion") + implementation("nl.devhaan:KotlinPoetDSL:0.1.1") + //testImplementation("org.springframework.security:spring-security-test:$securityTestVersion") testImplementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") } +sourceSets { + main { + java.srcDirs(File("C:\\Users\\Andrey\\IdeaProjects\\sicamp-helper\\build\\generated\\source")) + kotlin.srcDirs(File("C:\\Users\\Andrey\\IdeaProjects\\sicamp-helper\\build\\generated\\source")) + } +} + configurations.all { resolutionStrategy { eachDependency { diff --git a/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/Room.kt b/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/Room.kt index eb7dd10..65f564c 100644 --- a/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/Room.kt +++ b/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/Room.kt @@ -4,11 +4,15 @@ import org.jetbrains.exposed.dao.LongEntity import org.jetbrains.exposed.dao.LongEntityClass import org.jetbrains.exposed.dao.id.EntityID import ru.sicamp.sicamphelper.db.table.Rooms +import ru.sicamp.sicamphelper.generator.Info class Room(id: EntityID) : LongEntity(id) { companion object : LongEntityClass(Rooms) + @Info var name by Rooms.name + @Info var type by Rooms.type + @Info var description by Rooms.description } diff --git a/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/User.kt b/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/User.kt index 5109858..161f24f 100644 --- a/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/User.kt +++ b/src/main/kotlin/ru/sicamp/sicamphelper/db/entity/User.kt @@ -6,20 +6,28 @@ import org.jetbrains.exposed.dao.id.EntityID import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.userdetails.UserDetails import ru.sicamp.sicamphelper.db.table.Users +import ru.sicamp.sicamphelper.generator.Info import java.time.LocalDateTime class User(id: EntityID) : LongEntity(id), UserDetails { companion object : LongEntityClass(Users) + @Info var login by Users.login + @Info var name by Users.name var supervisor by User optionalReferencedOn Users.supervisor var _password by Users.password + @Info var tgId by Users.tgId + @Info var tgUsername by Users.tgUsername + @Info var role by Users.role var group by Group referencedOn Users.group + @Info var sex by Users.sex + @Info var age by Users.age var locked by Users.locked var enabled by Users.enabled diff --git a/src/main/kotlin/ru/sicamp/sicamphelper/generator/InfoGenerator.kt b/src/main/kotlin/ru/sicamp/sicamphelper/generator/InfoGenerator.kt new file mode 100644 index 0000000..e03a797 --- /dev/null +++ b/src/main/kotlin/ru/sicamp/sicamphelper/generator/InfoGenerator.kt @@ -0,0 +1,95 @@ +package ru.sicamp.sicamphelper.generator + +import com.squareup.kotlinpoet.asTypeName +import mu.KLogging +import nl.devhaan.kotlinpoetdsl.classes.clazz +import nl.devhaan.kotlinpoetdsl.constructorBuilder.buildConstructor +import nl.devhaan.kotlinpoetdsl.constructorBuilder.constructor +import nl.devhaan.kotlinpoetdsl.constructorBuilder.thiz +import nl.devhaan.kotlinpoetdsl.files.file +import nl.devhaan.kotlinpoetdsl.of +import nl.devhaan.kotlinpoetdsl.packaged +import nl.devhaan.kotlinpoetdsl.public +import nl.devhaan.kotlinpoetdsl.valOf +import ru.sicamp.sicamphelper.db.entity.Room +import ru.sicamp.sicamphelper.db.entity.User +import java.io.File +import kotlin.reflect.KClass +import kotlin.reflect.full.memberProperties + +class InfoGenerator { + fun generateInfo(kClass: KClass) { + val className = "${kClass.simpleName}Info" + logger.info("Beginning generating $className") + val file = File("C:\\Users\\Andrey\\IdeaProjects\\sicamp-helper\\build\\generated\\source") + file(GENERATED_PACKAGE, className) { + val constructorParameters = kClass.infoVariables() + val secondaryConstructor = buildConstructor { + val entityName = "entity" + constructor(entityName of kClass).thiz( + *constructorParameters.map { + "$entityName.${it.name}" + }.toTypedArray() + ) {} + } + logger.info("Found ${constructorParameters.size} parameters") + clazz(className, *constructorParameters.toTypedArray()) { + public.constructor(secondaryConstructor) + }.packaged(GENERATED_PACKAGE) + }.writeTo(file) + } + + private fun KClass<*>.infoPropertiesWithAnnotations() = memberProperties.mapNotNull { property -> + property.annotations.firstOrNull { it is Info }?.let { annotation -> + property to annotation + } + }.also { logger.info("Found ${it.size} properties") } + + private fun KClass<*>.infoVariables() = infoPropertiesWithAnnotations() + .map { (property, annotation) -> + logger.info("Getting type for ${property.name}") + val typeName = property.returnType.asTypeName() + property.name.valOf( + if (annotation is Info) { + if (property.returnType.isMarkedNullable) { + typeName.asNullable() + } else { + typeName + } + } else { + error("Annotation $annotation is not of type Info") + } + ) + } + + companion object : KLogging() { + const val GENERATED_PACKAGE = "ru.sicamp.helper.generated" + } +} + +@Target(AnnotationTarget.CLASS) +annotation class GeneratorTarget + +@Target(AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.SOURCE) +annotation class Info + +@Target(AnnotationTarget.PROPERTY) +@Retention(AnnotationRetention.SOURCE) +annotation class Dto + +@GeneratorTarget +class A( + @Info + val a: String? = "a", + @Info + val c: String = "c", + @Dto + val b: String = "b" +) + + +fun main() { + InfoGenerator().generateInfo(User::class) + InfoGenerator().generateInfo(Room::class) +} \ No newline at end of file