package org.cloudgraph.web.model.graph; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudgraph.common.CloudGraphConstants; import org.cloudgraph.web.model.ModelBean; import org.cloudgraph.web.model.tree.GraphTreeNodeModel; import org.cloudgraph.web.model.tree.TreeNodeTypeMap; import org.plasma.sdo.PlasmaProperty; import org.plasma.sdo.PlasmaType; import org.plasma.sdo.core.CoreDataObject; import org.plasma.sdo.profile.KeyType; import commonj.sdo.DataGraph; import commonj.sdo.DataObject; import commonj.sdo.Property; import commonj.sdo.Type; public abstract class DynamicGraphTreeBean extends ModelBean { private static final long serialVersionUID = 1L; private static Log log = LogFactory.getLog(DynamicGraphTreeBean.class); private long ids = 0; private GraphTreeNodeModel treeRoot; //private TreeState treeState; protected TreeNodeTypeMap typeMap; protected NodeLabelFormat labelFormat; private boolean displayNodeHelpText = true; protected Set<Integer> ajaxKeys = new HashSet<Integer>(); public DynamicGraphTreeBean() { } public DynamicGraphTreeBean(TreeNodeTypeMap typeMap) { this.typeMap = typeMap; } public GraphTreeNodeModel getModel() { return this.treeRoot; } //public void setTreeState(TreeState treeState) {this.treeState = treeState;} //public TreeState getTreeState() {return treeState;} public boolean isDisplayNodeHelpText() { return displayNodeHelpText; } public void setDisplayNodeHelpText(boolean displayNodeHelpText) { this.displayNodeHelpText = displayNodeHelpText; } public TreeNodeTypeMap getTypeMap() { return typeMap; } public void setTypeMap(TreeNodeTypeMap typeMap) { this.typeMap = typeMap; } /** * Init the tree structure. Load only the top-level nodes and then add/remove * child tree nodes dynamically based on user input, instead of loading all of * the nodes on instantiation. * @param model - the data graph with all the pertinent db data. */ protected void initTree(DataGraph[] graphs) { treeRoot = new GraphTreeNodeModel(++ids); treeRoot.setUserData("root"); treeRoot.setLevel(0); for (int i = 0; i < graphs.length; i++) { DataObject topObject = graphs[i].getRootObject(); DataObjectNode objectNode = new DataObjectNode(topObject, null); GraphTreeNodeModel topNode = new GraphTreeNodeModel(++ids); topNode.setIsRoot(true); topNode.setEnabled(true); // its visible name and label topNode.setName(topObject.getType().getName()); if (this.labelFormat == null) topNode.setLabel(objectNode.getLabel()); else topNode.setLabel( this.labelFormat.getLabel(objectNode)); if (this.displayNodeHelpText) { topNode.setTooltip(((PlasmaType)topObject.getType()).getName()); } topNode.setLevel(treeRoot.getLevel() + 1); topNode.setType(typeMap.getTreeNodeType(topNode.getLevel())); topNode.setUserData(objectNode); if (log.isDebugEnabled()) log.debug("created top node: " + "(" + topNode.getType() + ") " + topNode.getLabel()); if (this.getChildCount(topObject) == 0) topNode.setLeaf(true); else topNode.setLeaf(false); treeRoot.addNode(topNode); } } /** * The tree expand expand listener method. */ /* public void processExpansion(NodeExpandedEvent nodeExpandedEvent){ // get the source or the component who fired this event. Object source = nodeExpandedEvent.getSource(); if (source instanceof HtmlTreeNode) { // It should be a html tree node, if yes get // the ui tree which contains this node. UITree tree = ((HtmlTreeNode) source).getUITree(); // avoid null pointer exceptions even though not needed. but safety first ;-) if (tree == null) { return; } // get the row key i.e. id of the given node. Object rowKey = tree.getRowKey(); // get node expanded state. boolean isExpanded = false; if (getTreeState() != null) isExpanded = getTreeState().isExpanded((TreeRowKey) rowKey); else isExpanded = tree.isExpanded(); // get the model node of this node. GraphTreeNodeModel selectedTreeModelNode = (GraphTreeNodeModel) tree.getTreeNode(rowKey); if(null != selectedTreeModelNode){ if (isExpanded) { // add the children nodes. addChildrenNodes(selectedTreeModelNode); } else { // remove the children nodes. Iterator<?> it = selectedTreeModelNode.getChildren(); while (it.hasNext()) { it.next(); it.remove(); } } } } } */ /** * Method for adding children nodes to a given tree model node. */ /* public void addChildrenNodes(GraphTreeNodeModel parentNode){ DataObject parentDataObject = null; if (parentNode.getUserData() instanceof DataObjectNode) { DataObjectNode dataObjectNode = (DataObjectNode)parentNode.getUserData(); parentDataObject = dataObjectNode.getDataObject(); } else throw new IllegalStateException("expected DataObjectNode as user-data"); CommonNode[] childObjects = this.getChild(parentDataObject); if (childObjects == null || childObjects.length == 0) return; if (parentNode.getChildren() != null && parentNode.getChildren().hasNext()) { log.warn("found existing children - clearing and re-adding"); //parentNode.getNodes().clear(); //return; } for (CommonNode childObject : childObjects) { GraphTreeNodeModel childNode = new GraphTreeNodeModel(++ids); childNode.setEnabled(true); childNode.setName(childObject.getName()); if (this.labelFormat == null) childNode.setLabel(childObject.getLabel()); else childNode.setLabel( this.labelFormat.getLabel(childObject)); if (this.displayNodeHelpText) childNode.setTooltip(childObject.getLabel()); childNode.setLevel(parentNode.getLevel() + 2); childNode.setType(typeMap.getTreeNodeType(childNode.getLevel())); childNode.setUserData(childObject); if (log.isDebugEnabled()) log.debug("created child node: " + "(" + childNode.getType() + ") " + childNode.getLabel()); if (childObject instanceof DataObjectNode) { DataObjectNode objectNode = (DataObjectNode)childObject; if (this.getChildCount(objectNode.getDataObject()) == 0) childNode.setLeaf(true); else childNode.setLeaf(false); } else childNode.setLeaf(true); parentNode.addNode(childNode); } } */ private CommonNode[] getChild(DataObject parent) { List<CommonNode> list = new ArrayList<CommonNode>(); for (Property prop : parent.getType().getProperties()) { if (prop.getType().isDataType()) { PlasmaProperty p = (PlasmaProperty)prop; if (p.isKey(KeyType.primary)) continue; // boring if (parent.isSet(prop)) list.add(new DataPropertyNode(prop, parent)); } else { if (prop.isMany()) { List<DataObject> childList = parent.getList(prop); if (childList != null) { for (DataObject child : childList) list.add(new DataObjectNode(child, prop)); } } else { DataObject child = parent.getDataObject(prop); if (child != null) list.add(new DataObjectNode(child, prop)); } } } CommonNode[] result = new CommonNode[list.size()]; list.toArray(result); return result; } private int getChildCount(DataObject parent) { int count = 0; for (Property prop : parent.getType().getProperties()) { if (prop.getType().isDataType()) { PlasmaProperty p = (PlasmaProperty)prop; if (p.isKey(KeyType.primary)) continue; // boring if (parent.isSet(prop)) count++; } else { if (prop.isMany()) { List list = parent.getList(prop); if (list != null) count += list.size(); } else { DataObject child = parent.getDataObject(prop); if (child != null) count++; } } } return count; } public NodeLabelFormat getLabelFormat() { return labelFormat; } public void setLabelFormat(NodeLabelFormat labelFormat) { this.labelFormat = labelFormat; } }