Skip to content

Commit

Permalink
feat: support withHooks on field (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
Idane authored Jun 1, 2024
1 parent 54a819a commit 5ffbfc7
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@

/**
* Entity annotation, used to define generic persistent hooks which will run on the given entity
* When applied on a field, applies itself to the entity
*/
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(WithHooks.List.class)
public @interface WithHooks {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public <ID extends Serializable, Entity extends BaseCrudEntity<ID>> void validat
throw new RuntimeException("Cannot filter field [ " + fieldName + " ] as it was not found on entity [ " + metadataDTO.getSimpleName() + " ]");
}

Field field = metadataDTO.getFields().get(fieldName);
Field field = metadataDTO.getFields().get(fieldName).getField();
Class<?> fieldClazz = field.getType();

if (Collection.class.isAssignableFrom(field.getType())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,21 @@ class EntityMetadataDTO {

val hooksFromAnnotations: MutableSet<CRUDHooks<*, *>> = mutableSetOf()

val fields: MutableMap<String, Field> = mutableMapOf()
val fields: MutableMap<String, FieldDTO> = mutableMapOf()

val daoClazz: Class<out CrudDao>

constructor(entityClazz: KClass<out BaseCrudEntity<*>>) : this(entityClazz.java)

constructor(entityClazz: Class<out BaseCrudEntity<*>>) {
getFields(entityClazz)
deleteField = getEntityDeleteField(entityClazz)
deleteableType = getEntityDeleteableType(entityClazz)
cacheMetadata = getEntityCacheMetadata(entityClazz)
immutable = isEntityImmutable(entityClazz)
alwaysPersistCopy = shouldAlwaysPersistCopy(entityClazz)
collectHookAnnotations(entityClazz)
daoClazz = getEntityDao(entityClazz)
getFields(entityClazz)
simpleName = entityClazz.simpleName
}

Expand Down Expand Up @@ -80,15 +80,15 @@ class EntityMetadataDTO {
if (PersistentEntity::class.java.isAssignableFrom(fieldClazz) && currentDepth < MAX_FILTERFIELD_DEPTH) {
getFields(fieldClazz as Class<out PersistentEntity>, effectivePrefix + it.name, currentDepth + 1)
} else {
fields[effectivePrefix + it.name] = it
fields[effectivePrefix + it.name] = FieldDTO(it, it.declaredAnnotations.toList())
}
}
}

private fun collectHookAnnotations(entityClazz: Class<out BaseCrudEntity<*>>) {
val hookAnnotations = mutableSetOf<WithHooks>()
val annotations = entityClazz.declaredAnnotations + entityClazz.kotlin.allSuperclasses
.flatMap { it.java.declaredAnnotations.toList() }
.flatMap { it.java.declaredAnnotations.toList() } + fields.flatMap { (_, dto) -> dto.annotations }

// The first search targets the WithHooks.List annotation, which is the repeatable container for WithHooks
annotations
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.krud.crudframework.crud.model

import java.lang.reflect.Field

data class FieldDTO(
val field: Field,
val annotations: List<Annotation>
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ class EntityMetadataDTOHookTest {
private class GenericPersistentHooks2<ID : Serializable> :
CRUDHooks<ID, BaseCrudEntity<ID>>

@Target(AnnotationTarget.CLASS, AnnotationTarget.FIELD)
@WithHooks(hooks = [GenericPersistentHooks::class])
private annotation class WithGenericPersistentHooks

@Target(AnnotationTarget.CLASS, AnnotationTarget.FIELD)
@WithHooks(hooks = [GenericPersistentHooks2::class])
private annotation class WithGenericPersistentHooks2

Expand Down Expand Up @@ -73,4 +75,18 @@ class EntityMetadataDTOHookTest {

assertArrayEquals(arrayOf(GenericPersistentHooks::class.java, GenericPersistentHooks2::class.java), metadata.hookTypesFromAnnotations.toTypedArray())
}

@Test
fun `withHooks should apply on field`() {
class TestEntity : AbstractTestEntity() {
@WithHooks(hooks = [GenericPersistentHooks::class])
val someField: String = "ABCD"

@WithGenericPersistentHooks2
val someOtherField: String = "ABCD"
}

val metadata = EntityMetadataDTO(TestEntity::class.java)
assertArrayEquals(arrayOf(GenericPersistentHooks::class.java, GenericPersistentHooks2::class.java), metadata.hookTypesFromAnnotations.toTypedArray())
}
}

0 comments on commit 5ffbfc7

Please sign in to comment.