001: /**
002: * Copyright (C) 2001-2005 France Telecom R&D
003: */package org.objectweb.speedo.mim.jdo.lib;
004:
005: import org.objectweb.perseus.persistence.api.TransactionalPersistenceManager;
006: import org.objectweb.speedo.lib.Personality;
007: import org.objectweb.speedo.mim.api.HomeItf;
008: import org.objectweb.speedo.mim.lib.AbstractHomeImpl;
009: import org.objectweb.speedo.pm.api.POManagerFactoryItf;
010:
011: import java.util.ArrayList;
012: import java.util.Arrays;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.List;
016: import java.util.Map;
017:
018: import javax.jdo.InstanceCallbacks;
019: import javax.jdo.listener.AttachLifecycleListener;
020: import javax.jdo.listener.ClearCallback;
021: import javax.jdo.listener.ClearLifecycleListener;
022: import javax.jdo.listener.CreateLifecycleListener;
023: import javax.jdo.listener.DeleteCallback;
024: import javax.jdo.listener.DeleteLifecycleListener;
025: import javax.jdo.listener.DetachLifecycleListener;
026: import javax.jdo.listener.DirtyLifecycleListener;
027: import javax.jdo.listener.InstanceLifecycleEvent;
028: import javax.jdo.listener.InstanceLifecycleListener;
029: import javax.jdo.listener.LoadCallback;
030: import javax.jdo.listener.LoadLifecycleListener;
031: import javax.jdo.listener.StoreCallback;
032: import javax.jdo.listener.StoreLifecycleListener;
033:
034: public abstract class JDOAbstractHomeImpl extends AbstractHomeImpl {
035:
036: /**
037: * The InstanceLifecycleListener instances registered for the current class
038: * key = Integer value representing the event type (HomeItf#ATTACH)
039: * value = InstanceLifecycleListener[]
040: * @see HomeItf#PRE_ATTACH
041: */
042: private Map event2lifecycleListeners = null;
043:
044: public JDOAbstractHomeImpl() {
045: super (Personality.JDO);
046: }
047:
048: public JDOAbstractHomeImpl(TransactionalPersistenceManager atpm,
049: POManagerFactoryItf apmf) {
050: super (atpm, apmf);
051: }
052:
053: private List listener2events(Object listener) {
054: List eventTypes = new ArrayList();
055: if (listener instanceof AttachLifecycleListener) {
056: eventTypes.add(new Integer(HomeItf.PRE_ATTACH));
057: eventTypes.add(new Integer(HomeItf.POST_ATTACH));
058: }
059: if (listener instanceof DetachLifecycleListener) {
060: eventTypes.add(new Integer(HomeItf.PRE_DETACH));
061: eventTypes.add(new Integer(HomeItf.POST_DETACH));
062: }
063: if (listener instanceof ClearLifecycleListener) {
064: eventTypes.add(new Integer(HomeItf.PRE_CLEAR));
065: eventTypes.add(new Integer(HomeItf.POST_CLEAR));
066: }
067: if (listener instanceof CreateLifecycleListener) {
068: eventTypes.add(new Integer(HomeItf.POST_NEW));
069: }
070: if (listener instanceof DeleteLifecycleListener) {
071: eventTypes.add(new Integer(HomeItf.PRE_REMOVE));
072: eventTypes.add(new Integer(HomeItf.POST_REMOVE));
073: }
074: if (listener instanceof DirtyLifecycleListener) {
075: eventTypes.add(new Integer(HomeItf.PRE_DIRTY));
076: eventTypes.add(new Integer(HomeItf.POST_DIRTY));
077: }
078: if (listener instanceof LoadLifecycleListener) {
079: eventTypes.add(new Integer(HomeItf.POST_LOAD));
080: }
081: if (listener instanceof StoreLifecycleListener) {
082: eventTypes.add(new Integer(HomeItf.PRE_UPDATE));
083: eventTypes.add(new Integer(HomeItf.POST_UPDATE));
084: eventTypes.add(new Integer(HomeItf.PRE_CREATE));
085: eventTypes.add(new Integer(HomeItf.POST_CREATE));
086: eventTypes.add(new Integer(HomeItf.PRE_DELETE));
087: eventTypes.add(new Integer(HomeItf.POST_DELETE));
088: }
089: return eventTypes;
090: }
091:
092: /**
093: * Adds a listener for the current class
094: * @param listener is the new listener
095: */
096: public void addInstanceLifeCycleListener(Object listener) {
097: getLifecycleListener();
098: addListener(listener2events(listener), listener);
099: }
100:
101: /**
102: * Remove a listener for the current class
103: * @param listener is the listener to forget
104: */
105: public void removeInstanceLifeCycleListener(Object listener) {
106: getLifecycleListener();
107: removeListener(listener2events(listener), listener);
108: }
109:
110: public boolean hasInstanceLifeCycleListeners() {
111: return event2lifecycleListeners != null
112: && !event2lifecycleListeners.isEmpty();
113: }
114:
115: /**
116: * Instanciates the array of listener, the first time.
117: */
118: private void getLifecycleListener() {
119: if (event2lifecycleListeners == null) {
120: event2lifecycleListeners = new HashMap();
121: }
122: }
123:
124: /**
125: * Adds the listener for a particular type. If the listener is already
126: * present, the listener is not added.
127: * @param eventType specifies the type of the listener. This index corresponds
128: * to an index into the #lifecycleListener array.
129: * @param l is the listener to add
130: */
131: private synchronized void addListener(List eventTypes, Object l) {
132: if (eventTypes == null || l == null) {
133: return;
134: }
135: for (Iterator it = eventTypes.iterator(); it.hasNext();) {
136: addListener((Integer) it.next(),
137: (InstanceLifecycleListener) l);
138: }
139: }
140:
141: private void addListener(Integer eventType,
142: InstanceLifecycleListener listener) {
143: InstanceLifecycleListener[] ls = (InstanceLifecycleListener[]) event2lifecycleListeners
144: .get(eventType);
145: if (ls == null) {
146: ls = new InstanceLifecycleListener[] { listener };
147: } else {
148: List list = new ArrayList(Arrays.asList(ls));
149: if (!list.contains(listener)) {
150: list.add(listener);
151: ls = (InstanceLifecycleListener[]) list
152: .toArray(new InstanceLifecycleListener[list
153: .size()]);
154: }
155: }
156: event2lifecycleListeners.put(eventType, ls);
157: }
158:
159: private synchronized void removeListener(List eventTypes, Object l) {
160: if (eventTypes == null || l == null) {
161: return;
162: }
163: for (Iterator it = eventTypes.iterator(); it.hasNext();) {
164: removeListener((Integer) it.next(),
165: (InstanceLifecycleListener) l);
166: }
167: }
168:
169: /**
170: * Removes the listener for a particular type.
171: * @param eventType specifies the type of the listener. This index corresponds
172: * to an index into the #lifecycleListener array.
173: * @param l is the listener to remove
174: */
175: private void removeListener(Integer eventType, Object listener) {
176: if (event2lifecycleListeners == null) {
177: return;
178: }
179: InstanceLifecycleListener[] ls = (InstanceLifecycleListener[]) event2lifecycleListeners
180: .get(eventType);
181: if (ls != null) {
182: List list = new ArrayList(Arrays.asList(ls));
183: if (list.contains(listener)) {
184: list.remove(listener);
185: ls = (InstanceLifecycleListener[]) list
186: .toArray(new InstanceLifecycleListener[list
187: .size()]);
188: }
189: }
190: }
191:
192: public void sendEvent(int eventType, Object source, Object target) {
193: InstanceLifecycleListener[] ls = null;
194: if (event2lifecycleListeners != null) {
195: ls = (InstanceLifecycleListener[]) event2lifecycleListeners
196: .get(new Integer(eventType));
197: }
198: InstanceLifecycleEvent ev;
199: switch (eventType) {
200: case HomeItf.POST_NEW: //makePersist
201: if (ls != null) {
202: ev = new InstanceLifecycleEvent(source,
203: InstanceLifecycleEvent.CREATE, target);
204: for (int i = 0; i < ls.length; i++)
205: ((CreateLifecycleListener) ls[i]).postCreate(ev);
206: }
207: break;
208: case HomeItf.PRE_REMOVE: //deletePersistent
209: if (source instanceof DeleteCallback) {
210: ((DeleteCallback) source).jdoPreDelete();
211: }
212: if (ls != null) {
213: ev = new InstanceLifecycleEvent(source,
214: InstanceLifecycleEvent.DELETE, target);
215: for (int i = 0; i < ls.length; i++)
216: ((DeleteLifecycleListener) ls[i]).preDelete(ev);
217: }
218: break;
219: case HomeItf.POST_REMOVE://deletePersistent
220: if (ls != null) {
221: ev = new InstanceLifecycleEvent(source,
222: InstanceLifecycleEvent.DELETE, target);
223: for (int i = 0; i < ls.length; i++)
224: ((DeleteLifecycleListener) ls[i]).postDelete(ev);
225: }
226: break;
227:
228: case HomeItf.POST_LOAD:
229: if (source instanceof LoadCallback) {
230: ((LoadCallback) source).jdoPostLoad();
231: }
232: if (ls != null) {
233: ev = new InstanceLifecycleEvent(source,
234: InstanceLifecycleEvent.LOAD, target);
235: for (int i = 0; i < ls.length; i++)
236: ((LoadLifecycleListener) ls[i]).postLoad(ev);
237: }
238: break;
239: case HomeItf.PRE_DIRTY:
240: if (ls != null) {
241: ev = new InstanceLifecycleEvent(source,
242: InstanceLifecycleEvent.DIRTY, target);
243: for (int i = 0; i < ls.length; i++)
244: ((DirtyLifecycleListener) ls[i]).preDirty(ev);
245: }
246: break;
247: case HomeItf.POST_DIRTY:
248: if (ls != null) {
249: ev = new InstanceLifecycleEvent(source,
250: InstanceLifecycleEvent.DIRTY, target);
251: for (int i = 0; i < ls.length; i++)
252: ((DirtyLifecycleListener) ls[i]).postDirty(ev);
253: }
254: break;
255:
256: case HomeItf.PRE_CREATE: //INSERT
257: case HomeItf.PRE_UPDATE: //UPDATE
258: case HomeItf.PRE_DELETE: //DELETE
259: if (source instanceof StoreCallback) {
260: ((StoreCallback) source).jdoPreStore();
261: }
262: if (ls != null) {
263: ev = new InstanceLifecycleEvent(source,
264: InstanceLifecycleEvent.STORE, target);
265: for (int i = 0; i < ls.length; i++)
266: ((StoreLifecycleListener) ls[i]).preStore(ev);
267: }
268: break;
269: case HomeItf.POST_CREATE:
270: case HomeItf.POST_UPDATE:
271: case HomeItf.POST_DELETE:
272: if (ls != null) {
273: ev = new InstanceLifecycleEvent(source,
274: InstanceLifecycleEvent.STORE, target);
275: for (int i = 0; i < ls.length; i++)
276: ((StoreLifecycleListener) ls[i]).postStore(ev);
277: }
278: break;
279:
280: case HomeItf.PRE_CLEAR:
281: if (source instanceof ClearCallback) {
282: ((ClearCallback) source).jdoPreClear();
283: }
284: if (ls != null) {
285: ev = new InstanceLifecycleEvent(source,
286: InstanceLifecycleEvent.CLEAR, target);
287: for (int i = 0; i < ls.length; i++)
288: ((ClearLifecycleListener) ls[i]).preClear(ev);
289: }
290: break;
291: case HomeItf.POST_CLEAR:
292: if (ls != null) {
293: ev = new InstanceLifecycleEvent(source,
294: InstanceLifecycleEvent.CLEAR, target);
295: for (int i = 0; i < ls.length; i++)
296: ((ClearLifecycleListener) ls[i]).postClear(ev);
297: }
298: break;
299:
300: case HomeItf.PRE_ATTACH:
301: if (ls != null) {
302: ev = new InstanceLifecycleEvent(source,
303: InstanceLifecycleEvent.ATTACH, target);
304: for (int i = 0; i < ls.length; i++)
305: ((AttachLifecycleListener) ls[i]).preAttach(ev);
306: }
307: break;
308: case HomeItf.POST_ATTACH:
309: if (ls != null) {
310: ev = new InstanceLifecycleEvent(source,
311: InstanceLifecycleEvent.ATTACH, target);
312: for (int i = 0; i < ls.length; i++)
313: ((AttachLifecycleListener) ls[i]).postAttach(ev);
314: }
315: break;
316: case HomeItf.PRE_DETACH:
317: if (ls != null) {
318: ev = new InstanceLifecycleEvent(source,
319: InstanceLifecycleEvent.DETACH, target);
320: for (int i = 0; i < ls.length; i++)
321: ((DetachLifecycleListener) ls[i]).preDetach(ev);
322: }
323: break;
324: case HomeItf.POST_DETACH:
325: if (ls != null) {
326: ev = new InstanceLifecycleEvent(source,
327: InstanceLifecycleEvent.DETACH, target);
328: for (int i = 0; i < ls.length; i++)
329: ((DetachLifecycleListener) ls[i]).postDetach(ev);
330: }
331: break;
332: }
333: }
334: }
|