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.util.ArrayList;
16  import java.util.HashMap;
17  import java.util.HashSet;
18  import java.util.Iterator;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.Set;
22  
23  import javax.swing.event.TreeModelEvent;
24  import javax.swing.event.TreeModelListener;
25  import javax.swing.tree.TreeModel;
26  import javax.swing.tree.TreePath;
27  
28  import org.apache.log4j.Logger;
29  
30  import com.eviware.soapui.model.ModelItem;
31  import com.eviware.soapui.model.tree.nodes.PropertiesTreeNode;
32  import com.eviware.soapui.model.tree.nodes.PropertyTreeNode;
33  import com.eviware.soapui.model.tree.nodes.WorkspaceTreeNode;
34  import com.eviware.soapui.model.workspace.Workspace;
35  
36  /***
37   * The Navigator TreeModel
38   * 
39   * @author Ole.Matzura
40   */
41  
42  public class SoapUITreeModel implements TreeModel
43  {
44  	private Set<TreeModelListener> listeners = new HashSet<TreeModelListener>();
45  	private SoapUITreeNode workspaceNode;
46  	private final static Logger logger = Logger.getLogger( SoapUITreeModel.class );
47  	private Map<ModelItem, SoapUITreeNode> modelItemMap = new HashMap<ModelItem, SoapUITreeNode>();
48  	private boolean showProperties = false;
49  
50  	public SoapUITreeModel( Workspace workspace )
51  	{
52  		workspaceNode = new WorkspaceTreeNode( workspace, this );
53  		mapModelItem( workspaceNode );
54  	}
55  
56  	public Object getRoot()
57  	{
58  		return workspaceNode;
59  	}
60  
61  	public Object getChild( Object parent, int index )
62  	{
63  		SoapUITreeNode treeNode = ( SoapUITreeNode )parent;
64  		return treeNode.getChildNode( index );
65  	}
66  
67  	public int getChildCount( Object parent )
68  	{
69  		SoapUITreeNode treeNode = ( SoapUITreeNode )parent;
70  		return treeNode.getChildCount();
71  	}
72  
73  	public boolean isLeaf( Object node )
74  	{
75  		SoapUITreeNode treeNode = ( SoapUITreeNode )node;
76  		return treeNode.isLeaf();
77  	}
78  
79  	public void valueForPathChanged( TreePath path, Object newValue )
80  	{
81  		SoapUITreeNode treeNode = ( SoapUITreeNode )path.getLastPathComponent();
82  		if( treeNode.valueChanged( newValue ) )
83  		{
84  			// not implemented.. need to expose setName in ModelItem
85  		}
86  	}
87  
88  	public int getIndexOfChild( Object parent, Object child )
89  	{
90  		SoapUITreeNode treeNode = ( SoapUITreeNode )parent;
91  		return treeNode.getIndexOfChild( child );
92  	}
93  
94  	public void addTreeModelListener( TreeModelListener l )
95  	{
96  		listeners.add( l );
97  	}
98  
99  	public void removeTreeModelListener( TreeModelListener l )
100 	{
101 		listeners.remove( l );
102 	}
103 
104 	public void mapModelItem( SoapUITreeNode soapUITreeNode )
105 	{
106 		modelItemMap.put( soapUITreeNode.getModelItem(), soapUITreeNode );
107 	}
108 
109 	public void unmapModelItem( ModelItem modelItem )
110 	{
111 		if( modelItemMap.containsKey( modelItem ) )
112 		{
113 			modelItemMap.remove( modelItem );
114 		}
115 		else
116 		{
117 			logger.error( "Failed to unmap model item [" + modelItem.getName() + "]" );
118 			Thread.dumpStack();
119 		}
120 	}
121 
122 	public void notifyNodesInserted( TreeModelEvent e )
123 	{
124 		Iterator<TreeModelListener> i = listeners.iterator();
125 		while( i.hasNext() )
126 		{
127 			i.next().treeNodesInserted( e );
128 		}
129 	}
130 
131 	public void notifyNodesRemoved( TreeModelEvent e )
132 	{
133 		Iterator<TreeModelListener> i = listeners.iterator();
134 		while( i.hasNext() )
135 		{
136 			i.next().treeNodesRemoved( e );
137 		}
138 	}
139 
140 	public void notifyStructureChanged( TreeModelEvent e )
141 	{
142 		Iterator<TreeModelListener> i = listeners.iterator();
143 		while( i.hasNext() )
144 		{
145 			i.next().treeStructureChanged( e );
146 		}
147 	}
148 
149 	public void notifyNodesChanged( TreeModelEvent e )
150 	{
151 		Iterator<TreeModelListener> i = listeners.iterator();
152 		while( i.hasNext() )
153 		{
154 			i.next().treeNodesChanged( e );
155 		}
156 	}
157 
158 	public TreePath getPath( SoapUITreeNode treeNode )
159 	{
160 		// SoapUITreeNode treeNode = modelItemMap.get( modelItem );
161 		// if( treeNode == null )
162 		// throw new RuntimeException( "Missing mapping for modelItem " +
163 		// modelItem.getName() );
164 
165 		List<Object> nodes = new ArrayList<Object>();
166 		if( treeNode != null )
167 		{
168 			nodes.add( treeNode );
169 
170 			treeNode = treeNode.getParentTreeNode();
171 			while( treeNode != null )
172 			{
173 				nodes.add( 0, treeNode );
174 				treeNode = treeNode.getParentTreeNode();
175 			}
176 		}
177 
178 		return nodes.isEmpty() ? null : new TreePath( nodes.toArray() );
179 	}
180 
181 	public void notifyNodeChanged( SoapUITreeNode treeNode )
182 	{
183 		SoapUITreeNode parent = treeNode.getParentTreeNode();
184 		if( parent == null )
185 		{
186 			notifyNodesChanged( new TreeModelEvent( this, new Object[] { treeNode } ) );
187 			return;
188 		}
189 
190 		int ix = parent.getIndexOfChild( treeNode );
191 
192 		if( ix == -1 )
193 		{
194 			if( ( !( treeNode instanceof PropertyTreeNode ) && !( treeNode instanceof PropertiesTreeNode ) )
195 					|| isShowProperties() )
196 				logger.error( "Changed node [" + treeNode + "] not found in parent [" + parent + "]" );
197 
198 			return;
199 		}
200 
201 		if( !( treeNode instanceof PropertyTreeNode ) || showProperties )
202 		{
203 			notifyNodesChanged( new TreeModelEvent( this, getPath( parent ), new int[] { ix }, new Object[] { parent
204 					.getChildNode( ix ) } ) );
205 		}
206 	}
207 
208 	public void notifyNodeInserted( SoapUITreeNode treeNode )
209 	{
210 		SoapUITreeNode parent = treeNode.getParentTreeNode();
211 		int ix = parent.getIndexOfChild( treeNode );
212 
213 		if( ix == -1 )
214 		{
215 			logger.error( "Inserted node [" + treeNode + "] not found in parent [" + parent + "]" );
216 			return;
217 		}
218 
219 		mapModelItem( treeNode );
220 
221 		if( !( treeNode instanceof PropertyTreeNode ) || showProperties )
222 		{
223 			notifyNodesInserted( new TreeModelEvent( this, getPath( parent ), new int[] { ix }, new Object[] { parent
224 					.getChildNode( ix ) } ) );
225 		}
226 	}
227 
228 	public void notifyNodeRemoved( SoapUITreeNode treeNode )
229 	{
230 		notifyNodeRemoved( treeNode, true );
231 	}
232 
233 	public void notifyNodeRemoved( SoapUITreeNode treeNode, boolean release )
234 	{
235 		SoapUITreeNode parent = treeNode.getParentTreeNode();
236 		int ix = parent.getIndexOfChild( treeNode );
237 
238 		if( ix == -1 )
239 		{
240 			logger.error( "Removed node [" + treeNode + "] not found in parent [" + parent + "]" );
241 			return;
242 		}
243 
244 		if( !( treeNode instanceof PropertyTreeNode ) || showProperties )
245 		{
246 			notifyNodesRemoved( new TreeModelEvent( this, getPath( parent ), new int[] { ix }, new Object[] { parent
247 					.getChildNode( ix ) } ) );
248 		}
249 
250 		if( release )
251 			treeNode.release();
252 	}
253 
254 	public SoapUITreeNode getTreeNode( ModelItem parentItem )
255 	{
256 		return modelItemMap.get( parentItem );
257 	}
258 
259 	public TreePath getPath( ModelItem modelItem )
260 	{
261 		return getPath( modelItemMap.get( modelItem ) );
262 	}
263 
264 	public void mapModelItems( List<? extends SoapUITreeNode> treeNodes )
265 	{
266 		Iterator<? extends SoapUITreeNode> iterator = treeNodes.iterator();
267 		while( iterator.hasNext() )
268 		{
269 			SoapUITreeNode item = iterator.next();
270 			mapModelItem( item );
271 		}
272 	}
273 
274 	public boolean isShowProperties()
275 	{
276 		return showProperties;
277 	}
278 
279 	public void setShowProperties( boolean showProperties )
280 	{
281 		if( this.showProperties != showProperties )
282 		{
283 			this.showProperties = showProperties;
284 			notifyStructureChanged( new TreeModelEvent( this, getPath( workspaceNode ) ) );
285 		}
286 	}
287 }