Skip to content

Commit

Permalink
#49 - Add returnType and argumentTypes to MethodDetails
Browse files Browse the repository at this point in the history
  • Loading branch information
sebersole committed Oct 24, 2023
1 parent e395112 commit 2b52229
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public GlobalRegistrationsImpl(ClassDetailsRegistry classDetailsRegistry) {

@Override
public List<EntityListenerRegistration> getEntityListenerRegistrations() {
return entityListenerRegistrations;
return entityListenerRegistrations == null ? emptyList() : entityListenerRegistrations;
}

@Override
Expand Down Expand Up @@ -480,7 +480,11 @@ public void collectEntityListenerRegistrations(List<JaxbEntityListenerImpl> list
}

listeners.forEach( (listener) -> {
final EntityListenerRegistration listenerRegistration = EntityListenerRegistration.from( listener, classDetailsRegistry );
final EntityListenerRegistration listenerRegistration = EntityListenerRegistration.from(
EntityListenerRegistration.CallbackType.LISTENER,
listener,
classDetailsRegistry
);
entityListenerRegistrations.add( listenerRegistration );
} );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,22 @@ public MethodDetails getPostUpdateMethod() {
public MethodDetails getPostLoadMethod() {
return postLoadMethod;
}
public static EntityListenerRegistration from(JaxbEntityListenerImpl jaxbMapping, ClassDetailsRegistry classDetailsRegistry) {

public enum CallbackType {
/**
* Methods are defined on the entity as instance methods
*/
CALLBACK,
/**
* Methods are static and defined on a separate listener class
*/
LISTENER
}

public static EntityListenerRegistration from(
CallbackType callbackType,
JaxbEntityListenerImpl jaxbMapping,
ClassDetailsRegistry classDetailsRegistry) {
final ClassDetails listenerClassDetails = classDetailsRegistry.resolveClassDetails( jaxbMapping.getClazz() );
final MutableObject<MethodDetails> prePersistMethod = new MutableObject<>();
final MutableObject<MethodDetails> postPersistMethod = new MutableObject<>();
Expand All @@ -110,31 +125,38 @@ public static EntityListenerRegistration from(JaxbEntityListenerImpl jaxbMapping
// todo : make this sensitive to method arguments once we have MethodDetails tracking arguments
// for now, just match name
if ( jaxbMapping.getPrePersist() != null
&& methodDetails.getName().equals( jaxbMapping.getPrePersist().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPrePersist().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
prePersistMethod.set( methodDetails );
}
else if ( jaxbMapping.getPostPersist().getMethodName() != null
&& methodDetails.getName().equals( jaxbMapping.getPostPersist().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPostPersist().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
postPersistMethod.set( methodDetails );
}
else if ( jaxbMapping.getPreRemove() != null
&& methodDetails.getName().equals( jaxbMapping.getPreRemove().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPreRemove().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
preRemoveMethod.set( methodDetails );
}
else if ( jaxbMapping.getPostRemove() != null
&& methodDetails.getName().equals( jaxbMapping.getPostRemove().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPostRemove().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
postRemoveMethod.set( methodDetails );
}
else if ( jaxbMapping.getPreUpdate() != null
&& methodDetails.getName().equals( jaxbMapping.getPreUpdate().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPreUpdate().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
preUpdateMethod.set( methodDetails );
}
else if ( jaxbMapping.getPostUpdate() != null
&& methodDetails.getName().equals( jaxbMapping.getPostUpdate().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPostUpdate().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
postUpdateMethod.set( methodDetails );
}
else if ( jaxbMapping.getPostLoad() != null
&& methodDetails.getName().equals( jaxbMapping.getPostLoad().getMethodName() ) ) {
&& methodDetails.getName().equals( jaxbMapping.getPostLoad().getMethodName() )
&& matchesSignature( callbackType, methodDetails ) ) {
postLoadMethod.set( methodDetails );
}
} );
Expand All @@ -150,4 +172,18 @@ else if ( jaxbMapping.getPostLoad() != null
postLoadMethod.get()
);
}

private static boolean matchesSignature(CallbackType callbackType, MethodDetails methodDetails) {
if ( callbackType == CallbackType.CALLBACK ) {
// should have no arguments. and technically (spec) have a void return
return methodDetails.getArgumentTypes().isEmpty()
&& methodDetails.getReturnType() == null;
}
else {
assert callbackType == CallbackType.LISTENER;
// should have 1 argument. and technically (spec) have a void return
return methodDetails.getArgumentTypes().size() == 1
&& methodDetails.getReturnType() == null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/

/**
* Support for processing mapping XML files, ultimately creating/updating
* {@linkplain org.hibernate.models.source.spi.AnnotationUsage annotation} references
* on the model's {@linkplain org.hibernate.models.source.spi.AnnotationTarget targets}
* based on the XML.
*
* @author Steve Ebersole
*/
package org.hibernate.models.orm.xml;
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.models.orm.xml.globals;

import java.util.List;

import org.hibernate.models.orm.internal.ManagedResourcesImpl;
import org.hibernate.models.orm.spi.EntityListenerRegistration;
import org.hibernate.models.orm.spi.ManagedResources;
import org.hibernate.models.orm.spi.ProcessResult;
import org.hibernate.models.orm.spi.Processor;
import org.hibernate.models.orm.xml.SimpleEntity;
import org.hibernate.models.source.SourceModelTestHelper;
import org.hibernate.models.source.internal.SourceModelBuildingContextImpl;
import org.hibernate.models.source.spi.MethodDetails;

import org.junit.jupiter.api.Test;

import org.jboss.jandex.Index;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.models.internal.SimpleClassLoading.SIMPLE_CLASS_LOADING;

/**
* @author Steve Ebersole
*/
public class EntityListenerTests {
@Test
void testGlobalRegistration() {
final ManagedResources managedResources = new ManagedResourcesImpl.Builder()
.addXmlMappings( "mappings/globals.xml" )
.build();

final Index jandexIndex = SourceModelTestHelper.buildJandexIndex(
SIMPLE_CLASS_LOADING,
SimpleEntity.class
);
final SourceModelBuildingContextImpl buildingContext = SourceModelTestHelper.createBuildingContext(
jandexIndex,
SIMPLE_CLASS_LOADING
);

final ProcessResult processResult = Processor.process(
managedResources,
null,
new Processor.Options() {
@Override
public boolean areGeneratorsGlobal() {
return false;
}

@Override
public boolean shouldIgnoreUnlistedClasses() {
return false;
}
},
buildingContext
);

final List<EntityListenerRegistration> registrations = processResult
.getGlobalRegistrations()
.getEntityListenerRegistrations();
assertThat( registrations ).hasSize( 1 );
final EntityListenerRegistration registration = registrations.get( 0 );
final MethodDetails postPersistMethod = registration.getPostPersistMethod();
assertThat( postPersistMethod ).isNotNull();
assertThat( postPersistMethod.getReturnType() ).isNull();
assertThat( postPersistMethod.getArgumentTypes() ).hasSize( 1 );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* SPDX-License-Identifier: Apache-2.0
* Copyright: Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.models.orm.xml.globals;

/**
* JPA entity listener
*
* @author Steve Ebersole
*/
public class GlobalEntityListener {
public void entityCreated(Object entity) {
System.out.println( "Entity was created - " + entity );
}

public Object entityCreated() {
throw new RuntimeException( "Should not be called" );
}

public void entityCreated(Object e1, Object e2) {
throw new RuntimeException( "Should not be called" );
}
}
10 changes: 10 additions & 0 deletions hibernate-models-orm/src/test/resources/mappings/globals.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
<entity-mappings xmlns="http://www.hibernate.org/xsd/orm/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.1">
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="org.hibernate.models.orm.xml.globals.GlobalEntityListener">
<post-persist method-name="entityCreated"/>
</entity-listener>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>

<java-type class="java.lang.String" descriptor="org.hibernate.models.source.internal.StringTypeDescriptor"/>
<jdbc-type code="-1" descriptor="org.hibernate.type.descriptor.jdbc.ClobJdbcType"/>
<user-type class="java.util.UUID" descriptor="org.hibernate.models.orm.xml.MyUserType"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
package org.hibernate.models.source.internal.dynamic;

import java.util.List;

import org.hibernate.models.source.internal.MutableMemberDetails;
import org.hibernate.models.source.spi.ClassDetails;
import org.hibernate.models.source.spi.MethodDetails;
Expand All @@ -20,17 +22,24 @@ public class DynamicMethodDetails extends AbstractAnnotationTarget implements Me
private final MethodKind methodKind;
private final boolean isPersistable;

private final ClassDetails returnType;
private final List<ClassDetails> argumentTypes;

public DynamicMethodDetails(
String name,
ClassDetails type,
MethodKind methodKind,
boolean isPersistable,
ClassDetails returnType,
List<ClassDetails> argumentTypes,
SourceModelBuildingContext buildingContext) {
super( buildingContext );
this.name = name;
this.type = type;
this.methodKind = methodKind;
this.isPersistable = isPersistable;
this.returnType = returnType;
this.argumentTypes = argumentTypes;
}

@Override
Expand All @@ -48,6 +57,16 @@ public ClassDetails getType() {
return type;
}

@Override
public ClassDetails getReturnType() {
return returnType;
}

@Override
public List<ClassDetails> getArgumentTypes() {
return argumentTypes;
}

@Override
public boolean isPersistable() {
return isPersistable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ else if ( isBoolean( returnType ) && ( methodName.startsWith( "is" )
&& method.name().startsWith( "set" ) ) {
return new JandexMethodDetails(
method,
MethodDetails.MethodKind.GETTER,
MethodDetails.MethodKind.SETTER,
buildingContext.getClassDetailsRegistry().resolveClassDetails( method.parameterType( 0 ).name().toString() ),
buildingContext
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
*/
package org.hibernate.models.source.internal.jandex;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.models.source.internal.MutableMemberDetails;
import org.hibernate.models.source.spi.ClassDetails;
import org.hibernate.models.source.spi.ClassDetailsRegistry;
import org.hibernate.models.source.spi.MethodDetails;
import org.hibernate.models.source.spi.SourceModelBuildingContext;

import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;

import static org.hibernate.models.source.internal.ModifierUtils.isPersistableMethod;

Expand All @@ -24,6 +29,9 @@ public class JandexMethodDetails extends AbstractAnnotationTarget implements Met
private final MethodKind methodKind;
private final ClassDetails type;

private final ClassDetails returnType;
private final List<ClassDetails> argumentTypes;

public JandexMethodDetails(
MethodInfo methodInfo,
MethodKind methodKind,
Expand All @@ -33,6 +41,18 @@ public JandexMethodDetails(
this.methodInfo = methodInfo;
this.methodKind = methodKind;
this.type = type;

final ClassDetailsRegistry classDetailsRegistry = buildingContext.getClassDetailsRegistry();
if ( methodInfo.returnType().kind() == Type.Kind.VOID ) {
returnType = null;
}
else {
returnType = classDetailsRegistry.resolveClassDetails( methodInfo.returnType().name().toString() );
}
argumentTypes = new ArrayList<>( methodInfo.parametersCount() );
for ( int i = 0; i < methodInfo.parametersCount(); i++ ) {
argumentTypes.add( classDetailsRegistry.resolveClassDetails( methodInfo.parameterType( i ).name().toString() ) );
}
}

@Override
Expand All @@ -55,6 +75,16 @@ public ClassDetails getType() {
return type;
}

@Override
public ClassDetails getReturnType() {
return returnType;
}

@Override
public List<ClassDetails> getArgumentTypes() {
return argumentTypes;
}

@Override
public boolean isPersistable() {
if ( methodInfo.parametersCount() > 0 ) {
Expand Down
Loading

0 comments on commit 2b52229

Please sign in to comment.