summaryrefslogtreecommitdiff
path: root/src/main/java/com/c2kernel/gui/tree
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@cern.ch>2012-06-26 12:41:11 +0200
committerAndrew Branson <andrew.branson@cern.ch>2012-06-26 12:41:11 +0200
commit99eed1e3c7e7292aea91131baeb36f81e23e3e82 (patch)
treeeb1afe9e57736bb1e9113ece476b9d8f0dcc7917 /src/main/java/com/c2kernel/gui/tree
Initial refactor from kernel
Diffstat (limited to 'src/main/java/com/c2kernel/gui/tree')
-rw-r--r--src/main/java/com/c2kernel/gui/tree/Node.java232
-rw-r--r--src/main/java/com/c2kernel/gui/tree/NodeAgent.java33
-rw-r--r--src/main/java/com/c2kernel/gui/tree/NodeCollection.java68
-rw-r--r--src/main/java/com/c2kernel/gui/tree/NodeContext.java65
-rw-r--r--src/main/java/com/c2kernel/gui/tree/NodeEntity.java82
-rw-r--r--src/main/java/com/c2kernel/gui/tree/NodeItem.java112
-rw-r--r--src/main/java/com/c2kernel/gui/tree/NodeSubscriber.java13
7 files changed, 605 insertions, 0 deletions
diff --git a/src/main/java/com/c2kernel/gui/tree/Node.java b/src/main/java/com/c2kernel/gui/tree/Node.java
new file mode 100644
index 0000000..470eeba
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/Node.java
@@ -0,0 +1,232 @@
+package com.c2kernel.gui.tree;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.gui.DynamicTreeBuilder;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.AgentPath;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+public abstract class Node implements Runnable {
+
+ protected Path binding;
+ protected DefaultMutableTreeNode treeNode;
+ protected String name; // domain key
+ protected int sysKey; // target item
+ // attributes
+ protected String type = "";
+ protected Icon icon;
+ protected boolean isExpandable = false;
+ protected HashMap<Path, Node> childNodes = new HashMap<Path, Node>();
+ protected ArrayList<NodeSubscriber> subscribers = new ArrayList<NodeSubscriber>();
+ protected DynamicTreeBuilder loader = null;
+ private boolean loaded = false;
+ private String iconName;
+ protected EntityTabManager desktop;
+ static ImageIcon folder = Resource.findImage("folder.png");
+ static ImageIcon emptyLeaf = Resource.findImage("leaf.png");
+
+ public Node() {
+ }
+
+ protected void createTreeNode() {
+ this.treeNode = new DefaultMutableTreeNode(this);
+ }
+
+ public Node(Path path, EntityTabManager desktop) {
+ this.binding = path;
+ this.desktop = desktop;
+ this.sysKey = path.getSysKey();
+ // get the name of this node (last path element)
+ String[] pathComponents = path.getPath();
+ if (pathComponents.length > 0)
+ this.name = pathComponents[pathComponents.length-1];
+ else
+ this.name = Gateway.getProperty("Name");
+ }
+
+ public EntityTabManager getDesktop() {
+ return desktop;
+ }
+
+ public Node newNode(Path path)
+ {
+ try {
+ if (path.getEntity() instanceof AgentPath)
+ return new NodeAgent(path, desktop);
+ else
+ return new NodeItem(path, desktop);
+ } catch (ObjectNotFoundException ex) {
+ return new NodeContext(path, desktop);
+ }
+
+ }
+
+ /** Inserts a tree builder as the first child of the node, so it can be opened in the tree
+ */
+ public void makeExpandable() {
+ if (isExpandable) return;
+ loader = new DynamicTreeBuilder(this.treeNode);
+ this.treeNode.insert(loader.getTreeNode(),0);
+ isExpandable = true;
+ }
+
+
+ public DefaultMutableTreeNode getTreeNode() {
+ return treeNode;
+ }
+
+ public void setTreeNode(DefaultMutableTreeNode treeNode) {
+ this.treeNode = treeNode;
+ treeNode.setUserObject(this);
+ }
+
+ /** Subscription for loading node children.
+ * Note this is separate from the itemproxy subscription as it included query of the naming service
+ * and eventually should not require access to the item at all for higher performance */
+ public void subscribeNode(NodeSubscriber target) {
+ subscribers.add(target);
+ if (loaded == false) {
+ loaded = true;
+ loadMore();
+ }
+ else {
+ synchronized (childNodes) {
+ Node newNode;
+ for (Iterator<Node> nodes = childNodes.values().iterator(); nodes.hasNext();) {
+ newNode = nodes.next();
+ Logger.msg("subscribeNode target.add("+newNode.name+")");
+ target.add(newNode);
+ }
+ }
+ }
+ }
+
+ public void loadMore() {
+ Thread loading = new Thread(this);
+ loading.start();
+ }
+
+ public void unsubscribeNode(NodeSubscriber target) {
+ subscribers.remove(target);
+ }
+
+ public void add(Node newNode) {
+ synchronized(childNodes) {
+ childNodes.put(newNode.getPath(), newNode);
+ for (NodeSubscriber thisSub : subscribers) {
+ thisSub.add(newNode);
+ }
+ }
+ }
+
+ public void remove(Path oldPath) {
+ synchronized(childNodes) {
+ childNodes.remove(oldPath);
+ for (NodeSubscriber thisSub : subscribers) {
+ thisSub.remove(oldPath);
+ }
+ }
+ }
+
+ public void removeAllChildren() {
+ synchronized(childNodes) {
+ while (childNodes.keySet().iterator().hasNext()) {
+ remove(childNodes.keySet().iterator().next());
+ }
+ }
+ }
+
+ public Node getChildNode(Path itsPath) {
+ for (Iterator<Path> i = childNodes.keySet().iterator(); i.hasNext();) {
+ Object next = i.next();
+ if ( next.equals(itsPath) ) return childNodes.get(next);
+ }
+ return null;
+ }
+
+ // end of current batch
+ public void end(boolean more) {
+ for (NodeSubscriber thisSub : subscribers) {
+ thisSub.end(more);
+ }
+ }
+
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Node Loader: "+name);
+ loadChildren();
+ }
+
+ public abstract void loadChildren();
+
+ public void refresh() {
+ removeAllChildren();
+ loadChildren();
+ }
+
+ // Getters and Setters
+
+ public int getSysKey() { return sysKey; }
+// public void setSysKey( int sysKey ) { this.sysKey = sysKey; }
+
+ public String getName() { return name; }
+// public void setName( String name ) { this.name = name; }
+
+ public String getType() { return type; }
+// public void setType( String type ) { this.type = type; }
+
+ public Path getPath() { return binding; }
+
+ public DynamicTreeBuilder getTreeBuilder() { return loader; }
+
+ @Override
+ public String toString() {
+ if (this.name.length() > 0) {
+ return this.name;
+ }
+ else { return "Cristal"; }
+ }
+
+ public Icon getIcon() {
+ if (icon != null) return icon;
+ return(isExpandable?folder:emptyLeaf);
+ }
+
+ public String getIconName() {
+ return iconName;
+ }
+
+ public void setIcon(String icon) {
+ iconName = icon;
+ this.icon = Resource.findImage("typeicons/"+icon+"_16.png");
+ }
+
+ public JPopupMenu getPopupMenu() {
+ JPopupMenu popup = new JPopupMenu();
+ JMenuItem menuItem = new JMenuItem(Language.translate("Refresh"));
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (isExpandable) refresh();
+ }
+ });
+ popup.add(menuItem);
+ return popup;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tree/NodeAgent.java b/src/main/java/com/c2kernel/gui/tree/NodeAgent.java
new file mode 100644
index 0000000..45ffb07
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/NodeAgent.java
@@ -0,0 +1,33 @@
+
+package com.c2kernel.gui.tree;
+
+
+import java.util.ArrayList;
+
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.Path;
+
+/**
+ * Structure for Item presence on the tree and ItemDetails boxes. Created by NodeFactory.
+ * @author $Author: abranson $
+ * @version $Version$
+ */
+public class NodeAgent extends NodeEntity {
+
+ public NodeAgent(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ }
+
+ @Override
+ public void loadChildren() {
+ }
+
+ @Override
+ public ArrayList<String> getTabs() {
+
+ ArrayList<String> requiredTabs = super.getTabs();
+ requiredTabs.add("AgentProperties");
+ requiredTabs.add("JobList");
+ return requiredTabs;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tree/NodeCollection.java b/src/main/java/com/c2kernel/gui/tree/NodeCollection.java
new file mode 100644
index 0000000..631ed8b
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/NodeCollection.java
@@ -0,0 +1,68 @@
+package com.c2kernel.gui.tree;
+
+import java.util.ArrayList;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.collection.Parent2ChildCollection;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.utils.Logger;
+
+public class NodeCollection extends Node {
+
+ ItemProxy parent;
+ Parent2ChildCollection<CollectionMember> thisCollection;
+ String path;
+
+ public NodeCollection(ItemProxy parent, String name, EntityTabManager desktop) {
+ this.desktop = desktop;
+ this.parent = parent;
+ this.name = name;
+ this.path = parent.getSystemKey()+"/Collection/"+name;
+ createTreeNode();
+ this.makeExpandable();
+ }
+
+ @Override
+ public void loadChildren() {
+ Logger.msg(8, "NodeCollection::loadChildren()");
+ try {
+ thisCollection = (Parent2ChildCollection<CollectionMember>)parent.getObject("Collection/"+name);
+ } catch (ObjectNotFoundException ex) {
+ end(false);
+ return;
+ }
+
+ this.type = thisCollection.getClass().getName();
+ int lastDot = this.type.lastIndexOf('.');
+ if (lastDot > -1) this.type = this.type.substring(lastDot+1);
+ ArrayList<CollectionMember> collectionMembers = thisCollection.getMembers().list;
+ for (int i=0; i<collectionMembers.size(); i++)
+ {
+ CollectionMember aMember = collectionMembers.get(i);
+ if (aMember!=null)
+ try
+ {
+ EntityPath entityPath = new EntityPath(aMember.getEntityKey());
+ add(new NodeItem(entityPath, desktop));
+ }
+ catch (InvalidEntityPathException ex)
+ {
+ Logger.error("InvalidEntityPathException::NodeCollection::loadChildren() " + ex.toString());
+ }
+ }
+
+ end(false);
+
+ }
+
+ @Override
+ public DefaultMutableTreeNode getTreeNode() {
+ return treeNode;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tree/NodeContext.java b/src/main/java/com/c2kernel/gui/tree/NodeContext.java
new file mode 100644
index 0000000..b2d215c
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/NodeContext.java
@@ -0,0 +1,65 @@
+package com.c2kernel.gui.tree;
+
+import java.util.Enumeration;
+
+import com.c2kernel.entity.proxy.DomainPathSubscriber;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+
+public class NodeContext extends Node implements DomainPathSubscriber {
+ Enumeration<? extends Path> children;
+
+ public NodeContext(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ this.sysKey=Path.INVALID;
+ createTreeNode();
+ this.makeExpandable();
+ this.type = "Cristal Context";
+ }
+
+
+ @Override
+ public void loadChildren() {
+ if (children == null) {
+ Gateway.getProxyManager().subscribeTree(this, (DomainPath)binding);
+ children = binding.getChildren();
+ }
+
+ int batch = 75;
+ while (children.hasMoreElements() && batch > 0) {
+ Path newPath = children.nextElement();
+ if (newPath == null) break;
+ Logger.msg(2, "Subscription.run() - new node: " + newPath );
+ add( newNode(newPath));
+ batch--;
+ }
+ end(children.hasMoreElements());
+ }
+
+ @Override
+ public void pathAdded(DomainPath path) {
+ add(newNode(path));
+ }
+
+ @Override
+ public void refresh() {
+ children = null;
+ super.refresh();
+ }
+ @Override
+ public void pathRemoved(DomainPath path) {
+ remove(path);
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/src/main/java/com/c2kernel/gui/tree/NodeEntity.java b/src/main/java/com/c2kernel/gui/tree/NodeEntity.java
new file mode 100644
index 0000000..bc16a6c
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/NodeEntity.java
@@ -0,0 +1,82 @@
+package com.c2kernel.gui.tree;
+
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Structure for Item presence on the tree and ItemDetails boxes. Created by NodeFactory.
+ * @author $Author: abranson $
+ * @version $Version$
+ */
+public abstract class NodeEntity extends Node {
+
+ protected EntityProxy myEntity = null;
+
+ public NodeEntity(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ Logger.msg(2,"NodeEntity.<init> - Creating item for '"+path.toString()+"'.");
+
+ try {
+ // if an item - resolve the item and get its properties
+ myEntity = Gateway.getProxyManager().getProxy(path);
+ this.sysKey = path.getSysKey();
+ Logger.msg(2,"NodeEntity.<init> - System key is "+this.sysKey);
+
+ // Name should be the alias if present
+ String alias = myEntity.getName();
+ if (alias != null) this.name = alias;
+
+ this.type = myEntity.getProperty("Type");
+ String iconString = this.type;
+ if (type.equals("ActivityDesc")) iconString = myEntity.getProperty("Complexity")+iconString;
+ iconString = iconString.toLowerCase();
+ this.setIcon(iconString);
+ createTreeNode();
+ } catch (Exception e) {
+ Logger.msg(2, "NodeEntity.<init> - "+sysKey+" failed to resolve:");
+ Logger.error(e);
+ }
+ }
+
+ public EntityProxy getEntity() {
+ return myEntity;
+ }
+ /**
+ *
+ */
+ @Override
+ public JPopupMenu getPopupMenu() {
+ JPopupMenu popup = super.getPopupMenu();
+ JMenuItem openItem = new JMenuItem(Language.translate("Open"));
+ openItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ openItem();
+ }
+ });
+ popup.addSeparator();
+ popup.add(openItem);
+ return popup;
+ }
+
+ public void openItem() {
+ desktop.add(this);
+ }
+
+ public ArrayList<String> getTabs() {
+ ArrayList<String> requiredTabs = new ArrayList<String>();
+ return requiredTabs;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tree/NodeItem.java b/src/main/java/com/c2kernel/gui/tree/NodeItem.java
new file mode 100644
index 0000000..5d1f618
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/NodeItem.java
@@ -0,0 +1,112 @@
+package com.c2kernel.gui.tree;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.EntityDetails;
+import com.c2kernel.gui.EntityTabManager;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lookup.Path;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Structure for Item presence on the tree and ItemDetails boxes. Created by NodeFactory.
+ * @author $Author: abranson $
+ * @version $Version$
+ */
+public class NodeItem extends NodeEntity {
+
+ public NodeItem(Path path, EntityTabManager desktop) {
+ super(path, desktop);
+ try {
+ makeExpandable();
+ } catch (Exception e) {
+ Logger.error(e);
+ }
+ }
+
+ @Override
+ public void loadChildren() {
+ try {
+ String collections = myEntity.queryData("Collection/all");
+ StringTokenizer tok = new StringTokenizer(collections, ",");
+ while (tok.hasMoreTokens()) {
+ NodeCollection newCollection = new NodeCollection((ItemProxy)myEntity, tok.nextToken(), desktop);
+ add(newCollection);
+ }
+ end(false);
+ } catch (Exception e) {
+ Logger.error(e);
+ }
+ }
+
+ @Override
+ public JPopupMenu getPopupMenu() {
+ JPopupMenu popup = super.getPopupMenu();
+ popup.addSeparator();
+ try {
+ ArrayList<Job> jobList = ((ItemProxy)myEntity).getJobList(MainFrame.userAgent);
+ ArrayList<String> already = new ArrayList<String>();
+ if (jobList.size() > 0) {
+ for (Job thisJob : jobList) {
+ String stepName = thisJob.getStepName();
+ if (already.contains(stepName))
+ continue;
+ already.add(stepName);
+ JMenuItem menuItem = new JMenuItem(stepName);
+ menuItem.setActionCommand(stepName);
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ execute(e.getActionCommand());
+ }
+ });
+ popup.add(menuItem);
+
+ }
+ }
+ else {
+ JMenuItem noAct = new JMenuItem("No activities");
+ noAct.setEnabled(false);
+ popup.add(noAct);
+ }
+ } catch (Exception ex) {
+ JMenuItem error = new JMenuItem("Error querying jobs");
+ error.setEnabled(false);
+ popup.add(error);
+ }
+
+ return popup;
+ }
+
+ public void execute(String stepName) {
+ EntityDetails thisDetail = desktop.add(this);
+ thisDetail.runCommand("Execution", stepName);
+ }
+
+ @Override
+ public ArrayList<String> getTabs() {
+
+ ArrayList<String> requiredTabs = super.getTabs();
+ requiredTabs.add("Properties");
+ try {
+ String collNames = myEntity.queryData(ClusterStorage.COLLECTION+"/all");
+ if (collNames.length() > 0)
+ requiredTabs.add("Collection");
+ } catch (Exception e) { }
+ requiredTabs.add("Execution");
+ requiredTabs.add("History");
+ requiredTabs.add("Viewpoint");
+ requiredTabs.add("Workflow");
+ return requiredTabs;
+
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tree/NodeSubscriber.java b/src/main/java/com/c2kernel/gui/tree/NodeSubscriber.java
new file mode 100644
index 0000000..55f8aa9
--- /dev/null
+++ b/src/main/java/com/c2kernel/gui/tree/NodeSubscriber.java
@@ -0,0 +1,13 @@
+package com.c2kernel.gui.tree;
+
+import com.c2kernel.lookup.Path;
+
+
+public interface NodeSubscriber {
+
+ public void add(Node newNode);
+
+ public void remove(Path path);
+
+ public void end(boolean more);
+}