package org.nightlabs.jfire.personrelation.ui.tree;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.nightlabs.jdo.ObjectID;
import org.nightlabs.jfire.base.ui.jdo.tree.lazy.ActiveJDOObjectLazyTreeController;
import org.nightlabs.jfire.jdo.notification.TreeNodeMultiParentResolver;
import org.nightlabs.jfire.jdo.notification.TreeNodeParentResolver;
import org.nightlabs.jfire.personrelation.PersonRelationParentResolverProxy;
import org.nightlabs.jfire.personrelation.id.PersonRelationID;
import org.nightlabs.jfire.personrelation.ui.resource.Messages;
import org.nightlabs.jfire.prop.id.PropertySetID;
import org.nightlabs.progress.ProgressMonitor;
import org.nightlabs.progress.SubProgressMonitor;
public abstract class PersonRelationTreeController<N extends PersonRelationTreeNode>
extends ActiveJDOObjectLazyTreeController<ObjectID, Object, N>
{
private static final Logger logger = Logger.getLogger(PersonRelationTreeController.class);
public PersonRelationTreeController(boolean addDefaultDelegate) {
if (addDefaultDelegate) {
addPersonRelationTreeControllerDelegate(new DefaultPersonRelationTreeControllerDelegate<N>(this));
}
}
private List<IPersonRelationTreeControllerDelegate> personRelationTreeControllerDelegates = new ArrayList<IPersonRelationTreeControllerDelegate>();
private List<IPersonRelationTreeControllerDelegate> _personRelationTreeControllerDelegates = null;
public List<IPersonRelationTreeControllerDelegate> getPersonRelationTreeControllerDelegates() {
List<IPersonRelationTreeControllerDelegate> delegates = _personRelationTreeControllerDelegates;
if (delegates == null) {
synchronized (personRelationTreeControllerDelegates) {
delegates = _personRelationTreeControllerDelegates;
if (delegates == null) {
delegates = new ArrayList<IPersonRelationTreeControllerDelegate>(personRelationTreeControllerDelegates);
delegates = Collections.unmodifiableList(delegates);
_personRelationTreeControllerDelegates = delegates;
}
}
}
return delegates;
}
public void addPersonRelationTreeControllerDelegate(IPersonRelationTreeControllerDelegate delegate)
{
synchronized (personRelationTreeControllerDelegates) {
unregisterChangeListener();
personRelationTreeControllerDelegates.add(delegate);
PersonRelationParentResolverProxy personRelationParentResolver = (PersonRelationParentResolverProxy) getTreeNodeMultiParentResolver();
TreeNodeMultiParentResolver parentResolverDelegate = delegate.getPersonRelationParentResolverDelegate();
if (parentResolverDelegate != null)
personRelationParentResolver.addDelegate(parentResolverDelegate);
_personRelationTreeControllerDelegates = null;
jdoObjectClasses = null;
registerChangeListener();
registerJDOLifecycleListener();
}
clear();
}
/**
* Returns the delegate of the given class, if present, <code>null</code> otherwise.
*
* @param <T>
* @param clazz
* @return
*/
public <T extends IPersonRelationTreeControllerDelegate> T getPersonRelationTreeControllerDelegate(Class<T> clazz)
{
List<IPersonRelationTreeControllerDelegate> delegates = getPersonRelationTreeControllerDelegates();
for (IPersonRelationTreeControllerDelegate delegate : delegates) {
if (clazz.isInstance(delegate)) {
return (T) delegate;
}
}
return null;
}
@Override
public void clear() {
super.clear();
}
@Override
protected TreeNodeParentResolver createTreeNodeParentResolver() {
throw new UnsupportedOperationException("This method should not be called because we're using a TreeNode*Multi*ParentResolver!"); //$NON-NLS-1$
}
@Override
protected TreeNodeMultiParentResolver createTreeNodeMultiParentResolver() {
return new PersonRelationParentResolverProxy();
}
@Override
protected Class<?> getJDOObjectClass() {
throw new UnsupportedOperationException("This method should not be called because we have overridden 'getJDOObjectClasses()' below."); //$NON-NLS-1$
}
private Set<Class<? extends Object>> jdoObjectClasses = null;
@Override
protected Set<Class<? extends Object>> getJDOObjectClasses() {
Set<Class<? extends Object>> classes = jdoObjectClasses;
if (classes == null) {
synchronized (personRelationTreeControllerDelegates) {
classes = jdoObjectClasses;
if (classes == null) {
List<IPersonRelationTreeControllerDelegate> delegates = getPersonRelationTreeControllerDelegates();
classes = new HashSet<Class<? extends Object>>();
for (IPersonRelationTreeControllerDelegate delegate : delegates) {
classes.addAll(delegate.getJDOObjectClasses());
}
jdoObjectClasses = classes;
}
}
}
return classes;
}
@Override
protected Collection<Object> retrieveJDOObjects(Set<ObjectID> objectIDs, ProgressMonitor monitor) {
List<IPersonRelationTreeControllerDelegate> delegates = getPersonRelationTreeControllerDelegates();
monitor.beginTask(Messages.getString("org.nightlabs.jfire.personrelation.ui.PersonRelationTreeController.task.retrievingObjects.name"), 10 * delegates.size()); //$NON-NLS-1$
try {
Set<PropertySetID> personIDs = null;
Set<PersonRelationID> personRelationIDs = null;
Set<ObjectID> objectIDsLeft = new HashSet<ObjectID>(objectIDs);
Collection<Object> result = new ArrayList<Object>(objectIDs.size());
for (IPersonRelationTreeControllerDelegate delegate : delegates) {
if (objectIDsLeft.isEmpty())
break;
Collection<? extends Object> objects = delegate.retrieveJDOObjects(Collections.unmodifiableSet(objectIDsLeft), new SubProgressMonitor(monitor, 10));
if (objects != null) {
for (Object object : objects) {
Object objectID = delegate.getJDOObjectID(object);
if (objectID == null)
throw new IllegalStateException("delegate.getJDOObjectID(object) returned null! delegate=" + delegate + " object=" + object); //$NON-NLS-1$ //$NON-NLS-2$
objectIDsLeft.remove(objectID);
result.add(object);
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("retrieveJDOObjects: objectIDs.size=" + objectIDs.size() + " result.size=" + result.size()); //$NON-NLS-1$ //$NON-NLS-2$
if (logger.isTraceEnabled()) {
for (Object object : result) {
logger.trace("retrieveJDOObjects: * " + object); //$NON-NLS-1$
}
}
}
return result;
} finally {
monitor.done();
}
}
/**
* This is the abstract method from the super class, which we don't use in this {@link PersonRelationTreeController}'s implementation.
* Instead, we are in favour of the other method: retrieveChildCount(Set<ObjectID> parentIDs, ProgressMonitor monitor).
* See comments in the superclass {@link ActiveJDOObjectLazyTreeController}.
*/
@Override
protected Map<ObjectID, Long> retrieveChildCount(Set<ObjectID> parentIDs, ProgressMonitor monitor) { return null; }
@Override
protected Map<ObjectID, Long> retrieveChildCount(Set<N> parentNodes, Set<ObjectID> parentIDs, ProgressMonitor monitor) {
List<IPersonRelationTreeControllerDelegate> delegates = getPersonRelationTreeControllerDelegates();
Map<ObjectID, Long> result = new HashMap<ObjectID, Long>(parentIDs.size());
monitor.beginTask(Messages.getString("org.nightlabs.jfire.personrelation.ui.PersonRelationTreeController.task.retrievingChildCounts.name"), 10 * delegates.size()); //$NON-NLS-1$
try {
for (IPersonRelationTreeControllerDelegate delegate : delegates) {
Map<ObjectID, Long> delegateChildCountMap = delegate.retrieveChildCount(parentNodes, parentIDs, new SubProgressMonitor(monitor, 10));
for (Map.Entry<ObjectID, Long> me : delegateChildCountMap.entrySet()) {
ObjectID parentID = me.getKey();
Long childCount = me.getValue();
if (childCount == null)
childCount = 0L;
Long resultChildCount = result.get(parentID);
if (resultChildCount == null)
resultChildCount = childCount;
else
resultChildCount += childCount;
result.put(parentID, resultChildCount);
}
}
return result;
} finally {
monitor.done();
}
}
// -------------------------------------------------------------------------------------------------- ++ ------>>
/**
* This is the abstract method from the super class, which we don't use in this {@link PersonRelationTreeController} implementation.
* Instead, we are in favour of the other method: retrieveChildObjectIDs(N parentNode, ProgressMonitor monitor).
* See comments in the superclass {@link ActiveJDOObjectLazyTreeController}.
*/
@Override
protected Collection<ObjectID> retrieveChildObjectIDs(ObjectID parentID, ProgressMonitor monitor) { return null; }
@Override
protected Collection<ObjectID> retrieveChildObjectIDs(N parentNode, ProgressMonitor monitor) {
Collection<ObjectID> result = new ArrayList<ObjectID>(); // Note: It is from the index position of this Collection that we know the position of the child-nodes.
// And if we are to impose any ordering of the nodes, this should be the place to affect it. Kai.
List<IPersonRelationTreeControllerDelegate> delegates = getPersonRelationTreeControllerDelegates();
monitor.beginTask(Messages.getString("org.nightlabs.jfire.personrelation.ui.PersonRelationTreeController.task.retrievingChildIDs.name"), 10 * delegates.size()); //$NON-NLS-1$
try {
for (IPersonRelationTreeControllerDelegate delegate : delegates) {
Collection<? extends ObjectID> childObjectIDs = delegate.retrieveChildObjectIDs(parentNode, new SubProgressMonitor(monitor, 20));
if (childObjectIDs != null)
result.addAll(childObjectIDs);
}
return result;
} finally {
monitor.done();
}
}
@Override
protected ObjectID getJDOObjectID(Object jdoObject) {
ObjectID superResult = super.getJDOObjectID(jdoObject);
if (superResult != null)
return superResult;
List<IPersonRelationTreeControllerDelegate> delegates = getPersonRelationTreeControllerDelegates();
for (IPersonRelationTreeControllerDelegate delegate : delegates) {
ObjectID delegateResult = delegate.getJDOObjectID(jdoObject);
if (delegateResult != null)
return delegateResult;
}
return null;
}
}