001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.gui.tree;
020:
021: import java.util.Enumeration;
022: import java.util.Iterator;
023: import java.util.LinkedList;
024: import java.util.List;
025:
026: import javax.swing.tree.DefaultTreeModel;
027:
028: import org.apache.jmeter.config.gui.AbstractConfigGui;
029: import org.apache.jmeter.control.gui.TestPlanGui;
030: import org.apache.jmeter.control.gui.WorkBenchGui;
031: import org.apache.jmeter.exceptions.IllegalUserActionException;
032: import org.apache.jmeter.gui.GuiPackage;
033: import org.apache.jmeter.gui.JMeterGUIComponent;
034: import org.apache.jmeter.testelement.TestElement;
035: import org.apache.jmeter.testelement.TestPlan;
036: import org.apache.jmeter.testelement.WorkBench;
037: import org.apache.jmeter.testelement.property.NullProperty;
038: import org.apache.jmeter.util.NameUpdater;
039: import org.apache.jorphan.collections.HashTree;
040: import org.apache.jorphan.collections.ListedHashTree;
041:
042: public class JMeterTreeModel extends DefaultTreeModel {
043:
044: public JMeterTreeModel(TestElement tp, TestElement wb) {
045: super (new JMeterTreeNode(wb, null));
046: initTree(tp, wb);
047: }
048:
049: public JMeterTreeModel() {
050: this (new TestPlanGui().createTestElement(), new WorkBenchGui()
051: .createTestElement());
052: // super(new JMeterTreeNode(new WorkBenchGui().createTestElement(), null));
053: // TestElement tp = new TestPlanGui().createTestElement();
054: // initTree(tp);
055: }
056:
057: /**
058: * Hack to allow TreeModel to be used in non-GUI and headless mode.
059: *
060: * @deprecated - only for use by JMeter class!
061: * @param o - dummy
062: */
063: public JMeterTreeModel(Object o) {
064: this (new TestPlan(), new WorkBench());
065: // super(new JMeterTreeNode(new WorkBench(), null));
066: // TestElement tp = new TestPlan();
067: // initTree(tp, new WorkBench());
068: }
069:
070: /**
071: * Returns a list of tree nodes that hold objects of the given class type.
072: * If none are found, an empty list is returned.
073: */
074: public List getNodesOfType(Class type) {
075: List nodeList = new LinkedList();
076: traverseAndFind(type, (JMeterTreeNode) this .getRoot(), nodeList);
077: return nodeList;
078: }
079:
080: /**
081: * Get the node for a given TestElement object.
082: */
083: public JMeterTreeNode getNodeOf(TestElement userObject) {
084: return traverseAndFind(userObject, (JMeterTreeNode) getRoot());
085: }
086:
087: /**
088: * Adds the sub tree at the given node. Returns a boolean indicating whether
089: * the added sub tree was a full test plan.
090: */
091: public HashTree addSubTree(HashTree subTree, JMeterTreeNode current)
092: throws IllegalUserActionException {
093: Iterator iter = subTree.list().iterator();
094: while (iter.hasNext()) {
095: TestElement item = (TestElement) iter.next();
096: if (item instanceof TestPlan) {
097: TestPlan tp = (TestPlan) item;
098: current = (JMeterTreeNode) ((JMeterTreeNode) getRoot())
099: .getChildAt(0);
100: final TestPlan userObject = (TestPlan) current
101: .getUserObject();
102: userObject.addTestElement(item);
103: userObject.setName(item.getName());
104: userObject.setFunctionalMode(tp.isFunctionalMode());
105: userObject.setSerialized(tp.isSerialized());
106: addSubTree(subTree.getTree(item), current);
107: } else if (item instanceof WorkBench) {
108: current = (JMeterTreeNode) ((JMeterTreeNode) getRoot())
109: .getChildAt(1);
110: final TestElement testElement = ((TestElement) current
111: .getUserObject());
112: testElement.addTestElement(item);
113: testElement.setName(item.getName());
114: addSubTree(subTree.getTree(item), current);
115: } else {
116: addSubTree(subTree.getTree(item), addComponent(item,
117: current));
118: }
119: }
120: return getCurrentSubTree(current);
121: }
122:
123: public JMeterTreeNode addComponent(TestElement component,
124: JMeterTreeNode node) throws IllegalUserActionException {
125: if (node.getUserObject() instanceof AbstractConfigGui) {
126: throw new IllegalUserActionException(
127: "This node cannot hold sub-elements");
128: }
129: component.setProperty(TestElement.GUI_CLASS, NameUpdater
130: .getCurrentName(component
131: .getPropertyAsString(TestElement.GUI_CLASS)));
132:
133: GuiPackage guiPackage = GuiPackage.getInstance();
134: if (guiPackage != null) {
135: // The node can be added in non GUI mode at startup
136: guiPackage.updateCurrentNode();
137: JMeterGUIComponent guicomp = guiPackage.getGui(component);
138: guicomp.configure(component);
139: guicomp.modifyTestElement(component);
140: guiPackage.getCurrentGui(); // put the gui object back
141: // to the way it was.
142: }
143: JMeterTreeNode newNode = new JMeterTreeNode(component, this );
144:
145: // This check the state of the TestElement and if returns false it
146: // disable the loaded node
147: try {
148: if (component.getProperty(TestElement.ENABLED) instanceof NullProperty
149: || component
150: .getPropertyAsBoolean(TestElement.ENABLED)) {
151: newNode.setEnabled(true);
152: } else {
153: newNode.setEnabled(false);
154: }
155: } catch (Exception e) {
156: newNode.setEnabled(true);
157: }
158:
159: this .insertNodeInto(newNode, node, node.getChildCount());
160: return newNode;
161: }
162:
163: public void removeNodeFromParent(JMeterTreeNode node) {
164: if (!(node.getUserObject() instanceof TestPlan)
165: && !(node.getUserObject() instanceof WorkBench)) {
166: super .removeNodeFromParent(node);
167: }
168: }
169:
170: private void traverseAndFind(Class type, JMeterTreeNode node,
171: List nodeList) {
172: if (type.isInstance(node.getUserObject())) {
173: nodeList.add(node);
174: }
175: Enumeration enumNode = node.children();
176: while (enumNode.hasMoreElements()) {
177: JMeterTreeNode child = (JMeterTreeNode) enumNode
178: .nextElement();
179: traverseAndFind(type, child, nodeList);
180: }
181: }
182:
183: private JMeterTreeNode traverseAndFind(TestElement userObject,
184: JMeterTreeNode node) {
185: if (userObject == node.getUserObject()) {
186: return node;
187: }
188: Enumeration enumNode = node.children();
189: while (enumNode.hasMoreElements()) {
190: JMeterTreeNode child = (JMeterTreeNode) enumNode
191: .nextElement();
192: JMeterTreeNode result = traverseAndFind(userObject, child);
193: if (result != null)
194: return result;
195: }
196: return null;
197: }
198:
199: public HashTree getCurrentSubTree(JMeterTreeNode node) {
200: ListedHashTree hashTree = new ListedHashTree(node);
201: Enumeration enumNode = node.children();
202: while (enumNode.hasMoreElements()) {
203: JMeterTreeNode child = (JMeterTreeNode) enumNode
204: .nextElement();
205: hashTree.add(node, getCurrentSubTree(child));
206: }
207: return hashTree;
208: }
209:
210: public HashTree getTestPlan() {
211: return getCurrentSubTree((JMeterTreeNode) ((JMeterTreeNode) this
212: .getRoot()).getChildAt(0));
213: }
214:
215: /**
216: * Clear the test plan, and use default node for test plan and workbench
217: */
218: public void clearTestPlan() {
219: TestElement tp = new TestPlanGui().createTestElement();
220: clearTestPlan(tp);
221: }
222:
223: /**
224: * Clear the test plan, and use specified node for test plan and default node for workbench
225: *
226: * @param testPlan the node to use as the testplan top node
227: */
228: public void clearTestPlan(TestElement testPlan) {
229: // Remove the workbench and testplan nodes
230: int children = getChildCount(getRoot());
231: while (children > 0) {
232: JMeterTreeNode child = (JMeterTreeNode) getChild(getRoot(),
233: 0);
234: super .removeNodeFromParent(child);
235: children = getChildCount(getRoot());
236: }
237: // Init the tree
238: initTree(testPlan, new WorkBenchGui().createTestElement()); // Assumes this is only called from GUI mode
239: }
240:
241: /**
242: * Initialize the model with nodes for testplan and workbench.
243: *
244: * @param tp the element to use as testplan
245: * @param wb the element to use as workbench
246: */
247: private void initTree(TestElement tp, TestElement wb) {
248: // Insert the test plan node
249: insertNodeInto(new JMeterTreeNode(tp, this ),
250: (JMeterTreeNode) getRoot(), 0);
251: // Insert the workbench node
252: insertNodeInto(new JMeterTreeNode(wb, this ),
253: (JMeterTreeNode) getRoot(), 1);
254: // Let others know that the tree content has changed.
255: // This should not be necessary, but without it, nodes are not shown when the user
256: // uses the Close menu item
257: nodeStructureChanged((JMeterTreeNode) getRoot());
258: }
259: }
|