/* * Copyright to the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.rioproject.tools.ui.servicenotification; import org.jdesktop.swingx.JXTreeTable; import org.jdesktop.swingx.treetable.AbstractMutableTreeTableNode; import org.jdesktop.swingx.treetable.DefaultTreeTableModel; import org.jdesktop.swingx.treetable.TreeTableNode; import org.rioproject.event.RemoteServiceEvent; import org.rioproject.log.ServiceLogEvent; import org.rioproject.monitor.ProvisionFailureEvent; import org.rioproject.monitor.ProvisionMonitorEvent; import org.rioproject.sla.SLAThresholdEvent; import org.rioproject.tools.ui.servicenotification.filter.FilterCriteria; import org.rioproject.tools.ui.servicenotification.filter.FilterHandler; import javax.swing.tree.TreePath; import java.util.*; /** * The RemoteEventTreeModel extends DefaultTreeTableModel providing the model to * display {@link ProvisionFailureEvent}s, {@link ServiceLogEvent}s, {@code SLAThresholdEvent}s * and {@code ProvisionMonitorEvent}s in a tree table. */ public class RemoteEventTreeModel extends DefaultTreeTableModel { private JXTreeTable treeTable; private FilterCriteria filterCriteria; private final RemoteServiceEventNodeComparator comparator = new RemoteServiceEventNodeComparator(); private final FilterHandler filterControl = new FilterHandler(); private final List<DeploymentNode> completeModel = new ArrayList<DeploymentNode>(); private final List<DeploymentNode> filteredModel = new ArrayList<DeploymentNode>(); private final String COMPLETE = "complete"; private final String FILTER = "filtered"; public RemoteEventTreeModel(RootNode root, java.util.List<String> columns) { super(root, columns); } public void setTreeTable(JXTreeTable treeTable) { this.treeTable = treeTable; } public synchronized void addItem(RemoteServiceEvent event) { RemoteServiceEventNode remoteServiceEventNode = createRemoteServiceEventNode(event); Map<String, DeploymentNode> nodes = getDeploymentNodes(remoteServiceEventNode.getOperationalStringName()); addItem(remoteServiceEventNode, nodes.get(COMPLETE), nodes.get(FILTER)); } private RemoteServiceEventNode createRemoteServiceEventNode(RemoteServiceEvent event) { RemoteServiceEventNode remoteServiceEventNode = null; if(event instanceof ProvisionFailureEvent) { ProvisionFailureEvent pfe = (ProvisionFailureEvent)event; remoteServiceEventNode = new ProvisionFailureEventNode(pfe); } if(event instanceof ProvisionMonitorEvent) { ProvisionMonitorEvent pme = (ProvisionMonitorEvent)event; remoteServiceEventNode = new ProvisionMonitorEventNode(pme); } if(event instanceof ServiceLogEvent) { ServiceLogEvent sle = (ServiceLogEvent)event; remoteServiceEventNode = new ServiceLogEventNode(sle); } if(event instanceof SLAThresholdEvent) { SLAThresholdEvent sla = (SLAThresholdEvent)event; remoteServiceEventNode = new SLAThresholdEventNode(sla); } return remoteServiceEventNode; } private boolean hasRemoteServiceEventNode(RemoteServiceEventNode node, AbstractMutableTreeTableNode parent) { boolean has = false; for(int i=0; i< parent.getChildCount(); i++) { RemoteServiceEventNode childNode =(RemoteServiceEventNode)parent.getChildAt(i); if(comparator.compare(childNode, node)==0&& (node.getEvent().getID()==childNode.getEvent().getID() && node.getEvent().getSequenceNumber()==childNode.getEvent().getSequenceNumber())) { has = true; break; } } return has; } private void addItem(AbstractMutableTreeTableNode node, AbstractMutableTreeTableNode parent, AbstractMutableTreeTableNode filterParent) { if(parent==null) return; synchronized (completeModel) { int index = parent.getChildCount(); if(node instanceof RemoteServiceEventNode) { RemoteServiceEventNode rNode = (RemoteServiceEventNode)node; if(hasRemoteServiceEventNode(rNode, parent)) return; if(filterParent!=null && hasRemoteServiceEventNode(rNode, filterParent)) return; /* If we have a filter and the node passes filter step, insert into filterModel */ if(filterCriteria!=null && filterParent!=null && filterControl.include(filterCriteria, rNode)) { index = getItemIndex(rNode, filterParent); if(index!=-1) { filterParent.insert(rNode, index); //this.modelSupport.fireChildAdded(new TreePath(getPathToRoot(filterParent)), index, rNode); this.modelSupport.fireTreeStructureChanged(new TreePath(getPathToRoot(filterParent))); } } /* Always insert into the complete model */ index = getItemIndex(rNode, parent); if(index!=-1) { parent.insert(node, index); if(filterCriteria==null) { this.modelSupport.fireChildAdded(new TreePath(getPathToRoot(parent)), index, rNode); } } } else { parent.insert(node, index); this.modelSupport.fireChildAdded(new TreePath(getPathToRoot(parent)), index, node); } } } private int getItemIndex(RemoteServiceEventNode rNode, AbstractMutableTreeTableNode parent) { int index = parent.getChildCount(); for (int i = 0; i < parent.getChildCount(); i++) { RemoteServiceEventNode childNode =(RemoteServiceEventNode)parent.getChildAt(i); int result = comparator.compare(childNode, rNode); if(result>0) { index = i; break; /* Check for duplicate events */ } else if(result==0) { if(rNode.getEvent().getID()==childNode.getEvent().getID() && rNode.getEvent().getSequenceNumber()==childNode.getEvent().getSequenceNumber()) { return -1; } } } return index; } public void reset() { this.modelSupport.fireNewRoot(); } public void removeItem(int row) { AbstractMutableTreeTableNode node = getNode(row); if(node!=null) { TreePath treePath = null; if(node instanceof DeploymentNode) { } else { DeploymentNode dNode = (DeploymentNode) node.getParent(); if(dNode!=null) treePath = treeTable.getPathForRow(getDeploymentNodeRow(dNode)); } removeItem(node); if(treePath!=null) { this.modelSupport.fireTreeStructureChanged(treePath); //this.modelSupport.fireChildrenRemoved(treePath, new int[]{row}, new Object[]{node}); } } } public void removeItem(AbstractMutableTreeTableNode node) { synchronized (completeModel) { if(node!=null) { AbstractMutableTreeTableNode parent = (AbstractMutableTreeTableNode)node.getParent(); removeNodeFromParent(node); this.modelSupport.fireTreeStructureChanged(new TreePath(getPathToRoot(parent))); DeploymentNode deploymentNode = null; if(node instanceof DeploymentNode) { deploymentNode = (DeploymentNode)node; } if(parent.getChildCount()==0 && parent.getParent()!=null) { removeNodeFromParent(parent); this.modelSupport.fireNewRoot(); deploymentNode = (DeploymentNode)parent; } if(deploymentNode!=null) { if(filterCriteria!=null) { filteredModel.remove(deploymentNode); DeploymentNode dNode = getDeploymentNode(deploymentNode.getName(), completeModel); if(dNode!=null) { completeModel.remove(dNode); } } else { completeModel.remove(deploymentNode); } } } } } @Override public TreeTableNode[] getPathToRoot(TreeTableNode aNode) { List<TreeTableNode> path = new ArrayList<TreeTableNode>(); TreeTableNode node = aNode; while (node != root && node!=null) { path.add(0, node); node = node.getParent(); } if (node == root) { path.add(0, node); } return path.toArray(new TreeTableNode[path.size()]); } public RemoteServiceEventNode getRemoteServiceEventNode(int row) { AbstractMutableTreeTableNode node = getNode(row); RemoteServiceEventNode eventNode = null; if(node instanceof RemoteServiceEventNode) { eventNode = (RemoteServiceEventNode)node; } return eventNode; } private Map<String, DeploymentNode> getDeploymentNodes(String name) { Map<String, DeploymentNode> nodeMap = new HashMap<String, DeploymentNode>(); if(name==null) { return nodeMap; } DeploymentNode node = getDeploymentNode(name, completeModel); if(node==null) { node = new DeploymentNode(name); completeModel.add(node); if(filterCriteria==null) { addItem(node, (AbstractMutableTreeTableNode)getRoot(), null); } } nodeMap.put(COMPLETE, node); if(filterCriteria!=null) { DeploymentNode filteredNode = getDeploymentNode(name, filteredModel); if(filteredNode==null) { filteredNode = new DeploymentNode(name); filteredModel.add(filteredNode); addItem(filteredNode, (AbstractMutableTreeTableNode)getRoot(), null); } nodeMap.put(FILTER, filteredNode); } else { nodeMap.put(FILTER, null); } return nodeMap; } public DeploymentNode getDeploymentNode(String name, List<DeploymentNode> nodes) { if(name==null) return null; DeploymentNode dNode = null; for(DeploymentNode node : nodes) { if(node.getName().equals(name)) { dNode = node; break; } } return dNode; } Collection<DeploymentNode> getDeploymentNodes() { Collection<DeploymentNode> dNodes = new ArrayList<DeploymentNode>(); if(filterCriteria!=null) { dNodes.addAll(filteredModel); } else { dNodes.addAll(completeModel); } return dNodes; } public void setFilterCriteria(FilterCriteria filterCriteria) { if(this.filterCriteria!=null && this.filterCriteria.equals(filterCriteria)) { return; } this.filterCriteria = filterCriteria; if(this.filterCriteria!=null) { clearTree(filteredModel.isEmpty()?completeModel:filteredModel); filteredModel.clear(); for(DeploymentNode node : completeModel) { DeploymentNode newNode = new DeploymentNode(node.getName()); filteredModel.add(newNode); } for(DeploymentNode node : filteredModel) { ((AbstractMutableTreeTableNode)getRoot()).insert(node, filteredModel.indexOf(node)); } for(DeploymentNode node : completeModel) { int index = 0; for(int i=0; i < node.getChildCount(); i++) { RemoteServiceEventNode rNode = (RemoteServiceEventNode)node.getChildAt(i); RemoteServiceEventNode newNode = createRemoteServiceEventNode(rNode.getEvent()); if(filterControl.include(this.filterCriteria, newNode)) { getDeploymentNode(node.getName(), filteredModel).insert(newNode, index++); } } } } else { clearTree(filteredModel); filteredModel.clear(); for(DeploymentNode node : completeModel) { ((AbstractMutableTreeTableNode)getRoot()).insert(node, completeModel.indexOf(node)); } } this.modelSupport.fireNewRoot(); } private void clearTree(Collection<DeploymentNode> nodes) { for(DeploymentNode node : nodes) { node.removeFromParent(); } } public FilterCriteria getFilterCriteria() { return filterCriteria; } public AbstractMutableTreeTableNode getNode(int row) { int rowCounter = 0; AbstractMutableTreeTableNode node = null; for (int i = 0; i < getRoot().getChildCount(); i++) { AbstractMutableTreeTableNode tn = (AbstractMutableTreeTableNode) getRoot().getChildAt(i); if (rowCounter == row) { node = tn; break; } if(treeTable.isExpanded(rowCounter)) { for (int j = 0; j < tn.getChildCount(); j++) { rowCounter++; if (rowCounter == row) { node = (AbstractMutableTreeTableNode) tn.getChildAt(j); break; } } } if (node != null) break; rowCounter++; } return node; } int getDeploymentNodeRow(DeploymentNode deploymentNode) { int row = -1; int rowCounter = 0; for (int i = 0; i < getRoot().getChildCount(); i++) { AbstractMutableTreeTableNode tn = (AbstractMutableTreeTableNode) getRoot().getChildAt(i); if(tn instanceof DeploymentNode && deploymentNode.equals(tn)) { row = rowCounter; break; } if (treeTable.isExpanded(rowCounter)) { for (int j = 0; j < tn.getChildCount(); j++) { rowCounter++; } } rowCounter++; } return row; } void updated(TreePath treePath) { this.modelSupport.firePathChanged(treePath); } @Override public Object getValueAt(Object node, int column) { /*if (!isValidTreeTableNode(node)) { throw new IllegalArgumentException("node must be a valid node managed by this model"); }*/ if (column < 0 || column >= getColumnCount()) { throw new IllegalArgumentException("column must be a valid index"); } TreeTableNode ttn = (TreeTableNode) node; if (column >= ttn.getColumnCount()) { return null; } return ttn.getValueAt(column); //return super.getValueAt(node, column); } @Override public boolean isLeaf(Object node) { return ((TreeTableNode) node).isLeaf(); } public int getRowCount() { int rowCounter = 0; for (int i = 0; i < getRoot().getChildCount(); i++) { DeploymentNode dn = (DeploymentNode)getRoot().getChildAt(i); rowCounter += dn.getChildCount(); } return rowCounter; } class RemoteServiceEventNodeComparator implements Comparator<RemoteServiceEventNode> { public int compare(RemoteServiceEventNode node1, RemoteServiceEventNode node2) { return node1.getDate().compareTo(node2.getDate()); } } }