public static Callback[] resolveCallback(XClass beanClass, Class annotation, ReflectionManager reflectionManager) {
List<Callback> callbacks = new ArrayList<Callback>();
List<String> callbacksMethodNames = new ArrayList<String>(); //used to track overridden methods
List<Class> orderedListeners = new ArrayList<Class>();
XClass currentClazz = beanClass;
boolean stopListeners = false;
boolean stopDefaultListeners = false;
do {
Callback callback = null;
List<XMethod> methods = currentClazz.getDeclaredMethods();
final int size = methods.size();
for ( int i = 0; i < size ; i++ ) {
final XMethod xMethod = methods.get( i );
if ( xMethod.isAnnotationPresent( annotation ) ) {
Method method = reflectionManager.toMethod( xMethod );
final String methodName = method.getName();
if ( ! callbacksMethodNames.contains( methodName ) ) {
//overridden method, remove the superclass overridden method
if ( callback == null ) {
callback = new BeanCallback( method );
Class returnType = method.getReturnType();
Class[] args = method.getParameterTypes();
if ( returnType != Void.TYPE || args.length != 0 ) {
throw new RuntimeException(
"Callback methods annotated on the bean class must return void and take no arguments: " + annotation
.getName() + " - " + xMethod
);
}
if (!method.isAccessible()) method.setAccessible(true);
LOG.debugf("Adding %s as %s callback for entity %s",
methodName,
annotation.getSimpleName(),
beanClass.getName());
callbacks.add( 0, callback ); //superclass first
callbacksMethodNames.add( 0, methodName );
}
else {
throw new PersistenceException(
"You can only annotate one callback method with "
+ annotation.getName() + " in bean class: " + beanClass.getName()
);
}
}
}
}
if ( !stopListeners ) {
getListeners( currentClazz, orderedListeners );
stopListeners = currentClazz.isAnnotationPresent( ExcludeSuperclassListeners.class );
stopDefaultListeners = currentClazz.isAnnotationPresent( ExcludeDefaultListeners.class );
}
do {
currentClazz = currentClazz.getSuperclass();
}
while ( currentClazz != null
&& ! ( currentClazz.isAnnotationPresent( Entity.class )
|| currentClazz.isAnnotationPresent( MappedSuperclass.class ) )
);
}
while ( currentClazz != null );
//handle default listeners
if ( ! stopDefaultListeners ) {
List<Class> defaultListeners = (List<Class>) reflectionManager.getDefaults().get( EntityListeners.class );
if ( defaultListeners != null ) {
int defaultListenerSize = defaultListeners.size();
for ( int i = defaultListenerSize - 1; i >= 0 ; i-- ) {
orderedListeners.add( defaultListeners.get( i ) );
}
}
}
for ( Class listener : orderedListeners ) {
Callback callback = null;
if ( listener != null ) {
XClass xListener = reflectionManager.toXClass( listener );
callbacksMethodNames = new ArrayList<String>();
List<XMethod> methods = xListener.getDeclaredMethods();
final int size = methods.size();
for ( int i = 0; i < size ; i++ ) {
final XMethod xMethod = methods.get( i );
if ( xMethod.isAnnotationPresent( annotation ) ) {
final Method method = reflectionManager.toMethod( xMethod );