|
|
|
@ -116,8 +116,7 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
private boolean isDiscriminatorForced = true;
|
|
|
|
|
private boolean isDiscriminatorIncludedInSql = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<JpaCallbackClass> jpaCallbackClasses = new ArrayList<JpaCallbackClass>();
|
|
|
|
|
private final List<JpaCallbackClass> jpaCallbacks;
|
|
|
|
|
|
|
|
|
|
public EntityClass(
|
|
|
|
|
ClassInfo classInfo,
|
|
|
|
@ -133,12 +132,11 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
this.constraintSources = new HashSet<ConstraintSource>();
|
|
|
|
|
|
|
|
|
|
if ( hasOwnTable ) {
|
|
|
|
|
this.primaryTableSource = createTableSource(
|
|
|
|
|
JandexHelper.getSingleAnnotation(
|
|
|
|
|
AnnotationInstance tableAnnotation = JandexHelper.getSingleAnnotation(
|
|
|
|
|
getClassInfo(),
|
|
|
|
|
JPADotNames.TABLE
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
this.primaryTableSource = createTableSource( tableAnnotation );
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.primaryTableSource = null;
|
|
|
|
@ -148,156 +146,12 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
this.customLoaderQueryName = determineCustomLoader();
|
|
|
|
|
this.synchronizedTableNames = determineSynchronizedTableNames();
|
|
|
|
|
this.batchSize = determineBatchSize();
|
|
|
|
|
this.jpaCallbacks = determineEntityListeners();
|
|
|
|
|
|
|
|
|
|
processHibernateEntitySpecificAnnotations();
|
|
|
|
|
processCustomSqlAnnotations();
|
|
|
|
|
processProxyGeneration();
|
|
|
|
|
|
|
|
|
|
processDiscriminator();
|
|
|
|
|
|
|
|
|
|
// Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded)
|
|
|
|
|
if (JandexHelper.getSingleAnnotation(classInfo, JPADotNames.EXCLUDE_DEFAULT_LISTENERS) == null) {
|
|
|
|
|
for (AnnotationInstance callbackClasses : context.getIndex().getAnnotations(PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS)) {
|
|
|
|
|
for (Type callbackClass : callbackClasses.value().asClassArray()) {
|
|
|
|
|
String callbackClassName = callbackClass.name().toString();
|
|
|
|
|
try {
|
|
|
|
|
processDefaultJpaCallbacks(callbackClassName, context.getClassInfo(callbackClassName), context);
|
|
|
|
|
} catch (PersistenceException error) {
|
|
|
|
|
throw new PersistenceException(error.getMessage() + "default entity listener " + callbackClassName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Bind JPA entity listener callbacks, using superclasses first (unless excluded)
|
|
|
|
|
for (AnnotationInstance callbackClasses : classInfo.annotations().get(JPADotNames.ENTITY_LISTENERS)) {
|
|
|
|
|
for (Type callbackClass : callbackClasses.value().asClassArray()) {
|
|
|
|
|
String callbackClassName = callbackClass.name().toString();
|
|
|
|
|
try {
|
|
|
|
|
processJpaCallbacks(callbackClassName, context.getClassInfo(callbackClassName), true, context);
|
|
|
|
|
} catch (PersistenceException error) {
|
|
|
|
|
throw new PersistenceException(error.getMessage() + "entity listener " + callbackClassName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Bind JPA entity.mapped superclass callbacks, using superclasses first (unless excluded)
|
|
|
|
|
try {
|
|
|
|
|
processJpaCallbacks(getName(), classInfo, false, context);
|
|
|
|
|
} catch (PersistenceException error) {
|
|
|
|
|
throw new PersistenceException(error.getMessage() + "entity/mapped superclass " + classInfo.name().toString());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processDefaultJpaCallbacks( String instanceCallbackClassName,
|
|
|
|
|
ClassInfo callbackClassInfo,
|
|
|
|
|
AnnotationBindingContext context ) {
|
|
|
|
|
// Process superclass first if available and not excluded
|
|
|
|
|
if (JandexHelper.getSingleAnnotation(callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS) != null) {
|
|
|
|
|
DotName superName = callbackClassInfo.superName();
|
|
|
|
|
if (superName != null)
|
|
|
|
|
processDefaultJpaCallbacks(instanceCallbackClassName, context.getClassInfo(superName.toString()), context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String callbackClassName = callbackClassInfo.name().toString();
|
|
|
|
|
Map<Class<?>, String> callbacksByType = new HashMap<Class<?>, String>();
|
|
|
|
|
createDefaultCallback(PrePersist.class, PseudoJpaDotNames.DEFAULT_PRE_PERSIST, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
createDefaultCallback(PreRemove.class, PseudoJpaDotNames.DEFAULT_PRE_REMOVE, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
createDefaultCallback(PreUpdate.class, PseudoJpaDotNames.DEFAULT_PRE_UPDATE, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
createDefaultCallback(PostLoad.class, PseudoJpaDotNames.DEFAULT_POST_LOAD, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
createDefaultCallback(PostPersist.class, PseudoJpaDotNames.DEFAULT_POST_PERSIST, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
createDefaultCallback(PostRemove.class, PseudoJpaDotNames.DEFAULT_POST_REMOVE, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
createDefaultCallback(PostUpdate.class, PseudoJpaDotNames.DEFAULT_POST_UPDATE, callbackClassName, callbacksByType,
|
|
|
|
|
context);
|
|
|
|
|
if (!callbacksByType.isEmpty())
|
|
|
|
|
jpaCallbackClasses.add(new JpaCallbackClassImpl(instanceCallbackClassName, callbacksByType, true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processJpaCallbacks( String instanceCallbackClassName,
|
|
|
|
|
ClassInfo callbackClassInfo,
|
|
|
|
|
boolean isListener,
|
|
|
|
|
AnnotationBindingContext context ) {
|
|
|
|
|
// Process superclass first if available and not excluded
|
|
|
|
|
if (JandexHelper.getSingleAnnotation(callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS) != null) {
|
|
|
|
|
DotName superName = callbackClassInfo.superName();
|
|
|
|
|
if (superName != null)
|
|
|
|
|
processJpaCallbacks(instanceCallbackClassName, context.getClassInfo(superName.toString()), isListener, context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<Class<?>, String> callbacksByType = new HashMap<Class<?>, String>();
|
|
|
|
|
createCallback(PrePersist.class, JPADotNames.PRE_PERSIST, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
createCallback(PreRemove.class, JPADotNames.PRE_REMOVE, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
createCallback(PreUpdate.class, JPADotNames.PRE_UPDATE, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
createCallback(PostLoad.class, JPADotNames.POST_LOAD, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
createCallback(PostPersist.class, JPADotNames.POST_PERSIST, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
createCallback(PostRemove.class, JPADotNames.POST_REMOVE, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
createCallback(PostUpdate.class, JPADotNames.POST_UPDATE, callbacksByType, callbackClassInfo, isListener);
|
|
|
|
|
if (!callbacksByType.isEmpty())
|
|
|
|
|
jpaCallbackClasses.add(new JpaCallbackClassImpl(instanceCallbackClassName, callbacksByType, isListener));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createDefaultCallback( Class callbackTypeClass,
|
|
|
|
|
DotName callbackTypeName,
|
|
|
|
|
String callbackClassName,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass,
|
|
|
|
|
AnnotationBindingContext context ) {
|
|
|
|
|
for (AnnotationInstance callback : context.getIndex().getAnnotations(callbackTypeName)) {
|
|
|
|
|
MethodInfo methodInfo = (MethodInfo)callback.target();
|
|
|
|
|
validateMethod(methodInfo, callbackTypeClass, callbacksByClass, true);
|
|
|
|
|
if (methodInfo.declaringClass().name().equals(callbackClassName)) {
|
|
|
|
|
if (methodInfo.args().length != 1)
|
|
|
|
|
throw new PersistenceException("Callback method " + methodInfo.name() +
|
|
|
|
|
" must have exactly one argument defined as either Object or " +
|
|
|
|
|
getEntityName() + " in ");
|
|
|
|
|
createCallback(callbackTypeClass, callbacksByClass, methodInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createCallback( Class callbackTypeClass,
|
|
|
|
|
DotName callbackTypeName,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass,
|
|
|
|
|
ClassInfo callbackClassInfo,
|
|
|
|
|
boolean isListener ) {
|
|
|
|
|
Map<DotName, List<AnnotationInstance>> annotations = callbackClassInfo.annotations();
|
|
|
|
|
for (AnnotationInstance callback : annotations.get(callbackTypeName)) {
|
|
|
|
|
MethodInfo methodInfo = (MethodInfo)callback.target();
|
|
|
|
|
validateMethod(methodInfo, callbackTypeClass, callbacksByClass, isListener);
|
|
|
|
|
createCallback(callbackTypeClass, callbacksByClass, methodInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createCallback( Class callbackTypeClass,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass,
|
|
|
|
|
MethodInfo methodInfo ) {
|
|
|
|
|
callbacksByClass.put(callbackTypeClass, methodInfo.name());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void validateMethod( MethodInfo methodInfo,
|
|
|
|
|
Class callbackTypeClass,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass,
|
|
|
|
|
boolean isListener) {
|
|
|
|
|
if (methodInfo.returnType().kind() != Kind.VOID)
|
|
|
|
|
throw new PersistenceException("Callback method " + methodInfo.name() + " must have a void return type in ");
|
|
|
|
|
if (Modifier.isStatic(methodInfo.flags()) || Modifier.isFinal(methodInfo.flags()))
|
|
|
|
|
throw new PersistenceException("Callback method " + methodInfo.name() + " must not be static or final in ");
|
|
|
|
|
Type[] argTypes = methodInfo.args();
|
|
|
|
|
if (isListener) {
|
|
|
|
|
if (argTypes.length != 1)
|
|
|
|
|
throw new PersistenceException("Callback method " + methodInfo.name() + " must have exactly one argument in ");
|
|
|
|
|
String argTypeName = argTypes[0].name().toString();
|
|
|
|
|
if (!argTypeName.equals(Object.class.getName()) && !argTypeName.equals(getName()))
|
|
|
|
|
throw new PersistenceException("The argument for callback method " + methodInfo.name() +
|
|
|
|
|
" must be defined as either Object or " + getEntityName() + " in ");
|
|
|
|
|
} else if (argTypes.length != 0)
|
|
|
|
|
throw new PersistenceException("Callback method " + methodInfo.name() + " must have no arguments in ");
|
|
|
|
|
if (callbacksByClass.containsKey(callbackTypeClass))
|
|
|
|
|
throw new PersistenceException("Only one method may be annotated as a " + callbackTypeClass.getSimpleName() +
|
|
|
|
|
" callback method in ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ColumnValues getDiscriminatorColumnValues() {
|
|
|
|
@ -425,6 +279,14 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
return isDiscriminatorIncludedInSql;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getDiscriminatorMatchValue() {
|
|
|
|
|
return discriminatorMatchValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<JpaCallbackClass> getJpaCallbacks() {
|
|
|
|
|
return jpaCallbacks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String determineExplicitEntityName() {
|
|
|
|
|
final AnnotationInstance jpaEntityAnnotation = JandexHelper.getSingleAnnotation(
|
|
|
|
|
getClassInfo(), JPADotNames.ENTITY
|
|
|
|
@ -714,6 +576,7 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* todo see {@code Binder#createTable}
|
|
|
|
|
*
|
|
|
|
|
* @param tableAnnotation a annotation instance, either {@link javax.persistence.Table} or {@link javax.persistence.SecondaryTable}
|
|
|
|
|
*
|
|
|
|
|
* @return A table source for the specified annotation instance
|
|
|
|
@ -899,12 +762,194 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
return batchSizeAnnotation == null ? -1 : batchSizeAnnotation.value( "size" ).asInt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getDiscriminatorMatchValue() {
|
|
|
|
|
return discriminatorMatchValue;
|
|
|
|
|
private List<JpaCallbackClass> determineEntityListeners() {
|
|
|
|
|
List<JpaCallbackClass> callbackClassList = new ArrayList<JpaCallbackClass>();
|
|
|
|
|
|
|
|
|
|
// Bind default JPA entity listener callbacks (unless excluded), using superclasses first (unless excluded)
|
|
|
|
|
if ( JandexHelper.getSingleAnnotation( getClassInfo(), JPADotNames.EXCLUDE_DEFAULT_LISTENERS ) == null ) {
|
|
|
|
|
List<AnnotationInstance> defaultEntityListenerAnnotations = getLocalBindingContext().getIndex()
|
|
|
|
|
.getAnnotations( PseudoJpaDotNames.DEFAULT_ENTITY_LISTENERS );
|
|
|
|
|
for ( AnnotationInstance annotation : defaultEntityListenerAnnotations ) {
|
|
|
|
|
for ( Type callbackClass : annotation.value().asClassArray() ) {
|
|
|
|
|
String callbackClassName = callbackClass.name().toString();
|
|
|
|
|
try {
|
|
|
|
|
processDefaultJpaCallbacks( callbackClassName, callbackClassList );
|
|
|
|
|
}
|
|
|
|
|
catch ( PersistenceException error ) {
|
|
|
|
|
throw new PersistenceException( error.getMessage() + "default entity listener " + callbackClassName );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<JpaCallbackClass> getJpaCallbackClasses() {
|
|
|
|
|
return jpaCallbackClasses;
|
|
|
|
|
// Bind JPA entity listener callbacks, using superclasses first (unless excluded)
|
|
|
|
|
List<AnnotationInstance> annotationList = getClassInfo().annotations().get( JPADotNames.ENTITY_LISTENERS );
|
|
|
|
|
if ( annotationList != null ) {
|
|
|
|
|
for ( AnnotationInstance annotation : annotationList ) {
|
|
|
|
|
for ( Type callbackClass : annotation.value().asClassArray() ) {
|
|
|
|
|
String callbackClassName = callbackClass.name().toString();
|
|
|
|
|
try {
|
|
|
|
|
processJpaCallbacks( callbackClassName, true, callbackClassList );
|
|
|
|
|
}
|
|
|
|
|
catch ( PersistenceException error ) {
|
|
|
|
|
throw new PersistenceException( error.getMessage() + "entity listener " + callbackClassName );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bind JPA entity.mapped superclass callbacks, using superclasses first (unless excluded)
|
|
|
|
|
try {
|
|
|
|
|
processJpaCallbacks( getName(), false, callbackClassList );
|
|
|
|
|
}
|
|
|
|
|
catch ( PersistenceException error ) {
|
|
|
|
|
throw new PersistenceException(
|
|
|
|
|
error.getMessage() + "entity/mapped superclass " + getClassInfo().name().toString()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return callbackClassList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processDefaultJpaCallbacks(String instanceCallbackClassName, List<JpaCallbackClass> jpaCallbackClassList) {
|
|
|
|
|
ClassInfo callbackClassInfo = getLocalBindingContext().getClassInfo( instanceCallbackClassName );
|
|
|
|
|
|
|
|
|
|
// Process superclass first if available and not excluded
|
|
|
|
|
if ( JandexHelper.getSingleAnnotation( callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ) != null ) {
|
|
|
|
|
DotName superName = callbackClassInfo.superName();
|
|
|
|
|
if ( superName != null ) {
|
|
|
|
|
processDefaultJpaCallbacks( instanceCallbackClassName, jpaCallbackClassList );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String callbackClassName = callbackClassInfo.name().toString();
|
|
|
|
|
Map<Class<?>, String> callbacksByType = new HashMap<Class<?>, String>();
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PrePersist.class, PseudoJpaDotNames.DEFAULT_PRE_PERSIST, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PreRemove.class, PseudoJpaDotNames.DEFAULT_PRE_REMOVE, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PreUpdate.class, PseudoJpaDotNames.DEFAULT_PRE_UPDATE, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PostLoad.class, PseudoJpaDotNames.DEFAULT_POST_LOAD, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PostPersist.class, PseudoJpaDotNames.DEFAULT_POST_PERSIST, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PostRemove.class, PseudoJpaDotNames.DEFAULT_POST_REMOVE, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
createDefaultCallback(
|
|
|
|
|
PostUpdate.class, PseudoJpaDotNames.DEFAULT_POST_UPDATE, callbackClassName, callbacksByType
|
|
|
|
|
);
|
|
|
|
|
if ( !callbacksByType.isEmpty() ) {
|
|
|
|
|
jpaCallbackClassList.add( new JpaCallbackClassImpl( instanceCallbackClassName, callbacksByType, true ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processJpaCallbacks(String instanceCallbackClassName, boolean isListener, List<JpaCallbackClass> callbackClassList) {
|
|
|
|
|
|
|
|
|
|
ClassInfo callbackClassInfo = getLocalBindingContext().getClassInfo( instanceCallbackClassName );
|
|
|
|
|
|
|
|
|
|
// Process superclass first if available and not excluded
|
|
|
|
|
if ( JandexHelper.getSingleAnnotation( callbackClassInfo, JPADotNames.EXCLUDE_SUPERCLASS_LISTENERS ) != null ) {
|
|
|
|
|
DotName superName = callbackClassInfo.superName();
|
|
|
|
|
if ( superName != null ) {
|
|
|
|
|
processJpaCallbacks(
|
|
|
|
|
instanceCallbackClassName,
|
|
|
|
|
isListener,
|
|
|
|
|
callbackClassList
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<Class<?>, String> callbacksByType = new HashMap<Class<?>, String>();
|
|
|
|
|
createCallback( PrePersist.class, JPADotNames.PRE_PERSIST, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
createCallback( PreRemove.class, JPADotNames.PRE_REMOVE, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
createCallback( PreUpdate.class, JPADotNames.PRE_UPDATE, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
createCallback( PostLoad.class, JPADotNames.POST_LOAD, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
createCallback( PostPersist.class, JPADotNames.POST_PERSIST, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
createCallback( PostRemove.class, JPADotNames.POST_REMOVE, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
createCallback( PostUpdate.class, JPADotNames.POST_UPDATE, callbacksByType, callbackClassInfo, isListener );
|
|
|
|
|
if ( !callbacksByType.isEmpty() ) {
|
|
|
|
|
callbackClassList.add( new JpaCallbackClassImpl( instanceCallbackClassName, callbacksByType, isListener ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createDefaultCallback(Class callbackTypeClass,
|
|
|
|
|
DotName callbackTypeName,
|
|
|
|
|
String callbackClassName,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass) {
|
|
|
|
|
for ( AnnotationInstance callback : getLocalBindingContext().getIndex().getAnnotations( callbackTypeName ) ) {
|
|
|
|
|
MethodInfo methodInfo = (MethodInfo) callback.target();
|
|
|
|
|
validateMethod( methodInfo, callbackTypeClass, callbacksByClass, true );
|
|
|
|
|
if ( methodInfo.declaringClass().name().toString().equals( callbackClassName ) ) {
|
|
|
|
|
if ( methodInfo.args().length != 1 ) {
|
|
|
|
|
throw new PersistenceException(
|
|
|
|
|
String.format(
|
|
|
|
|
"Callback method %s must have exactly one argument defined as either Object or %s in ",
|
|
|
|
|
methodInfo.name(),
|
|
|
|
|
getEntityName()
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
callbacksByClass.put( callbackTypeClass, methodInfo.name() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void createCallback(Class callbackTypeClass,
|
|
|
|
|
DotName callbackTypeName,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass,
|
|
|
|
|
ClassInfo callbackClassInfo,
|
|
|
|
|
boolean isListener) {
|
|
|
|
|
Map<DotName, List<AnnotationInstance>> annotations = callbackClassInfo.annotations();
|
|
|
|
|
List<AnnotationInstance> annotationInstances = annotations.get( callbackTypeName );
|
|
|
|
|
if ( annotationInstances == null ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
for ( AnnotationInstance callbackAnnotation : annotationInstances ) {
|
|
|
|
|
MethodInfo methodInfo = (MethodInfo) callbackAnnotation.target();
|
|
|
|
|
validateMethod( methodInfo, callbackTypeClass, callbacksByClass, isListener );
|
|
|
|
|
callbacksByClass.put( callbackTypeClass, methodInfo.name() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void validateMethod(MethodInfo methodInfo,
|
|
|
|
|
Class callbackTypeClass,
|
|
|
|
|
Map<Class<?>, String> callbacksByClass,
|
|
|
|
|
boolean isListener) {
|
|
|
|
|
if ( methodInfo.returnType().kind() != Kind.VOID ) {
|
|
|
|
|
throw new PersistenceException( "Callback method " + methodInfo.name() + " must have a void return type in " );
|
|
|
|
|
}
|
|
|
|
|
if ( Modifier.isStatic( methodInfo.flags() ) || Modifier.isFinal( methodInfo.flags() ) ) {
|
|
|
|
|
throw new PersistenceException( "Callback method " + methodInfo.name() + " must not be static or final in " );
|
|
|
|
|
}
|
|
|
|
|
Type[] argTypes = methodInfo.args();
|
|
|
|
|
if ( isListener ) {
|
|
|
|
|
if ( argTypes.length != 1 ) {
|
|
|
|
|
throw new PersistenceException( "Callback method " + methodInfo.name() + " must have exactly one argument in " );
|
|
|
|
|
}
|
|
|
|
|
String argTypeName = argTypes[0].name().toString();
|
|
|
|
|
if ( !argTypeName.equals( Object.class.getName() ) && !argTypeName.equals( getName() ) ) {
|
|
|
|
|
throw new PersistenceException(
|
|
|
|
|
"The argument for callback method " + methodInfo.name() +
|
|
|
|
|
" must be defined as either Object or " + getEntityName() + " in "
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( argTypes.length != 0 ) {
|
|
|
|
|
throw new PersistenceException( "Callback method " + methodInfo.name() + " must have no arguments in " );
|
|
|
|
|
}
|
|
|
|
|
if ( callbacksByClass.containsKey( callbackTypeClass ) ) {
|
|
|
|
|
throw new PersistenceException(
|
|
|
|
|
"Only one method may be annotated as a " + callbackTypeClass.getSimpleName() +
|
|
|
|
|
" callback method in "
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process JPA callbacks, in superclass-first order (unless superclasses are excluded), using default listeners first
|
|
|
|
@ -923,31 +968,16 @@ public class EntityClass extends ConfiguredClass {
|
|
|
|
|
this.isListener = isListener;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritDoc}
|
|
|
|
|
*
|
|
|
|
|
* @see org.hibernate.metamodel.source.binder.JpaCallbackClass#getCallback(java.lang.Class)
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public String getCallback( Class<?> callbackAnnotationClass ) {
|
|
|
|
|
return callbacksByType.get(callbackAnnotationClass);
|
|
|
|
|
public String getCallbackMethod(Class<?> callbackType) {
|
|
|
|
|
return callbacksByType.get( callbackType );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritDoc}
|
|
|
|
|
*
|
|
|
|
|
* @see org.hibernate.metamodel.source.binder.JpaCallbackClass#getName()
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public String getName() {
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* {@inheritDoc}
|
|
|
|
|
*
|
|
|
|
|
* @see org.hibernate.metamodel.source.binder.JpaCallbackClass#isListener()
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public boolean isListener() {
|
|
|
|
|
return isListener;
|
|
|
|
|