View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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 		@Override
194 		public void settingsReloaded()
195 		{
196 			// TODO Auto-generated method stub
197 		}
198 	}
199 
200 	public void reorder( boolean notify )
201 	{
202 		if( orderItems != null )
203 		{
204 			sortModelItems( orderItems, orderSetting );
205 
206 			if( notify )
207 			{
208 				getTreeModel().notifyStructureChanged( new TreeModelEvent( this, getTreeModel().getPath( this ) ) );
209 			}
210 		}
211 	}
212 
213 	public <T2 extends SoapUITreeNode> void sortModelItems( List<T2> modelItems, final String setting )
214 	{
215 		Collections.sort( modelItems, new Comparator<T2>()
216 		{
217 			public int compare( T2 o1, T2 o2 )
218 			{
219 				String name1 = o1.getModelItem().getName();
220 				String name2 = o2.getModelItem().getName();
221 
222 				if( name1 == null && name2 == null )
223 				{
224 					return 0;
225 				}
226 				else if( name1 == null )
227 				{
228 					return -1;
229 				}
230 				else if( name2 == null )
231 				{
232 					return 1;
233 				}
234 				else if( setting != null && SoapUI.getSettings().getBoolean( setting ) )
235 				{
236 					return name1.compareToIgnoreCase( name2 );
237 				}
238 				else
239 				{
240 					return name1.compareTo( name2 );
241 				}
242 			}
243 		} );
244 	}
245 
246 	public Enumeration<?> children()
247 	{
248 		Vector<TreeNode> children = new Vector<TreeNode>();
249 		for( int c = 0; c < getChildCount(); c++ )
250 			children.add( getChildAt( c ) );
251 
252 		return children.elements();
253 	}
254 
255 	public boolean getAllowsChildren()
256 	{
257 		return !isLeaf();
258 	}
259 
260 	public TreeNode getChildAt( int childIndex )
261 	{
262 		return getChildNode( childIndex );
263 	}
264 
265 	public int getIndex( TreeNode node )
266 	{
267 		return getIndexOfChild( node );
268 	}
269 
270 	public TreeNode getParent()
271 	{
272 		return getParentTreeNode();
273 	}
274 
275 	public class ReorderPropertyChangeListener implements PropertyChangeListener
276 	{
277 		public void propertyChange( PropertyChangeEvent arg0 )
278 		{
279 			reorder( true );
280 			SoapUI.getNavigator().selectModelItem( ( ModelItem )arg0.getSource() );
281 		}
282 	}
283 }