-
Notifications
You must be signed in to change notification settings - Fork 2
Feature/schema class generation #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jansigi
merged 18 commits into
SchwarzIT:main
from
jansigi:feature/schema-class-generation
Apr 10, 2024
Merged
Changes from 10 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
7103f67
added SchemaClass generation
jansigi fffc60b
fixed reducer generation
jansigi 366d354
code clean up
jansigi 47110ea
made function to expression
jansigi 45e4b4c
renamed postfix to suffix
jansigi 6296609
converted function to expression body
jansigi 07744d9
removed obvious named arguments
jansigi 773deba
updated class documentation
jansigi 6a25bfa
made subEntity clearer
jansigi 2515d48
extracted file for Schema and renamed File to DatabaseRecord
jansigi 88025c1
removed reduced models for SchemaClasses
jansigi 7ecefaf
renamed to CMType and removed Generic
jansigi 5424de4
moved path into CMType
jansigi 44caf95
extended test to assert generated file
jansigi 0594fa4
add ExpectedSchema File for testing
jansigi ee0162b
fixed linter
jansigi c70859b
fixed unresolved
jansigi 1e8b16f
fixed path
jansigi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
crystal-map-api/src/main/java/com/schwarz/crystalapi/SchemaClass.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.schwarz.crystalapi | ||
|
||
@Retention(AnnotationRetention.BINARY) | ||
@Target(AnnotationTarget.CLASS) | ||
annotation class SchemaClass |
11 changes: 11 additions & 0 deletions
11
crystal-map-api/src/main/java/com/schwarz/crystalapi/schema/DatabaseRecord.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.schwarz.crystalapi.schema | ||
|
||
interface DatabaseRecord<out T> | ||
|
||
class CMField<T : Any>(val name: String, val path: String) : DatabaseRecord<T> | ||
|
||
class CMList<T : Any>(val name: String, val path: String) : DatabaseRecord<T> | ||
jansigi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
class CMObject<out T : Schema>(val element: T, val path: String) : DatabaseRecord<T> | ||
|
||
class CMObjectList<out T : Schema>(val element: T, val name: String, val path: String) : DatabaseRecord<T> |
3 changes: 3 additions & 0 deletions
3
crystal-map-api/src/main/java/com/schwarz/crystalapi/schema/Schema.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package com.schwarz.crystalapi.schema | ||
|
||
interface Schema |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
187 changes: 187 additions & 0 deletions
187
...processor/src/main/java/com/schwarz/crystalprocessor/generation/model/SchemaGeneration.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
package com.schwarz.crystalprocessor.generation.model | ||
|
||
import com.schwarz.crystalapi.schema.CMField | ||
import com.schwarz.crystalapi.schema.CMList | ||
import com.schwarz.crystalapi.schema.CMObject | ||
import com.schwarz.crystalapi.schema.CMObjectList | ||
import com.schwarz.crystalapi.schema.Schema | ||
import com.schwarz.crystalprocessor.model.entity.SchemaClassHolder | ||
import com.schwarz.crystalprocessor.model.field.CblBaseFieldHolder | ||
import com.schwarz.crystalprocessor.model.field.CblFieldHolder | ||
import com.schwarz.crystalprocessor.util.ConversionUtil | ||
import com.schwarz.crystalprocessor.util.TypeUtil | ||
import com.squareup.kotlinpoet.FileSpec | ||
import com.squareup.kotlinpoet.FunSpec | ||
import com.squareup.kotlinpoet.KModifier | ||
import com.squareup.kotlinpoet.ParameterSpec | ||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy | ||
import com.squareup.kotlinpoet.PropertySpec | ||
import com.squareup.kotlinpoet.TypeName | ||
import com.squareup.kotlinpoet.TypeSpec | ||
import com.squareup.kotlinpoet.asTypeName | ||
|
||
/** | ||
* This class is responsible for generating the Schema classes. | ||
* | ||
* To generate a SchemaClass, add the following annotation to your Class: | ||
* ``` | ||
* @SchemaClass | ||
* ``` | ||
* All the fields will then be generated into a new file. | ||
*/ | ||
class SchemaGeneration { | ||
private val pathAttributeName = "path" | ||
fun generateModel(holder: SchemaClassHolder, schemaClassPaths: List<String>): FileSpec { | ||
val packageName = holder.sourcePackage | ||
val schemaClassName = holder.entitySimpleName | ||
|
||
val schemaClass: TypeSpec.Builder = buildSchemaClass(schemaClassName) | ||
|
||
buildAndAddFieldProperties(holder, schemaClass, schemaClassPaths) | ||
|
||
return FileSpec.builder(packageName, schemaClassName).addType(schemaClass.build()).build() | ||
} | ||
|
||
private fun buildSchemaClass(className: String): TypeSpec.Builder { | ||
val pathParameter = ParameterSpec.builder(pathAttributeName, String::class).defaultValue("%S", "").build() | ||
|
||
return TypeSpec.classBuilder(className) | ||
.addModifiers(KModifier.OPEN) | ||
jansigi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.addSuperinterface(Schema::class) | ||
.primaryConstructor( | ||
FunSpec.constructorBuilder() | ||
.addParameter(pathParameter) | ||
.build() | ||
) | ||
} | ||
|
||
private fun buildAndAddFieldProperties( | ||
holder: SchemaClassHolder, | ||
schemaClass: TypeSpec.Builder, | ||
schemaClassPaths: List<String>, | ||
) { | ||
buildAndAddConstantFieldProperties(holder, schemaClass, schemaClassPaths) | ||
buildAndAddNormalFieldProperties(holder, schemaClass, schemaClassPaths) | ||
} | ||
|
||
private fun buildAndAddConstantFieldProperties( | ||
holder: SchemaClassHolder, | ||
schemaClass: TypeSpec.Builder, | ||
schemaClassPaths: List<String> | ||
) { | ||
holder.fieldConstants.forEach { (fieldName, fieldObject) -> | ||
val defaultVariableName = "DEFAULT_${fieldObject.constantName}" | ||
jansigi marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
val constantProperty = PropertySpec.builder( | ||
defaultVariableName, | ||
fieldObject.fieldType | ||
).initializer( | ||
ConversionUtil.convertStringToDesiredFormat( | ||
fieldObject.typeMirror, | ||
fieldObject.constantValue | ||
) | ||
) | ||
|
||
schemaClass.addProperty(constantProperty.build()) | ||
|
||
buildAndAddFieldProperty( | ||
schemaClass, | ||
fieldName, | ||
fieldObject, | ||
schemaClassPaths | ||
) | ||
} | ||
} | ||
|
||
private fun buildAndAddNormalFieldProperties( | ||
holder: SchemaClassHolder, | ||
schemaClass: TypeSpec.Builder, | ||
schemaClassPaths: List<String> | ||
) { | ||
holder.fields.forEach { (fieldName, fieldObject) -> | ||
buildAndAddFieldProperty( | ||
schemaClass, | ||
fieldName, | ||
fieldObject, | ||
schemaClassPaths, | ||
) | ||
} | ||
} | ||
|
||
private fun buildAndAddFieldProperty( | ||
schemaClass: TypeSpec.Builder, | ||
fieldName: String, | ||
fieldObject: CblBaseFieldHolder, | ||
schemaClassPaths: List<String>, | ||
): TypeSpec.Builder = schemaClass.addProperty( | ||
buildFieldProperty(fieldObject, fieldName, schemaClassPaths) | ||
) | ||
|
||
private fun buildFieldProperty( | ||
fieldObject: CblBaseFieldHolder, | ||
fieldName: String, | ||
schemaClassPaths: List<String>, | ||
): PropertySpec { | ||
val isObject = schemaClassPaths.contains(fieldObject.typeMirror.toString()) | ||
|
||
val outerType = getOuterPropertyType(fieldObject.isIterable, isObject) | ||
|
||
val innerType: TypeName = getInnerPropertyType(fieldObject) | ||
|
||
return PropertySpec.builder( | ||
fieldName, | ||
outerType.parameterizedBy(innerType) | ||
).initializer( | ||
createPropertyFormat(fieldName, innerType, fieldObject.isIterable, isObject), | ||
outerType, | ||
).build() | ||
} | ||
|
||
private fun createPropertyFormat( | ||
fieldName: String, | ||
propertyType: TypeName, | ||
isIterable: Boolean, | ||
isObject: Boolean | ||
): String { | ||
val propertyAccessPath = | ||
"if ($pathAttributeName.isBlank()) \"$fieldName\" else \"\$$pathAttributeName.$fieldName\"" | ||
|
||
return when { | ||
isIterable && isObject -> buildObjectListFormat(propertyType, fieldName, propertyAccessPath) | ||
isObject -> buildObjectFormat(propertyType, propertyAccessPath) | ||
else -> buildSimpleFormat(fieldName) | ||
} | ||
} | ||
|
||
private fun buildObjectListFormat(propertyType: TypeName, fieldName: String, propertyAccessPath: String): String = | ||
"""%T( | ||
$propertyType($propertyAccessPath), | ||
"$fieldName", | ||
$pathAttributeName, | ||
)""" | ||
|
||
private fun buildSimpleFormat(fieldName: String): String = | ||
"""%T("$fieldName", $pathAttributeName)""" | ||
|
||
private fun buildObjectFormat(propertyType: TypeName, propertyAccessPath: String): String = | ||
"""%T( | ||
$propertyType($propertyAccessPath), | ||
$pathAttributeName, | ||
)""" | ||
|
||
private fun getOuterPropertyType( | ||
isIterable: Boolean, | ||
isObject: Boolean | ||
) = when { | ||
isIterable && isObject -> CMObjectList::class.asTypeName() | ||
isIterable -> CMList::class.asTypeName() | ||
isObject -> CMObject::class.asTypeName() | ||
else -> CMField::class.asTypeName() | ||
} | ||
|
||
private fun getInnerPropertyType(field: CblBaseFieldHolder): TypeName { | ||
val subEntity = (field as? CblFieldHolder)?.subEntitySimpleName | ||
|
||
return TypeUtil.parseMetaType(field.typeMirror, false, subEntity) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.