/**
* Copyright (C) 2001-2005 France Telecom R&D
*/
package org.objectweb.speedo.mim.jdo.lib;
import org.objectweb.perseus.persistence.api.TransactionalPersistenceManager;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.mim.api.HomeItf;
import org.objectweb.speedo.mim.lib.AbstractHomeImpl;
import org.objectweb.speedo.pm.api.POManagerFactoryItf;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jdo.InstanceCallbacks;
import javax.jdo.listener.AttachLifecycleListener;
import javax.jdo.listener.ClearCallback;
import javax.jdo.listener.ClearLifecycleListener;
import javax.jdo.listener.CreateLifecycleListener;
import javax.jdo.listener.DeleteCallback;
import javax.jdo.listener.DeleteLifecycleListener;
import javax.jdo.listener.DetachLifecycleListener;
import javax.jdo.listener.DirtyLifecycleListener;
import javax.jdo.listener.InstanceLifecycleEvent;
import javax.jdo.listener.InstanceLifecycleListener;
import javax.jdo.listener.LoadCallback;
import javax.jdo.listener.LoadLifecycleListener;
import javax.jdo.listener.StoreCallback;
import javax.jdo.listener.StoreLifecycleListener;
public abstract class JDOAbstractHomeImpl extends AbstractHomeImpl {
/**
* The InstanceLifecycleListener instances registered for the current class
* key = Integer value representing the event type (HomeItf#ATTACH)
* value = InstanceLifecycleListener[]
* @see HomeItf#PRE_ATTACH
*/
private Map event2lifecycleListeners = null;
public JDOAbstractHomeImpl() {
super(Personality.JDO);
}
public JDOAbstractHomeImpl(TransactionalPersistenceManager atpm,
POManagerFactoryItf apmf) {
super(atpm, apmf);
}
private List listener2events(Object listener) {
List eventTypes = new ArrayList();
if (listener instanceof AttachLifecycleListener) {
eventTypes.add(new Integer(HomeItf.PRE_ATTACH));
eventTypes.add(new Integer(HomeItf.POST_ATTACH));
}
if (listener instanceof DetachLifecycleListener) {
eventTypes.add(new Integer(HomeItf.PRE_DETACH));
eventTypes.add(new Integer(HomeItf.POST_DETACH));
}
if (listener instanceof ClearLifecycleListener) {
eventTypes.add(new Integer(HomeItf.PRE_CLEAR));
eventTypes.add(new Integer(HomeItf.POST_CLEAR));
}
if (listener instanceof CreateLifecycleListener) {
eventTypes.add(new Integer(HomeItf.POST_NEW));
}
if (listener instanceof DeleteLifecycleListener) {
eventTypes.add(new Integer(HomeItf.PRE_REMOVE));
eventTypes.add(new Integer(HomeItf.POST_REMOVE));
}
if (listener instanceof DirtyLifecycleListener) {
eventTypes.add(new Integer(HomeItf.PRE_DIRTY));
eventTypes.add(new Integer(HomeItf.POST_DIRTY));
}
if (listener instanceof LoadLifecycleListener) {
eventTypes.add(new Integer(HomeItf.POST_LOAD));
}
if (listener instanceof StoreLifecycleListener) {
eventTypes.add(new Integer(HomeItf.PRE_UPDATE));
eventTypes.add(new Integer(HomeItf.POST_UPDATE));
eventTypes.add(new Integer(HomeItf.PRE_CREATE));
eventTypes.add(new Integer(HomeItf.POST_CREATE));
eventTypes.add(new Integer(HomeItf.PRE_DELETE));
eventTypes.add(new Integer(HomeItf.POST_DELETE));
}
return eventTypes;
}
/**
* Adds a listener for the current class
* @param listener is the new listener
*/
public void addInstanceLifeCycleListener(Object listener) {
getLifecycleListener();
addListener(listener2events(listener), listener);
}
/**
* Remove a listener for the current class
* @param listener is the listener to forget
*/
public void removeInstanceLifeCycleListener(Object listener) {
getLifecycleListener();
removeListener(listener2events(listener), listener);
}
public boolean hasInstanceLifeCycleListeners() {
return event2lifecycleListeners != null
&& !event2lifecycleListeners.isEmpty();
}
/**
* Instanciates the array of listener, the first time.
*/
private void getLifecycleListener() {
if (event2lifecycleListeners == null) {
event2lifecycleListeners = new HashMap();
}
}
/**
* Adds the listener for a particular type. If the listener is already
* present, the listener is not added.
* @param eventType specifies the type of the listener. This index corresponds
* to an index into the #lifecycleListener array.
* @param l is the listener to add
*/
private synchronized void addListener(List eventTypes, Object l) {
if (eventTypes == null || l == null) {
return;
}
for (Iterator it = eventTypes.iterator(); it.hasNext();) {
addListener((Integer) it.next(), (InstanceLifecycleListener) l);
}
}
private void addListener(Integer eventType, InstanceLifecycleListener listener) {
InstanceLifecycleListener[] ls = (InstanceLifecycleListener[])
event2lifecycleListeners.get(eventType);
if (ls == null) {
ls = new InstanceLifecycleListener[]{ listener};
} else {
List list = new ArrayList(Arrays.asList(ls));
if (!list.contains(listener)) {
list.add(listener);
ls = (InstanceLifecycleListener[])
list.toArray(new InstanceLifecycleListener[list.size()]);
}
}
event2lifecycleListeners.put(eventType, ls);
}
private synchronized void removeListener(List eventTypes, Object l) {
if (eventTypes == null || l == null) {
return;
}
for (Iterator it = eventTypes.iterator(); it.hasNext();) {
removeListener((Integer) it.next(), (InstanceLifecycleListener) l);
}
}
/**
* Removes the listener for a particular type.
* @param eventType specifies the type of the listener. This index corresponds
* to an index into the #lifecycleListener array.
* @param l is the listener to remove
*/
private void removeListener(Integer eventType, Object listener) {
if (event2lifecycleListeners == null) {
return;
}
InstanceLifecycleListener[] ls = (InstanceLifecycleListener[])
event2lifecycleListeners.get(eventType);
if (ls != null) {
List list = new ArrayList(Arrays.asList(ls));
if (list.contains(listener)) {
list.remove(listener);
ls = (InstanceLifecycleListener[])
list.toArray(new InstanceLifecycleListener[list.size()]);
}
}
}
public void sendEvent(int eventType, Object source, Object target) {
InstanceLifecycleListener[] ls = null;
if (event2lifecycleListeners != null) {
ls = (InstanceLifecycleListener[])
event2lifecycleListeners.get(new Integer(eventType));
}
InstanceLifecycleEvent ev;
switch(eventType) {
case HomeItf.POST_NEW: //makePersist
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.CREATE, target);
for(int i=0; i < ls.length; i++)
((CreateLifecycleListener) ls[i]).postCreate(ev);
}
break;
case HomeItf.PRE_REMOVE: //deletePersistent
if (source instanceof DeleteCallback) {
((DeleteCallback) source).jdoPreDelete();
}
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.DELETE, target);
for(int i=0; i < ls.length; i++)
((DeleteLifecycleListener) ls[i]).preDelete(ev);
}
break;
case HomeItf.POST_REMOVE://deletePersistent
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.DELETE, target);
for(int i=0; i < ls.length; i++)
((DeleteLifecycleListener) ls[i]).postDelete(ev);
}
break;
case HomeItf.POST_LOAD:
if (source instanceof LoadCallback) {
((LoadCallback) source).jdoPostLoad();
}
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.LOAD, target);
for(int i=0; i < ls.length; i++)
((LoadLifecycleListener) ls[i]).postLoad(ev);
}
break;
case HomeItf.PRE_DIRTY:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.DIRTY, target);
for(int i=0; i < ls.length; i++)
((DirtyLifecycleListener) ls[i]).preDirty(ev);
}
break;
case HomeItf.POST_DIRTY:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.DIRTY, target);
for(int i=0; i < ls.length; i++)
((DirtyLifecycleListener) ls[i]).postDirty(ev);
}
break;
case HomeItf.PRE_CREATE: //INSERT
case HomeItf.PRE_UPDATE: //UPDATE
case HomeItf.PRE_DELETE: //DELETE
if (source instanceof StoreCallback) {
((StoreCallback) source).jdoPreStore();
}
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.STORE, target);
for(int i=0; i < ls.length; i++)
((StoreLifecycleListener) ls[i]).preStore(ev);
}
break;
case HomeItf.POST_CREATE:
case HomeItf.POST_UPDATE:
case HomeItf.POST_DELETE:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.STORE, target);
for(int i=0; i < ls.length; i++)
((StoreLifecycleListener) ls[i]).postStore(ev);
}
break;
case HomeItf.PRE_CLEAR:
if (source instanceof ClearCallback) {
((ClearCallback) source).jdoPreClear();
}
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.CLEAR, target);
for(int i=0; i < ls.length; i++)
((ClearLifecycleListener) ls[i]).preClear(ev);
}
break;
case HomeItf.POST_CLEAR:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.CLEAR, target);
for(int i=0; i < ls.length; i++)
((ClearLifecycleListener) ls[i]).postClear(ev);
}
break;
case HomeItf.PRE_ATTACH:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.ATTACH, target);
for(int i=0; i < ls.length; i++)
((AttachLifecycleListener) ls[i]).preAttach(ev);
}
break;
case HomeItf.POST_ATTACH:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.ATTACH, target);
for(int i=0; i < ls.length; i++)
((AttachLifecycleListener) ls[i]).postAttach(ev);
}
break;
case HomeItf.PRE_DETACH:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.DETACH, target);
for(int i=0; i < ls.length; i++)
((DetachLifecycleListener) ls[i]).preDetach(ev);
}
break;
case HomeItf.POST_DETACH:
if (ls != null) {
ev = new InstanceLifecycleEvent(source, InstanceLifecycleEvent.DETACH, target);
for(int i=0; i < ls.length; i++)
((DetachLifecycleListener) ls[i]).postDetach(ev);
}
break;
}
}
}