View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2009 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.model.tree;
14  
15  import java.awt.Rectangle;
16  import java.beans.PropertyChangeEvent;
17  import java.beans.PropertyChangeListener;
18  import java.util.Collections;
19  import java.util.Comparator;
20  import java.util.Enumeration;
21  import java.util.List;
22  import java.util.Vector;
23  
24  import javax.swing.JPopupMenu;
25  import javax.swing.JTree;
26  import javax.swing.event.TreeModelEvent;
27  import javax.swing.tree.TreeNode;
28  import javax.swing.tree.TreePath;
29  
30  import com.eviware.soapui.SoapUI;
31  import com.eviware.soapui.model.ModelItem;
32  import com.eviware.soapui.model.settings.SettingsListener;
33  import com.eviware.soapui.model.testsuite.TestCase;
34  import com.eviware.soapui.model.testsuite.TestStep;
35  import com.eviware.soapui.support.action.swing.ActionList;
36  import com.eviware.soapui.support.action.swing.ActionListBuilder;
37  import com.eviware.soapui.support.action.swing.ActionSupport;
38  
39  /***
40   * Abstract base class for SoapUITreeNode implementations
41   * 
42   * @author Ole.Matzura
43   */
44  
45  public abstract class AbstractModelItemTreeNode<T extends ModelItem> implements SoapUITreeNode, PropertyChangeListener
46  {
47  	private final T modelItem;
48  	private final ModelItem parentItem;
49  	private final SoapUITreeModel treeModel;
50  	private List<? extends SoapUITreeNode> orderItems;
51  	private String orderSetting;
52  	private InternalSettingsListener internalSettingsListener;
53  
54  	protected AbstractModelItemTreeNode( T modelItem, ModelItem parentItem, SoapUITreeModel treeModel )
55  	{
56  		this.modelItem = modelItem;
57  		this.parentItem = parentItem;
58  		this.treeModel = treeModel;
59  
60  		modelItem.addPropertyChangeListener( this );
61  	}
62  
63  	public SoapUITreeModel getTreeModel()
64  	{
65  		return treeModel;
66  	}
67  
68  	public T getModelItem()
69  	{
70  		return modelItem;
71  	}
72  
73  	public boolean valueChanged( Object newValue )
74  	{
75  		return false;
76  	}
77  
78  	public boolean isLeaf()
79  	{
80  		return getChildCount() == 0;
81  	}
82  
83  	public int getChildCount()
84  	{
85  		return orderItems == null ? 0 : orderItems.size();
86  	}
87  
88  	public SoapUITreeNode getChildNode( int index )
89  	{
90  		return orderItems == null ? null : orderItems.get( index );
91  	}
92  
93  	public int getIndexOfChild( Object child )
94  	{
95  		return orderItems == null ? -1 : orderItems.indexOf( child );
96  	}
97  
98  	public String toString()
99  	{
100 		if( modelItem instanceof TestStep )
101 			return ( ( TestStep )modelItem ).getLabel();
102 		else if( modelItem instanceof TestCase )
103 			return ( ( TestCase )modelItem ).getLabel();
104 
105 		return modelItem.getName();
106 	}
107 
108 	public JPopupMenu getPopup()
109 	{
110 		return ActionSupport.buildPopup( getActions() );
111 	}
112 
113 	public ActionList getActions()
114 	{
115 		return ActionListBuilder.buildActions( modelItem );
116 	}
117 
118 	public SoapUITreeNode getParentTreeNode()
119 	{
120 		return treeModel.getTreeNode( parentItem );
121 	}
122 
123 	public void propertyChange( PropertyChangeEvent evt )
124 	{
125 		String propertyName = evt.getPropertyName();
126 		if( propertyName.equals( ModelItem.NAME_PROPERTY ) || propertyName.equals( ModelItem.LABEL_PROPERTY ) )
127 		{
128 			// use this since length has probably changed
129 			getTreeModel().notifyNodeChanged( this );
130 		}
131 		else if( propertyName.equals( ModelItem.ICON_PROPERTY ) )
132 		{
133 			// hack to improve rendering performance
134 			JTree mainTree = SoapUI.getNavigator().getMainTree();
135 			TreePath nodePath = getTreeModel().getPath( this );
136 			Rectangle rowBounds = mainTree.getPathBounds( nodePath );
137 			if( rowBounds != null )
138 			{
139 				mainTree.repaint( rowBounds );
140 			}
141 		}
142 	}
143 
144 	public void release()
145 	{
146 		modelItem.removePropertyChangeListener( this );
147 
148 		if( internalSettingsListener != null )
149 			SoapUI.getSettings().removeSettingsListener( internalSettingsListener );
150 
151 		getTreeModel().unmapModelItem( modelItem );
152 	}
153 
154 	public <T2 extends SoapUITreeNode> void initOrdering( List<T2> items, String setting )
155 	{
156 		this.orderItems = items;
157 		this.orderSetting = setting;
158 
159 		internalSettingsListener = new InternalSettingsListener( this, setting );
160 		SoapUI.getSettings().addSettingsListener( internalSettingsListener );
161 		sortModelItems( items, setting );
162 	}
163 
164 	private final class InternalSettingsListener implements SettingsListener
165 	{
166 		private final AbstractModelItemTreeNode<?> node;
167 		private final String setting;
168 
169 		public InternalSettingsListener( AbstractModelItemTreeNode<?> node, String setting )
170 		{
171 			this.node = node;
172 			this.setting = setting;
173 		}
174 
175 		public void settingChanged( String name, String newValue, String oldValue )
176 		{
177 			if( name.equals( setting ) )
178 			{
179 				if( oldValue == null )
180 					oldValue = "false";
181 
182 				if( newValue == null )
183 					newValue = "false";
184 
185 				if( !oldValue.equals( newValue ) )
186 				{
187 					TreePath path = getTreeModel().getPath( AbstractModelItemTreeNode.this );
188 					node.reorder( SoapUI.getNavigator().isVisible( path ) && SoapUI.getNavigator().isExpanded( path ) );
189 				}
190 			}
191 		}
192 	}
193 
194 	public void reorder( boolean notify )
195 	{
196 		if( orderItems != null )
197 		{
198 			sortModelItems( orderItems, orderSetting );
199 
200 			if( notify )
201 			{
202 				getTreeModel().notifyStructureChanged( new TreeModelEvent( this, getTreeModel().getPath( this ) ) );
203 			}
204 		}
205 	}
206 
207 	public <T2 extends SoapUITreeNode> void sortModelItems( List<T2> modelItems, final String setting )
208 	{
209 		Collections.sort( modelItems, new Comparator<T2>()
210 		{
211 			public int compare( T2 o1, T2 o2 )
212 			{
213 				String name1 = o1.getModelItem().getName();
214 				String name2 = o2.getModelItem().getName();
215 
216 				if( name1 == null && name2 == null )
217 				{
218 					return 0;
219 				}
220 				else if( name1 == null )
221 				{
222 					return -1;
223 				}
224 				else if( name2 == null )
225 				{
226 					return 1;
227 				}
228 				else if( setting != null && SoapUI.getSettings().getBoolean( setting ) )
229 				{
230 					return name1.compareToIgnoreCase( name2 );
231 				}
232 				else
233 				{
234 					return name1.compareTo( name2 );
235 				}
236 			}
237 		} );
238 	}
239 
240 	public Enumeration<?> children()
241 	{
242 		Vector<TreeNode> children = new Vector<TreeNode>();
243 		for( int c = 0; c < getChildCount(); c++ )
244 			children.add( getChildAt( c ) );
245 
246 		return children.elements();
247 	}
248 
249 	public boolean getAllowsChildren()
250 	{
251 		return !isLeaf();
252 	}
253 
254 	public TreeNode getChildAt( int childIndex )
255 	{
256 		return getChildNode( childIndex );
257 	}
258 
259 	public int getIndex( TreeNode node )
260 	{
261 		return getIndexOfChild( node );
262 	}
263 
264 	public TreeNode getParent()
265 	{
266 		return getParentTreeNode();
267 	}
268 
269 	public class ReorderPropertyChangeListener implements PropertyChangeListener
270 	{
271 		public void propertyChange( PropertyChangeEvent arg0 )
272 		{
273 			reorder( true );
274 			SoapUI.getNavigator().selectModelItem( ( ModelItem )arg0.getSource() );
275 		}
276 	}
277 }