1   package junit.swingui;
2   
3   import java.util.*;
4   
5   import javax.swing.event.*;
6   import javax.swing.tree.*;
7   import junit.extensions.TestDecorator;
8   import junit.framework.*;
9   
10  /***
11   * A tree model for a Test.
12   */
13  class TestTreeModel implements TreeModel {
14  	private Test fRoot;
15  	private Vector fModelListeners= new Vector();
16  	private Hashtable fFailures= new Hashtable();
17  	private Hashtable fErrors= new Hashtable();
18  	private Hashtable fRunTests= new Hashtable();
19  	
20  	/***
21  	 * Constructs a tree model with the given test as its root.
22  	 */
23  	public TestTreeModel(Test root) {
24  		super();
25  		fRoot= root;
26  	}
27  	
28  	/***
29  	 * adds a TreeModelListener
30  	 */
31  	public void addTreeModelListener(TreeModelListener l) {
32  		if (!fModelListeners.contains(l))
33  			fModelListeners.addElement(l);
34  	}
35  	/***
36  	 * Removes a TestModelListener
37  	 */
38  	public void removeTreeModelListener(TreeModelListener l) {
39  		fModelListeners.removeElement(l);
40  	}
41  	/***
42  	 * Finds the path to a test. Returns the index of the test in its
43  	 * parent test suite.
44  	 */
45  	public int findTest(Test target, Test node, Vector path) {
46  		if (target.equals(node)) 
47  			return 0;
48  			
49  		TestSuite suite= isTestSuite(node);
50  		for (int i= 0; i < getChildCount(node); i++) {
51  			Test t= suite.testAt(i); 
52  			int index= findTest(target, t, path);
53  			if (index >= 0) {
54  				path.insertElementAt(node, 0);
55  				if (path.size() == 1)
56  					return i;
57  				return index;
58  			}
59  		}
60  		return -1;
61  	}
62  	/***
63  	 * Fires a node changed event
64  	 */
65  	public void fireNodeChanged(TreePath path, int index) {
66  		int[] indices= {index};
67  		Object[] changedChildren= {getChild(path.getLastPathComponent(), index)};
68  		TreeModelEvent event= new TreeModelEvent(this, path, indices, changedChildren);
69  		
70  		Enumeration e= fModelListeners.elements();
71  		while (e.hasMoreElements()) { 
72  			TreeModelListener l= (TreeModelListener) e.nextElement();
73  			l.treeNodesChanged(event);
74  		}	
75  	}
76  	/***
77  	 * Gets the test at the given index
78  	 */
79  	public Object getChild(Object parent, int index) {
80  		TestSuite suite= isTestSuite(parent);
81  		if (suite != null) 
82  			return suite.testAt(index);
83  		return null; 
84  	}
85  	/***
86  	 * Gets the number of tests.
87  	 */
88  	public int getChildCount(Object parent) {
89  		TestSuite suite= isTestSuite(parent);
90  		if (suite != null) 
91  			return suite.testCount();
92  		return 0;
93  	}
94  	/***
95  	 * Gets the index of a test in a test suite
96  	 */
97  	public int getIndexOfChild(Object parent, Object child) {
98  		TestSuite suite= isTestSuite(parent);
99  		if (suite != null) {
100 			int i= 0;
101 			for (Enumeration e= suite.tests(); e.hasMoreElements(); i++) {
102 				if (child.equals((Test)e.nextElement()))
103 					return i;
104 			}
105 		}
106 		return -1; 
107 	}
108 	/***
109 	 * Returns the root of the tree
110 	 */
111 	public Object getRoot() {
112 		return fRoot;
113 	}
114 	/***
115 	 * Tests if the test is a leaf.
116 	 */
117 	public boolean isLeaf(Object node) {
118 		return isTestSuite(node) == null;
119 	}
120 	/***
121 	 * Tests if the node is a TestSuite.
122 	 */
123 	TestSuite isTestSuite(Object node) {
124 		if (node instanceof TestSuite) 
125 			return (TestSuite)node;
126 		if (node instanceof TestDecorator) { 
127 			Test baseTest= ((TestDecorator)node).getTest(); 
128 			return isTestSuite(baseTest); 
129 		} 
130 		return null;
131 	}
132 	
133 	/***
134 	 * Called when the value of the model object was changed in the view
135 	 */
136 	public void valueForPathChanged(TreePath path, Object newValue) {
137 		// we don't support direct editing of the model
138 		System.out.println("TreeModel.valueForPathChanged: not implemented");
139 	}
140 	/***
141 	 * Remembers a test failure
142 	 */
143 	void addFailure(Test t) {
144 		fFailures.put(t, t);
145 	}
146 	/***
147 	 * Remembers a test error
148 	 */
149 	void addError(Test t) {
150 		fErrors.put(t, t);
151 	}
152 	/***
153 	 * Remembers that a test was run
154 	 */
155 	void addRunTest(Test t) {
156 		fRunTests.put(t, t);
157 	}
158 	/***
159 	 * Returns whether a test was run
160 	 */
161 	boolean wasRun(Test t) {
162 		return fRunTests.get(t) != null;
163 	}
164 	/***
165 	 * Tests whether a test was an error
166 	 */
167 	boolean isError(Test t) {
168 		return (fErrors != null) && fErrors.get(t) != null;
169 	}
170 	/***
171 	 * Tests whether a test was a failure
172 	 */
173 	boolean isFailure(Test t) {
174 		return (fFailures != null) && fFailures.get(t) != null;
175 	}
176 	/***
177 	 * Resets the test results
178 	 */
179 	void resetResults() {
180 		fFailures= new Hashtable();
181 		fRunTests= new Hashtable();
182 		fErrors= new Hashtable();
183 	}
184 }