Skip to content

Method: resolveEntityListeners()

1: package cz.cvut.kbss.jopa.model.metamodel;
2:
3: import cz.cvut.kbss.jopa.exception.MetamodelInitializationException;
4: import cz.cvut.kbss.jopa.model.annotations.EntityListeners;
5: import cz.cvut.kbss.jopa.model.lifecycle.LifecycleEvent;
6:
7: import java.lang.reflect.Method;
8: import java.lang.reflect.Modifier;
9:
10: class EntityLifecycleCallbackResolver {
11:
12: private AbstractIdentifiableType<?> managedType;
13: private EntityLifecycleListenerManager manager;
14:
15: /**
16: * Builds an instance of {@link EntityLifecycleListenerManager} for the specified managed type.
17: * <p>
18: * The manager contains:
19: * <ul>
20: * <li>Lifecycle callbacks declared in the entity class,</li>
21: * <li>EntityListener instance declared on the entity class,</li>
22: * <li>Reference to parent {@link EntityLifecycleListenerManager} (if exists).</li>
23: * </ul>
24: *
25: * @param et AbstractIdentifiableType to process
26: * @return Lifecycle listener manager instance
27: */
28: EntityLifecycleListenerManager resolve(AbstractIdentifiableType<?> et) {
29: this.managedType = et;
30: this.manager = new EntityLifecycleListenerManager();
31: resolveLifecycleCallbacks();
32: resolveEntityListeners();
33: if (et.getSupertype() != null) {
34: manager.setParent(et.getSupertype().getLifecycleListenerManager());
35: }
36: return manager;
37: }
38:
39: private void resolveLifecycleCallbacks() {
40: final Class<?> cls = managedType.getJavaType();
41: for (Method m : cls.getDeclaredMethods()) {
42: for (LifecycleEvent hookType : LifecycleEvent.values()) {
43: if (m.getDeclaredAnnotation(hookType.getAnnotation()) != null) {
44: verifyCallbackNotAlreadyDefined(hookType);
45: verifyLifecycleCallbackSignature(m);
46: manager.addLifecycleCallback(hookType, m);
47: }
48: }
49: }
50: }
51:
52: private void verifyCallbackNotAlreadyDefined(LifecycleEvent hookType) {
53: if (manager.hasLifecycleCallback(hookType)) {
54: throw new MetamodelInitializationException("The type [" + managedType.getJavaType().getName() +
55: "] has multiple lifecycle callbacks for the lifecycle event [" + hookType + "].");
56: }
57: }
58:
59: private void verifyLifecycleCallbackSignature(Method callback) {
60: if (callback.getParameterCount() > 0) {
61: throw MetamodelInitializationException
62: .invalidArgumentsForLifecycleListener(managedType.getJavaType(), callback);
63: }
64: if (!callback.getReturnType().equals(Void.TYPE)) {
65: throw MetamodelInitializationException
66: .invalidReturnTypeForLifecycleListener(managedType.getJavaType(), callback);
67: }
68: if (Modifier.isFinal(callback.getModifiers()) || Modifier.isStatic(callback.getModifiers())) {
69: throw MetamodelInitializationException
70: .invalidLifecycleListenerModifier(managedType.getJavaType(), callback);
71: }
72: }
73:
74: private void resolveEntityListeners() {
75: final EntityListeners listenersAnn = managedType.getJavaType().getDeclaredAnnotation(EntityListeners.class);
76:• if (listenersAnn == null) {
77: return;
78: }
79:• for (Class<?> listenerType : listenersAnn.value()) {
80: try {
81: final Object listener = listenerType.newInstance();
82: manager.addEntityListener(listener);
83: resolveEntityListenerCallbacks(listener, listenerType);
84: } catch (InstantiationException | IllegalAccessException e) {
85: throw new MetamodelInitializationException("Unable to instantiate entity listener of type "
86: + listenerType + ". The listener has to have a public no-arg constructor.");
87: }
88: }
89: }
90:
91: private void resolveEntityListenerCallbacks(Object listener, Class<?> listenerType) {
92: for (Method m : listenerType.getDeclaredMethods()) {
93: for (LifecycleEvent hookType : LifecycleEvent.values()) {
94: if (m.getDeclaredAnnotation(hookType.getAnnotation()) != null) {
95: verifyEntityListenerCallbackNotAlreadyDefined(listener, listenerType, hookType);
96: verifyEntityListenerCallbackSignature(listenerType, m);
97: manager.addEntityListenerCallback(listener, hookType, m);
98: }
99: }
100: }
101: }
102:
103: private void verifyEntityListenerCallbackNotAlreadyDefined(Object listener, Class<?> listenerType,
104: LifecycleEvent event) {
105: if (manager.hasEntityListenerCallback(listener, event)) {
106: throw new MetamodelInitializationException("The entity listener [" + listenerType.getName() +
107: "] has multiple callbacks for the lifecycle event [" + event + "].");
108: }
109: }
110:
111: private void verifyEntityListenerCallbackSignature(Class<?> listenerType, Method callback) {
112: if (callback.getParameterCount() != 1) {
113: throw MetamodelInitializationException
114: .invalidArgumentsForEntityListenerCallback(listenerType, callback);
115: }
116: final Class<?> paramType = callback.getParameterTypes()[0];
117: if (!paramType.isAssignableFrom(Object.class) && !paramType.isAssignableFrom(managedType.getJavaType())) {
118: throw MetamodelInitializationException
119: .invalidEntityListenerCallbackParameterType(managedType.getJavaType(), listenerType, callback);
120: }
121: if (!callback.getReturnType().equals(Void.TYPE)) {
122: throw MetamodelInitializationException.invalidReturnTypeForEntityListenerCallback(listenerType, callback);
123: }
124: if (Modifier.isFinal(callback.getModifiers()) || Modifier.isStatic(callback.getModifiers())) {
125: throw MetamodelInitializationException.invalidEntityListenerCallbackModifier(listenerType, callback);
126: }
127: }
128: }