Skip to content

Method: invokePostRemoveCallbacks(Object)

1: package cz.cvut.kbss.jopa.model.metamodel;
2:
3: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
4: import cz.cvut.kbss.jopa.model.annotations.EntityListeners;
5: import cz.cvut.kbss.jopa.model.lifecycle.LifecycleEvent;
6:
7: import java.lang.reflect.InvocationTargetException;
8: import java.lang.reflect.Method;
9: import java.util.*;
10:
11: /**
12: * Manages entity lifecycle callbacks declared either in the entity (entity lifecycle callbacks) or in its entity
13: * listener (entity listener callbacks) and provides means for their invocation.
14: */
15: public class EntityLifecycleListenerManager {
16:
17: private static final EntityLifecycleListenerManager EMPTY = new EntityLifecycleListenerManager();
18:
19: private EntityLifecycleListenerManager parent;
20:
21: private final Map<LifecycleEvent, Method> lifecycleCallbacks = new EnumMap<>(LifecycleEvent.class);
22:
23: private List<Object> entityListeners;
24:
25: private Map<Object, Map<LifecycleEvent, Method>> entityListenerCallbacks;
26:
27: /**
28: * Gets default instance of this manager, which contains no listeners and does nothing on invocation.
29: *
30: * @return Default {@link EntityLifecycleListenerManager} instance
31: */
32: public static EntityLifecycleListenerManager empty() {
33: return EMPTY;
34: }
35:
36: /**
37: * Calls pre-persist callbacks for the specified instance.
38: * <p>
39: * These include:
40: * <ul>
41: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
42: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
43: * </ul>
44: *
45: * @param instance The instance for persist
46: */
47: public void invokePrePersistCallbacks(Object instance) {
48: invokeCallbacks(instance, LifecycleEvent.PRE_PERSIST);
49: }
50:
51: private void invokeCallbacks(Object instance, LifecycleEvent lifecycleEvent) {
52: invokeEntityListenerCallbacks(instance, lifecycleEvent);
53: invokeInternalCallbacks(instance, lifecycleEvent);
54: }
55:
56: private void invokeEntityListenerCallbacks(Object instance, LifecycleEvent lifecycleEvent) {
57: if (parent != null) {
58: parent.invokeEntityListenerCallbacks(instance, lifecycleEvent);
59: }
60: if (entityListeners != null) {
61: entityListeners.forEach(listener -> {
62: getEntityListenerCallback(listener, lifecycleEvent).ifPresent(method -> {
63: if (!method.isAccessible()) {
64: method.setAccessible(true);
65: }
66: try {
67: method.invoke(listener, instance);
68: } catch (IllegalAccessException | InvocationTargetException e) {
69: throw new OWLPersistenceException("Unable to invoke entity listener method " + method, e);
70: }
71: });
72: });
73: }
74: }
75:
76: private Optional<Method> getEntityListenerCallback(Object listener, LifecycleEvent lifecycleEvent) {
77: final Map<LifecycleEvent, Method> callbacks = entityListenerCallbacks.get(listener);
78: return Optional.ofNullable(callbacks.get(lifecycleEvent));
79: }
80:
81: private void invokeInternalCallbacks(Object instance, LifecycleEvent lifecycleEvent) {
82: if (parent != null) {
83: parent.invokeInternalCallbacks(instance, lifecycleEvent);
84: }
85: if (lifecycleCallbacks.containsKey(lifecycleEvent)) {
86: final Method listener = lifecycleCallbacks.get(lifecycleEvent);
87: if (!listener.isAccessible()) {
88: listener.setAccessible(true);
89: }
90: try {
91: listener.invoke(instance);
92: } catch (IllegalAccessException | InvocationTargetException e) {
93: throw new OWLPersistenceException("Unable to invoke method lifecycle listener " + listener, e);
94: }
95: }
96: }
97:
98: /**
99: * Calls post-persist callbacks for the specified instance.
100: * <p>
101: * These include:
102: * <ul>
103: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
104: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
105: * </ul>
106: *
107: * @param instance The newly persisted instance
108: */
109: public void invokePostPersistCallbacks(Object instance) {
110: invokeCallbacks(instance, LifecycleEvent.POST_PERSIST);
111: }
112:
113: /**
114: * Calls post-load callbacks for the specified instance.
115: * <p>
116: * These include:
117: * <ul>
118: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
119: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
120: * </ul>
121: *
122: * @param instance The loaded instance
123: */
124: public void invokePostLoadCallbacks(Object instance) {
125: invokeCallbacks(instance, LifecycleEvent.POST_LOAD);
126: }
127:
128: /**
129: * Calls pre-update callbacks for the specified instance.
130: * <p>
131: * These include:
132: * <ul>
133: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
134: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
135: * </ul>
136: *
137: * @param instance The updated instance
138: */
139: public void invokePreUpdateCallbacks(Object instance) {
140: invokeCallbacks(instance, LifecycleEvent.PRE_UPDATE);
141: }
142:
143: /**
144: * Calls post-update callbacks for the specified instance.
145: * <p>
146: * These include:
147: * <ul>
148: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
149: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
150: * </ul>
151: *
152: * @param instance The updated instance
153: */
154: public void invokePostUpdateCallbacks(Object instance) {
155: invokeCallbacks(instance, LifecycleEvent.POST_UPDATE);
156: }
157:
158: /**
159: * Calls pre-remove callbacks for the specified instance.
160: * <p>
161: * These include:
162: * <ul>
163: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
164: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
165: * </ul>
166: *
167: * @param instance The instance for removal
168: */
169: public void invokePreRemoveCallbacks(Object instance) {
170: invokeCallbacks(instance, LifecycleEvent.PRE_REMOVE);
171: }
172:
173: /**
174: * Calls post-remove callbacks for the specified instance.
175: * <p>
176: * These include:
177: * <ul>
178: * <li>Lifecycle callbacks declared by the entity or its managed ancestors,</li>
179: * <li>Callbacks declared in classes referenced by {@link EntityListeners} on the entity or its ancestors.</li>
180: * </ul>
181: *
182: * @param instance The removed instance
183: */
184: public void invokePostRemoveCallbacks(Object instance) {
185: invokeCallbacks(instance, LifecycleEvent.POST_REMOVE);
186: }
187:
188: void setParent(EntityLifecycleListenerManager parent) {
189: this.parent = parent;
190: }
191:
192: void addEntityListener(Object entityListener) {
193: assert entityListener != null;
194:
195: if (entityListeners == null) {
196: this.entityListeners = new ArrayList<>();
197: }
198: entityListeners.add(entityListener);
199: if (entityListenerCallbacks == null) {
200: this.entityListenerCallbacks = new HashMap<>();
201: }
202: entityListenerCallbacks.put(entityListener, new EnumMap<>(LifecycleEvent.class));
203: }
204:
205: void addLifecycleCallback(LifecycleEvent event, Method callback) {
206: assert event != null;
207: assert callback != null;
208:
209: lifecycleCallbacks.put(event, callback);
210: }
211:
212: Map<LifecycleEvent, Method> getLifecycleCallbacks() {
213: return Collections.unmodifiableMap(lifecycleCallbacks);
214: }
215:
216: boolean hasLifecycleCallback(LifecycleEvent event) {
217: return lifecycleCallbacks.containsKey(event);
218: }
219:
220: List<Object> getEntityListeners() {
221: return entityListeners != null ? Collections.unmodifiableList(entityListeners) : Collections.emptyList();
222: }
223:
224: Map<Object, Map<LifecycleEvent, Method>> getEntityListenerCallbacks() {
225: return entityListenerCallbacks != null ? Collections.unmodifiableMap(entityListenerCallbacks) :
226: Collections.emptyMap();
227: }
228:
229: void addEntityListenerCallback(Object listener, LifecycleEvent event, Method callback) {
230: assert listener != null;
231: assert event != null;
232: assert callback != null;
233: assert entityListenerCallbacks.containsKey(listener);
234:
235: entityListenerCallbacks.get(listener).put(event, callback);
236: }
237:
238: boolean hasEntityListenerCallback(Object listener, LifecycleEvent event) {
239: return entityListenerCallbacks != null && entityListenerCallbacks.containsKey(listener) &&
240: entityListenerCallbacks.get(listener).containsKey(event);
241: }
242: }