package org.nightlabs.jfire.personrelation.issuetracking.trade.ui.extended;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.jdo.FetchPlan;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.nightlabs.base.ui.resource.SharedImages;
import org.nightlabs.jdo.NLJDOHelper;
import org.nightlabs.jdo.ObjectID;
import org.nightlabs.jfire.person.Person;
import org.nightlabs.jfire.personrelation.PersonRelation;
import org.nightlabs.jfire.personrelation.PersonRelationType;
import org.nightlabs.jfire.personrelation.dao.PersonRelationDAO;
import org.nightlabs.jfire.personrelation.id.PersonRelationID;
import org.nightlabs.jfire.personrelation.issuetracking.trade.ui.Activator;
import org.nightlabs.jfire.personrelation.ui.tree.AbstractPersonRelationTreeLabelProviderDelegate;
import org.nightlabs.jfire.personrelation.ui.tree.PersonRelationTreeController;
import org.nightlabs.jfire.personrelation.ui.tree.PersonRelationTreeNode;
import org.nightlabs.jfire.prop.PropertySet;
import org.nightlabs.jfire.prop.id.PropertySetID;
import org.nightlabs.progress.NullProgressMonitor;
/**
* Handles the more specialised {@link LabelProvider}s for displaying nodes containing {@link PropertySet}s.
*
* @author khaireel (at) nightlabs (dot) de
*/
public class PropertySetTreeLabelProviderDelegate extends AbstractPersonRelationTreeLabelProviderDelegate {
@Override
public Class<?> getJDOObjectClass() { return Person.class; }
@Override
public Class<? extends ObjectID> getJDOObjectIDClass() { return PropertySetID.class; }
@Override
public int[][] getJDOObjectColumnSpan(ObjectID jdoObjectID, Object jdoObject) { return null; }
@Override
public String getJDOObjectText(ObjectID jdoObjectID, Object jdoObject, int spanColIndex) {
return null; // Let the default LabelProvider in the PersonRelationTree handle this.
}
@Override
public Image getJDOObjectImage(ObjectID jdoObjectID, Object jdoObject, int spanColIndex) {
// Here's the tricky bit: Handling the PropertySet means we are handling the cases when we are at the
// root node(s) of the PersonRelationTree, where the forward relations to its children is not necessarily straight-forward.
//
// For example, (ignoring all children that do not contain a PersonRelation type):
// Case I [straight-forward]: If ALL of the root's children are of the same PersonRelationType,
// then this root's relation to ALL it's children is simply the reversed PersonRelationType.
//
// Case II [non-straight-forward]: Otherwise, we cannot be sure what the root's relation to its children is.
// In this case, do we revert to the default icon?
//
// Now, in order to check the children, we need access to the PersonRelationTreeController, where the map between
// the JDOObjectID and the actual PersonRelationTreeNode is held.
// This should expedite stuffs; since this method is called several times for the exact same jdoObjectID!
Image image = objectID2Image.get(jdoObjectID);
if (image != null)
return image;
// Cautiously work to access the data of the LAZY tree.
// See notes on progress-steps.
// Lazy-progress: Step 1.
List<PersonRelationTreeNode> treeNodeList = personRelationTreeController.getTreeNodeList(jdoObjectID);
if (treeNodeList == null || treeNodeList.isEmpty())
return null;
// Lazy progress: Step 2.
PersonRelationTreeNode rootNode = treeNodeList.get(0); // We can simply pick the first because we are examining only the children -- and all children of a given node is the same!
long rootNodeChildCount = personRelationTreeController.getNodeCount(rootNode);
if (rootNodeChildCount < 0)
return null;
// Lazy progress: Step 3. Now we should be ready.
if (rootNodeChildCount == 0)
return null; // <-- This means that rootNode has no children. Fall-back and let the default procedure take over.
// We examine all the children for [Case I].
// i.e. We should be able to access the children's ObjectIDs, without loading the rest of the Objects.
List<ObjectID> childrenJDOObjectIDs = rootNode.getChildrenJDOObjectIDs();
PersonRelationType relationTypeToRoot = null;
for (ObjectID childObjectID : childrenJDOObjectIDs) {
if (childObjectID instanceof PersonRelationID) {
PersonRelation personRelation = getPersonRelation((PersonRelationID) childObjectID);
PersonRelationType personRelationType = personRelation.getPersonRelationType();
if (relationTypeToRoot == null)
relationTypeToRoot = personRelationType;
else {
if (!relationTypeToRoot.equals(personRelationType)) {
// [Case II] Stop and no need to figure out the relations anymore. This root doesnt have a unique relationship with its children.
Image nodeIcon = SharedImages.getSharedImage(Activator.getDefault(), PersonRelationTreeLabelProviderDelegate.class, "");
objectID2Image.put((PropertySetID) jdoObjectID, nodeIcon);
return nodeIcon;
}
}
}
}
// One last check:
if (relationTypeToRoot == null)
return null;
// If we have survived up till here, then we have found [Case I] to be true.
String personRelationTypeID = relationTypeToRoot.getReversePersonRelationTypeID().personRelationTypeID;
Image nodeIcon = SharedImages.getSharedImage(Activator.getDefault(), PersonRelationTreeLabelProviderDelegate.class, personRelationTypeID);
objectID2Image.put((PropertySetID) jdoObjectID, nodeIcon);
return nodeIcon;
}
private PersonRelationTreeController<PersonRelationTreeNode> personRelationTreeController;
private Map<PropertySetID, Image> objectID2Image = new WeakHashMap<PropertySetID, Image>();
/**
* Creates a new instance of the PropertySetTreeLabelProviderDelegate, with a reference to a valid {@link PersonRelationTreeController}.
*/
public PropertySetTreeLabelProviderDelegate(PersonRelationTreeController<PersonRelationTreeNode> personRelationTreeController) {
this.personRelationTreeController = personRelationTreeController;
}
// TODO Think: Is this a good way? We just need the PersonRelation reference to the ID. Should do this in a Job/SWT thread?
private PersonRelation getPersonRelation(final PersonRelationID personRelationID) {
return PersonRelationDAO.sharedInstance().getPersonRelation(
personRelationID, new String[] {FetchPlan.DEFAULT, PersonRelation.FETCH_GROUP_PERSON_RELATION_TYPE},
NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new NullProgressMonitor());
}
}