more work on data events

This commit is contained in:
Gavin King 2024-12-20 20:30:00 +01:00
parent 24df225d80
commit 3b3bd5ec1a
4 changed files with 157 additions and 43 deletions

View File

@ -108,12 +108,6 @@ public final class ClassWriter {
pw.println();
// TODO: move this!
if ( context.addDependentAnnotation() && context.isDataEventPackageAvailable()
&& entity.isImplementation() && !entity.isReactive() ) {
pw.println("\t@Inject private Event<? super LifecycleEvent<?>> event;\n");
}
final List<MetaAttribute> members = entity.getMembers();
for ( MetaAttribute metaMember : members ) {
if ( metaMember instanceof InnerClassMetaAttribute innerClass ) {

View File

@ -637,8 +637,23 @@ public class AnnotationMetaEntity extends AnnotationMeta {
if ( needsDefaultConstructor() ) {
addDefaultConstructor();
}
if ( needsEventBus() ) {
addEventBus();
}
}
}
private boolean needsEventBus() {
return jakartaDataRepository
&& !usingReactiveSession( sessionType ) // non-reactive
&& context.isDataEventPackageAvailable() // events
&& context.addInjectAnnotation() // @nject
&& context.addDependentAnnotation(); // CDI
}
void addEventBus() {
putMember("_event", new EventField(this) );
}
/**
* For usage with CDI, but outside Quarkus, Jakarta Data
@ -1382,6 +1397,7 @@ public class AnnotationMetaEntity extends AnnotationMeta {
new LifecycleMethod(
this, method,
entity,
typeAsString(lifecycleParameterArgument(parameterType)),
methodName,
parameter.getSimpleName().toString(),
getSessionVariableName(),
@ -1424,6 +1440,23 @@ public class AnnotationMetaEntity extends AnnotationMeta {
}
}
private TypeMirror lifecycleParameterArgument(TypeMirror parameterType) {
switch (parameterType.getKind()) {
case ARRAY:
final ArrayType arrayType = (ArrayType) parameterType;
return arrayType.getComponentType();
case DECLARED:
final DeclaredType declaredType = (DeclaredType) parameterType;
final TypeElement typeElement = (TypeElement) declaredType.asElement();
return typeElement.getQualifiedName().contentEquals(LIST)
&& !declaredType.getTypeArguments().isEmpty()
? declaredType.getTypeArguments().get(0)
: context.getElementUtils().getTypeElement(JAVA_OBJECT).asType();
default:
return parameterType;
}
}
private static boolean isVoid(TypeMirror returnType) {
switch (returnType.getKind()) {
case VOID:

View File

@ -0,0 +1,66 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.processor.annotation;
import org.hibernate.processor.model.MetaAttribute;
import org.hibernate.processor.model.Metamodel;
import org.hibernate.processor.util.Constants;
/**
* Used by the container to instantiate a Jakarta Data repository.
*
* @author Gavin King
*/
public class EventField implements MetaAttribute {
private final AnnotationMetaEntity annotationMetaEntity;
public EventField(AnnotationMetaEntity annotationMetaEntity) {
this.annotationMetaEntity = annotationMetaEntity;
}
@Override
public boolean hasTypedAttribute() {
return true;
}
@Override
public boolean hasStringAttribute() {
return false;
}
@Override
public String getAttributeDeclarationString() {
annotationMetaEntity.importType("jakarta.inject.Inject");
annotationMetaEntity.importType("jakarta.data.event.LifecycleEvent");
return "\n@Inject\nprivate Event<? super LifecycleEvent<?>> event;";
}
@Override
public String getAttributeNameDeclarationString() {
throw new UnsupportedOperationException("operation not supported");
}
@Override
public String getMetaType() {
throw new UnsupportedOperationException("operation not supported");
}
@Override
public String getPropertyName() {
return "event";
}
@Override
public String getTypeDeclaration() {
return Constants.ENTITY_MANAGER;
}
@Override
public Metamodel getHostingEntity() {
return annotationMetaEntity;
}
}

View File

@ -15,6 +15,7 @@ import static org.hibernate.processor.util.Constants.UNI;
public class LifecycleMethod extends AbstractAnnotatedMethod {
private final String entity;
private final String actualEntity;
private final String methodName;
private final String parameterName;
private final String operationName;
@ -33,6 +34,7 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
AnnotationMetaEntity annotationMetaEntity,
ExecutableElement method,
String entity,
String actualEntity,
String methodName,
String parameterName,
String sessionName,
@ -44,6 +46,7 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
boolean hasGeneratedId) {
super(annotationMetaEntity, method, sessionName, sessionType);
this.entity = entity;
this.actualEntity = actualEntity;
this.methodName = methodName;
this.parameterName = parameterName;
this.operationName = operationName;
@ -74,7 +77,7 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
StringBuilder declaration = new StringBuilder();
preamble(declaration);
nullCheck(declaration, parameterName);
preEvent(declaration);
fireEvents(declaration, "Pre");
if ( !isReactive() ) {
declaration.append( "\ttry {\n" );
}
@ -88,53 +91,71 @@ public class LifecycleMethod extends AbstractAnnotatedMethod {
declaration
.append( ";\n" );
}
postEvent(declaration);
fireEvents(declaration, "Post");
returnArgument(declaration);
declaration.append("}");
return declaration.toString();
}
private void postEvent(StringBuilder declaration) {
private void fireEvents(StringBuilder declaration, String prefix) {
if ( annotationMetaEntity.getContext().isDataEventPackageAvailable()
&& annotationMetaEntity.getContext().addDependentAnnotation()
&& eventTypes.contains( operationName )
&& !isReactive()) {
final String postEventType = "Post" + capitalize( operationName ) + "Event";
annotationMetaEntity.importType( "jakarta.data.event." + postEventType );
declaration
.append( "\tevent.select(new TypeLiteral<" )
.append( postEventType )
.append( "<" )
.append( annotationMetaEntity.importType( entity ) )
.append( ">>(){})\n\t\t\t.fire(new " )
.append( postEventType )
.append( "<>(" )
.append( parameterName )
.append( "));\n" );
final String entityName = iterateEvents( declaration );
fireEvent( declaration, entityName, prefix + capitalize( operationName ) + "Event" );
endIterateEvents( declaration );
}
}
private void preEvent(StringBuilder declaration) {
if ( annotationMetaEntity.getContext().isDataEventPackageAvailable()
&& annotationMetaEntity.getContext().addDependentAnnotation()
&& eventTypes.contains( operationName )
&& !isReactive()) {
final String preEventType = "Pre" + capitalize( operationName ) + "Event";
annotationMetaEntity.importType( "jakarta.data.event." + preEventType );
private void fireEvent(StringBuilder declaration, String entityName, String eventType) {
annotationMetaEntity.importType( "jakarta.data.event.LifecycleEvent" );
annotationMetaEntity.importType( "jakarta.enterprise.util.TypeLiteral" );
annotationMetaEntity.importType( "jakarta.enterprise.event.Event" );
annotationMetaEntity.importType( "jakarta.inject.Inject" );
annotationMetaEntity.importType( "jakarta.data.event." + eventType );
if (parameterKind != ParameterKind.NORMAL) {
declaration.append( "\t" );
}
declaration
.append( "\tevent.select(new TypeLiteral<" )
.append( preEventType )
.append( "\tif (event != null) {\n" );
if (parameterKind != ParameterKind.NORMAL) {
declaration.append( "\t" );
}
declaration
.append( "\t\tevent.select(new TypeLiteral<" )
.append( eventType )
.append( "<" )
.append( annotationMetaEntity.importType( entity ) )
.append( ">>(){})\n\t\t\t.fire(new " )
.append( preEventType )
.append( annotationMetaEntity.importType( actualEntity ) )
.append( ">>(){})\n\t\t\t\t.fire(new " )
.append( eventType )
.append( "<>(" )
.append( parameterName )
.append( entityName )
.append( "));\n");
if (parameterKind != ParameterKind.NORMAL) {
declaration.append( "\t" );
}
declaration
.append("\t}\n" );
}
private void endIterateEvents(StringBuilder declaration) {
if (parameterKind != ParameterKind.NORMAL) {
declaration
.append( "\t}\n");
}
}
private String iterateEvents(StringBuilder declaration) {
if (parameterKind != ParameterKind.NORMAL) {
declaration
.append( "\tfor (var _entity : ")
.append( parameterName )
.append(") {\n" );
return "_entity";
}
else {
return parameterName;
}
}