/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package alma.acs.gui.loglevel.tree; import java.util.logging.Logger; import javax.swing.SwingWorker; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import org.omg.CORBA.ORB; import si.ijs.maci.ClientInfo; import si.ijs.maci.ComponentInfo; import si.ijs.maci.ContainerInfo; import si.ijs.maci.Manager; import alma.acs.gui.loglevel.tree.node.TreeClientInfo; import alma.acs.gui.loglevel.tree.node.TreeComponentInfo; import alma.acs.gui.loglevel.tree.node.TreeContainerInfo; import alma.acs.gui.loglevel.tree.node.TreeContentInfo; import alma.acs.gui.util.threadsupport.EDTExecutor; /** * The model for the tree of containers/components * * @author acaproni * */ public class LogLvlTreeModel extends DefaultTreeModel implements LogLevelListener { private static final long serialVersionUID = 4164177256689824546L; /** * A class to force a node to appear as non-leaf * * @author acaproni * */ public class NoLeafNode extends DefaultMutableTreeNode { private static final long serialVersionUID = 5681551972997000126L; /** * Constructor * * @param str The user object */ public NoLeafNode(Object obj) { super(obj); } /** * Force the node to be a non-leaf * * @return false */ public boolean isLeaf() { return false; } } // The client to get componets, conainers, clients from the manager private AdministratorClient admin=null; // The ORB private ORB orb=null; // The logger private Logger log=null; // The root node of the tree private DefaultMutableTreeNode rootNode = null; // The non leaf nodes for containers and clients // // Components are shown on the container node and in the Components node private DefaultMutableTreeNode managersNode = new NoLeafNode("Managers"); private DefaultMutableTreeNode clientsNode = new NoLeafNode("Clients"); private DefaultMutableTreeNode containersNode = new NoLeafNode("Containers"); // The node of components (it can be hidden depending on user taste) private DefaultMutableTreeNode componentsNode = new NoLeafNode("Components"); // The node of services private DefaultMutableTreeNode servicesNode = new NoLeafNode("Services"); /** * Constructor * */ public LogLvlTreeModel(ORB theOrb, Logger theLogger) { super(null); if (theOrb==null) { throw new IllegalArgumentException("Invalid null ORB"); } orb=theOrb; if (theLogger==null) { throw new IllegalArgumentException("Invalid null lOGGER"); } log=theLogger; } /** * Start the computation * * @throws Exception if an error happens while connecting */ public void start() throws Exception { if (admin!=null) { throw new IllegalArgumentException("Invalid op: call stop before (admin!=null)"); } SwingWorker<AdministratorClient, Void> worker = new SwingWorker<AdministratorClient, Void>() { protected AdministratorClient doInBackground() throws Exception { AdministratorClient tmp = new AdministratorClient(orb,log); try { tmp.connectToManager(); } catch (Exception e) { throw new Exception("Exception while connecting to manager",e); } return tmp; } }; worker.execute(); admin = worker.get(); refreshTree(); admin.addLogListener(this); } /** * Terminate the computation */ public void stop() { admin.addLogListener(null); // Remove the listener admin.disconnect(); admin=null; } /** * Build the tree. * It read the clients, components and containers and add them * to the tree. * */ public void refreshTree() { if (admin==null) { setRoot(null); if (rootNode!=null) { rootNode.removeAllChildren(); } rootNode=null; } rootNode= new DefaultMutableTreeNode("root"); managersNode.removeAllChildren(); clientsNode.removeAllChildren(); componentsNode.removeAllChildren(); containersNode.removeAllChildren(); servicesNode.removeAllChildren(); rootNode.add(managersNode); // rootNode.add(clientsNode); // yatagai:hide for now. rootNode.add(containersNode); // rootNode.add(componentsNode); // yatagai: not used any more rootNode.add(servicesNode); Object[] children = new Object[] { managersNode, clientsNode, containersNode, componentsNode, servicesNode }; int[] indexes = new int[] { rootNode.getIndex(managersNode), rootNode.getIndex(clientsNode), rootNode.getIndex(containersNode), rootNode.getIndex(componentsNode), rootNode.getIndex(servicesNode) }; fireTreeNodesInserted(rootNode, rootNode.getPath(), indexes, children); setRoot(rootNode); buildManagersNode(); buildClientsNode(); buildContainersNode(); buildComponentsNode(); buildServicesNode(); } /** * Build the node of managers */ private void buildManagersNode() { managersNode.add(new DefaultMutableTreeNode(formatManagerLoc(admin.getManagerLoc()))); } /** * Build the node of clients by reading the active clients * * @param clients */ private void buildClientsNode() { ClientInfo[] cliInfos; try { cliInfos=admin.retrieveClientInfo("*"); } catch (Exception e) { System.err.println("Exception caught while getting the clients: "+e.getMessage()); e.printStackTrace(System.err); clientsNode.removeAllChildren(); return; } if (cliInfos==null) { return; } for (ClientInfo c: cliInfos) { clientLoggedIn(c); } } /** * Build the node of containers by reading the active containers * */ private void buildContainersNode() { ContainerInfo[] contInfos; try { contInfos=admin.retrieveContainerInfo("*"); } catch (Exception e) { System.err.println("Exception caught while getting the clients: "+e.getMessage()); e.printStackTrace(System.err); containersNode.removeAllChildren(); return; } if (contInfos==null) { return; } for (ContainerInfo c: contInfos) { containerLoggedIn(c); } } /** * Build the list of components by reading the running components * * @param container */ private void buildComponentsNode() { ComponentInfo[] components=null; try { components=admin.retrieveComponentInfo("*"); } catch (Exception e) { System.err.println("Exception caught while retrieving active componenst: "+e.getMessage()); e.printStackTrace(System.err); } if (components==null) { return; } for (int t=0; t<components.length; t++) { componentLoggedIn(components[t]); } } /** * Build the list of services */ private void buildServicesNode() { servicesNode.add(new DefaultMutableTreeNode("CDB")); servicesNode.add(new DefaultMutableTreeNode("AcsAlarmService")); } /** * Fromat the manager loc in a more readable string * * @param manLoc The managerLoc (like corbaloc::....) * @return A humager readable string */ private String formatManagerLoc(String manLoc) { if (manLoc==null || manLoc.length()==0) { return "No manager connected"; } StringBuilder temp = new StringBuilder("Manager "); if (!manLoc.startsWith("corbaloc::")) { temp.append(manLoc); return temp.toString(); } temp.append("@ "); String[] strs = manLoc.split(":"); temp.append(strs[2]); temp.append(':'); strs=strs[3].split("/"); temp.append(strs[0]); return temp.toString(); } /** * Returns if the given node is the manager * * @param selNode the node to test * @return true if the node is the manager */ protected boolean isManagerNode(DefaultMutableTreeNode selNode) { return selNode.getUserObject().equals(formatManagerLoc(admin.getManagerLoc())); } /** * Returns if the given node is a service * * @param selNode the node to test * @return true if the node is a service */ protected boolean isServiceNode(DefaultMutableTreeNode selNode) { return !isManagerNode(selNode) && selNode.getUserObject() instanceof String; } /** * Navigate the tree to find a container with the given name or handle. * The search begins from the passed node and scans all the childs * until it finds the node. * The search is done comparing the name with the name of the item * hold by the tree node and its childreen. * If the name param is null, the handle is used. * * The method is recursive. * * @param node The root of the subtree to look for the * node. * If it is null, the search starts from the root. * @param name The name of the node i.e. the name of * the client/conatainer/component hold * by the node * If null, the handle is used during the search * @param handle The handle of the client/component/container to search * This param is used only if name is null * @return The first node in the tree with the given mane * null If such a node does not exist */ public DefaultMutableTreeNode findNode(DefaultMutableTreeNode node, String name, int handle) { if (node==null) { // The search starts from the root node = (DefaultMutableTreeNode)getRoot(); if (node==null) { // Ops no root found ==> node not found return null; } } if (checkNodeContent(node, name, handle)) { return node; } for (int t=0; t<node.getChildCount(); t++) { DefaultMutableTreeNode found=findNode((DefaultMutableTreeNode)node.getChildAt(t),name,handle); if (found!=null) { return found; } } return null; } /** * Check the content of the passed node. * The check is done taking the content of the Node and checking * if its name (or handle) is equal to the passed parameter. * The comparison is done on the name if the name param is not null, * otherwise on the handle. * * If the node is the root, name is checked against the string or rootNode * * @param node The node whose content has to be checked * @param name The name of the component/client/container * If it is null, it is ignored * @param handle The handle * (ignored if the name is not null) * @return true if the name or the handle contained in the node * are equal to the passed parameter * false otherwise (even if the node is null) */ private boolean checkNodeContent(DefaultMutableTreeNode node, String name, int handle) { if (node==null) { return false; } // Get the user object Object content=node.getUserObject(); if (content==null) { return false; } if (content instanceof TreeContentInfo) { TreeContentInfo info=(TreeContentInfo)content; if (name!=null) { return info.compareName(name); } return info.compareHandle(handle); } else if (content instanceof String) { // The passed node is the root, so check the content of the // string it contains against the name param // The content is a String for other nodes too (for // example the node Clients or Containers; i.e. some of the nodes // added to improve the readability of the tree) if (name==null) { // A String can never be equal to a handle! return false; } return ((String)content).compareTo(name)==0; } // The type of the user object is unknown System.out.println("Comparison failed because the content type is unknown: "+content.getClass().getName()); System.out.println("\t"+content.toString()); return false; } /** * @see LogLevelListener */ public void clientLoggedIn(ClientInfo clientInfo) { if (clientInfo==null) { throw new IllegalArgumentException("Invalid null ClientInfo"); } addNode(new TreeClientInfo(clientInfo), clientsNode); } /** * @see LogLevelListener */ public void clientLoggedOut(int clientHandle) { DefaultMutableTreeNode nodeToRemove = findNode(clientsNode, null, clientHandle); if (nodeToRemove!=null) { int idx = clientsNode.getIndex(nodeToRemove); clientsNode.remove(idx); Object[] children = new Object[] { nodeToRemove }; int[] indexes = new int[] { idx }; fireTreeNodesRemoved(clientsNode, clientsNode.getPath(), indexes, children); } } /** * @see LogLevelListener */ public void componentLoggedIn(ComponentInfo compInfo) { updateComponent(compInfo); TreeComponentInfo info = new TreeComponentInfo(compInfo); addNode(info,componentsNode); } /** * @see LogLevelListener */ public void componentReleased(ComponentInfo compInfo) { // Nothing to do because the component is still in use and must be // shown in its container } /** * @see LogLevelListener */ public void componentLoggedOut(int compHandle) { removeComponent(compHandle); removeFromComponentSubtree(compHandle); } /** * @see LogLevelListener */ public void containerLoggedIn(ContainerInfo contInfo) { if (findNode(null,contInfo.name, 0)!=null) { System.out.println(contInfo.name+" already in the tree"); } else { // Add the new container addNode(new TreeContainerInfo(contInfo), containersNode); } } /** * @see LogLevelListener */ public void containerLoggedOut(int conthandle) { DefaultMutableTreeNode contNode = findNode(containersNode,null, conthandle); if (contNode!=null) { System.out.println("Found a container node with handle "+conthandle); Object[] children = new Object[] { contNode }; int idx=containersNode.getIndex(contNode); int[] indexes = new int[] { idx }; containersNode.remove(contNode); fireTreeNodesRemoved(containersNode, containersNode.getPath(), indexes, children); } } /** * Add a component to its container if it is not already there * * @param info The component to add to the container */ private void updateComponent(ComponentInfo info) { if (info==null) { throw new IllegalArgumentException("Invalid null ComponentInfo"); } // Check if the component is already present (it can happen // if it is referenced by more then one client) if (findNode(containersNode,info.name, 0)!=null) { return; } // Look for a container with the name of the container of the // component DefaultMutableTreeNode contNode = findNode(containersNode,info.container_name, 0); if (contNode==null) { throw new IllegalStateException("Trying to add a component but the container does not exist!"); } addNode(new TreeComponentInfo(info),contNode); } /** * Remove all the occurrencies of the component with the given * handle from the tree * * @param handle The handle of the component to remove */ private void removeComponent(int handle) { // Look for a node with the given handle DefaultMutableTreeNode compNode = findNode(containersNode,null, handle); if (compNode==null) { // The node is not in the tree: nothing to do return; } DefaultMutableTreeNode parent = (DefaultMutableTreeNode)compNode.getParent(); int idx = parent.getIndex(compNode); parent.remove(compNode); Object[] children = new Object[] { compNode }; int[] indexes = new int[] { idx }; fireTreeNodesRemoved(parent,parent.getPath(), indexes, children); } /** * Remove a node from the subtree of components * * @param compHandle The handle of the component to remove */ private void removeFromComponentSubtree(int compHandle) { DefaultMutableTreeNode child = findNode(componentsNode, null, compHandle); if (child==null) { // The component is not in the list return; } int pos = componentsNode.getIndex(child); componentsNode.remove(pos); int[] indexes = new int[] { pos }; Object[] children = new Object[] { child }; fireTreeNodesRemoved(componentsNode, componentsNode.getPath(), indexes, children); } /** * show/hide the components subtree * * @param show If true the components node is set to visible */ public void showComponents(boolean show) { boolean isComponentsNodeVisible=findNode(null, "Components", 0)!=null; if (show) { if (isComponentsNodeVisible) { return; } // Add the node rootNode.add(componentsNode); int[] indexes = new int[] { rootNode.getIndex(componentsNode) }; Object[] children = new Object[] { componentsNode }; fireTreeNodesInserted(rootNode, rootNode.getPath(), indexes, children); } else { if (!isComponentsNodeVisible) { return; } // Remove the node int pos = rootNode.getIndex(componentsNode); rootNode.remove(componentsNode); int[] indexes = new int[] { pos }; Object[] children = new Object[] { componentsNode }; fireTreeNodesRemoved(rootNode, rootNode.getPath(), indexes, children); } } /** * show/hide the clients subtree * * @param show If true the clients node is set to visible */ public void showClients(boolean show) { boolean isCclientsNodeVisible=findNode(null, "Clients", 0)!=null; if (show) { if (isCclientsNodeVisible) { return; } // Add the node rootNode.add(clientsNode); int[] indexes = new int[] { rootNode.getIndex(clientsNode) }; Object[] children = new Object[] { clientsNode }; fireTreeNodesInserted(rootNode, rootNode.getPath(), indexes, children); } else { if (!isCclientsNodeVisible) { return; } // Remove the node int pos = rootNode.getIndex(clientsNode); rootNode.remove(clientsNode); int[] indexes = new int[] { pos }; Object[] children = new Object[] { clientsNode }; fireTreeNodesRemoved(rootNode, rootNode.getPath(), indexes, children); } } /** * Add an entry to a node. * The new node is inserted ordered by its name. * * @param newItem The new entry to add * @param node The node where the entry has to be added * */ private void addNode(final TreeContentInfo newItem, final DefaultMutableTreeNode node) { if (newItem==null) { throw new IllegalArgumentException("Invalid null item to add"); } if (node==null) { throw new IllegalArgumentException("Invalid null node to add the item to"); } EDTExecutor.instance().execute(new Runnable() { @Override public void run() { DefaultMutableTreeNode newChild = new DefaultMutableTreeNode(newItem); // Find the position to insert the new node int pos=0; boolean found=false; if (node.getChildCount()!=0) { for (int t=0; t<node.getChildCount(); t++) { DefaultMutableTreeNode child = (DefaultMutableTreeNode)node.getChildAt(t); String childName = ((TreeContentInfo)child.getUserObject()).getName(); if (childName.compareTo(newItem.getName())>0) { pos=t; found=true; break; } } } // Add the node in the right position if (found) { node.insert(newChild, pos); } else { // The node must be appended at the end of the list node.add(newChild); } // Trigger a refresh of the tree int[] indexes = new int[node.getChildCount()]; for (int t=0; t<indexes.length; t++) { indexes[t]=t; } Object[] children = new Object[indexes.length]; for (int t=0; t<indexes.length; t++) { children[t]=node.getChildAt(t); } fireTreeNodesInserted(node, node.getPath(), indexes, children); } }); } /** * Return the manager reference * * @return The manager reference or * null if the reference is not available */ public Manager getManagerRef() { if (admin==null) { return null; } return admin.getManagerRef(); } public AdministratorClient getAdminClient() { return admin; } }