View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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;
14  
15  import java.awt.event.ActionEvent;
16  import java.lang.ref.Reference;
17  import java.lang.ref.WeakReference;
18  import java.util.Iterator;
19  
20  import javax.swing.AbstractAction;
21  import javax.swing.Action;
22  import javax.swing.JMenu;
23  import javax.swing.JMenuItem;
24  import javax.swing.event.PopupMenuEvent;
25  import javax.swing.event.PopupMenuListener;
26  
27  import com.eviware.soapui.impl.WorkspaceImpl;
28  import com.eviware.soapui.impl.actions.ImportWsdlProjectAction;
29  import com.eviware.soapui.impl.actions.SwitchWorkspaceAction;
30  import com.eviware.soapui.impl.wsdl.WsdlProject;
31  import com.eviware.soapui.model.ModelItem;
32  import com.eviware.soapui.model.iface.Interface;
33  import com.eviware.soapui.model.iface.Operation;
34  import com.eviware.soapui.model.iface.Request;
35  import com.eviware.soapui.model.mock.MockOperation;
36  import com.eviware.soapui.model.mock.MockResponse;
37  import com.eviware.soapui.model.mock.MockService;
38  import com.eviware.soapui.model.project.Project;
39  import com.eviware.soapui.model.testsuite.LoadTest;
40  import com.eviware.soapui.model.testsuite.TestCase;
41  import com.eviware.soapui.model.testsuite.TestStep;
42  import com.eviware.soapui.model.testsuite.TestSuite;
43  import com.eviware.soapui.model.workspace.Workspace;
44  import com.eviware.soapui.model.workspace.WorkspaceListener;
45  import com.eviware.soapui.support.UISupport;
46  import com.eviware.soapui.support.action.SoapUIActionMapping;
47  import com.eviware.soapui.support.action.support.DefaultActionMapping;
48  import com.eviware.soapui.support.action.swing.SwingActionDelegate;
49  import com.eviware.soapui.support.types.StringToStringMap;
50  import com.eviware.soapui.ui.desktop.DesktopListener;
51  import com.eviware.soapui.ui.desktop.DesktopPanel;
52  
53  /***
54   * Workspace/Deskopt Listener that updates the recent menus..
55   * 
56   * @author ole.matzura
57   */
58  
59  public class RecentItemsListener implements WorkspaceListener, DesktopListener
60  {
61  	private static final String RECENT_WORKSPACES_SETTING = "RecentWorkspaces";
62  	private static final String RECENT_PROJECTS_SETTING = "RecentProjects";
63  	private JMenu recentProjectsMenu;
64  	private JMenu recentWorkspacesMenu;
65  	private JMenu recentEditorsMenu;
66  	private boolean switchingWorkspace;
67  	
68  	public RecentItemsListener( JMenu recentWorkspacesMenu2, JMenu recentProjectsMenu2, JMenu recentEditorsMenu2 )
69  	{
70  		recentWorkspacesMenu = recentWorkspacesMenu2;
71  		recentProjectsMenu = recentProjectsMenu2;
72  		recentEditorsMenu = recentEditorsMenu2;
73  		recentEditorsMenu.add( "- empty -" ).setEnabled( false );
74  		recentEditorsMenu.getPopupMenu().addPopupMenuListener( new PopupMenuListener() {
75  
76  			public void popupMenuCanceled( PopupMenuEvent e )
77  			{
78  			}
79  
80  			public void popupMenuWillBecomeInvisible( PopupMenuEvent e )
81  			{
82  			}
83  
84  			public void popupMenuWillBecomeVisible( PopupMenuEvent e )
85  			{
86  				for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
87  				{
88  					ShowEditorAction action = ( ShowEditorAction ) recentEditorsMenu.getItem( c ).getAction();
89  					if( action == null )
90  						continue;
91  					
92  					if( action.isReleased() )
93  					{
94  						recentEditorsMenu.remove( c );
95  						c--;
96  					}
97  					else
98  					{
99  						try
100 						{
101 							action.update();
102 						}
103 						catch( Throwable e1 )
104 						{
105 							recentEditorsMenu.remove( c );
106 							c--;
107 						}
108 					}
109 				}
110 				
111 				if( recentEditorsMenu.getItemCount() == 0 )
112 					recentEditorsMenu.add( "- empty -" ).setEnabled( false );
113 				
114 			}} );
115 		
116 		updateRecentWorkspacesMenu();
117 		updateRecentProjectsMenu();
118 	}
119 
120 	private void updateRecentWorkspacesMenu()
121 	{
122 		String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
123 		StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
124 		
125 		recentWorkspacesMenu.removeAll();
126 		
127 		if( history.size() > 0 )
128 		{
129 			for( Iterator<String> i = history.keySet().iterator(); i.hasNext(); )
130 			{
131 				String filePath = i.next();
132 				DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath );
133 				String wsName = history.get( filePath );
134 				
135 				if( SoapUI.getWorkspace().getPath().equals( filePath ))
136 					continue;
137 				
138 				mapping.setName( wsName);
139 				mapping.setDescription( "Switches to the [" + wsName + "] workspace" );
140 				
141 				AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
142 				recentWorkspacesMenu.add( new JMenuItem( delegate ));
143 			}
144 		}
145 		else
146 		{
147 			recentWorkspacesMenu.add( "- empty -" ).setEnabled( false );
148 		}
149 	}
150 	
151 	private void updateRecentProjectsMenu()
152 	{
153 		recentProjectsMenu.removeAll();
154 		
155 		String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
156 		StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
157 		
158 		if( history.size() > 0 )
159 		{
160 			for( Iterator<String> i = history.keySet().iterator(); i.hasNext(); )
161 			{
162 				String filePath = i.next();
163 				DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath );
164 				String wsName = history.get( filePath );
165 				mapping.setName( wsName);
166 				mapping.setDescription( "Switches to the [" + wsName + "] project" );
167 				
168 				AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
169 				recentProjectsMenu.add( new JMenuItem( delegate ));
170 			}
171 		}
172 		else
173 		{
174 			recentProjectsMenu.add( "- empty -" ).setEnabled( false );
175 		}
176 	}
177 	
178 	public void projectAdded( Project project )
179 	{
180 		if( switchingWorkspace )
181 			return;
182 		
183 		String filePath = ((WsdlProject)project).getPath();
184 		if( filePath == null )
185 			return;
186 		
187 		String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
188 		if( recent != null )
189 		{
190 			StringToStringMap history = StringToStringMap.fromXml( recent );
191 			history.remove( filePath );
192 			SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, history.toXml() );
193 		}
194 		
195 		for( int c = 0; c < recentProjectsMenu.getItemCount(); c++ )
196 		{
197 			SwingActionDelegate action = ( SwingActionDelegate ) recentProjectsMenu.getItem( c ).getAction();
198 			if( action == null )
199 				continue;
200 			
201 			SoapUIActionMapping mapping = action.getMapping();
202 			if( filePath.equals( mapping.getParam()) )
203 			{
204 				recentProjectsMenu.remove( c );
205 				break;
206 			}
207 		}
208 		
209 		if( recentProjectsMenu.getItemCount() == 0 )
210 			recentProjectsMenu.add( "- empty -" ).setEnabled( false );
211 	}
212 
213 	public void projectChanged( Project project )
214 	{
215 	}
216 
217 	public void projectRemoved( Project project )
218 	{
219 		if( switchingWorkspace )
220 			return;
221 		
222 		String filePath = ((WsdlProject)project).getPath();
223 		
224 		String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
225 		StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
226 		history.put( filePath, project.getName() );
227 		SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, history.toXml() );
228 		
229 		DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath );
230 		mapping.setName( project.getName() );
231 		mapping.setDescription( "Switches to the [" + project.getName() + "] project" );
232 		
233 		AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
234 		recentProjectsMenu.add( new JMenuItem( delegate ));
235 		
236 		SwingActionDelegate action = ( SwingActionDelegate ) recentProjectsMenu.getItem( 0 ).getAction();
237 		if( action == null )
238 			recentProjectsMenu.remove( 0 );
239 		
240 		removeProjectEditors( project );
241 	}
242 
243 	private void removeProjectEditors( Project project )
244 	{
245 		for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
246 		{
247 			ShowEditorAction action = ( ShowEditorAction ) recentEditorsMenu.getItem( c ).getAction();
248 			if( action == null )
249 				continue;
250 			
251 			if( action.isReleased() )
252 			{
253 				recentEditorsMenu.remove( c );
254 				c--;
255 			}
256 			else
257 			{
258 				try
259 				{
260 					action.update();
261 					if( dependsOnProject( action.getModelItem(), project ))
262 					{
263 						recentEditorsMenu.remove( c );
264 						c--;
265 					}
266 				}
267 				catch( Throwable e1 )
268 				{
269 					recentEditorsMenu.remove( c );
270 					c--;
271 				}
272 			}
273 		}		
274 	}
275 
276 	private boolean dependsOnProject( ModelItem modelItem, Project project )
277 	{
278 		if( modelItem instanceof Interface )
279 		{
280 			return ((Interface)modelItem).getProject() == project;
281 		}
282 		else if( modelItem instanceof Operation )
283 		{
284 			return ((Operation)modelItem).getInterface().getProject() == project;
285 		}
286 		else if( modelItem instanceof Request )
287 		{
288 			return ((Request)modelItem).getOperation().getInterface().getProject() == project;
289 		}
290 		else if( modelItem instanceof TestSuite )
291 		{
292 			return ((TestSuite)modelItem).getProject() == project;
293 		}
294 		else if( modelItem instanceof TestCase )
295 		{
296 			return ((TestCase)modelItem).getTestSuite().getProject() == project;
297 		}
298 		else if( modelItem instanceof TestStep )
299 		{
300 			return ((TestStep)modelItem).getTestCase().getTestSuite().getProject() == project;
301 		}
302 		else if( modelItem instanceof LoadTest )
303 		{
304 			return ((LoadTest)modelItem).getTestCase().getTestSuite().getProject() == project;
305 		}
306 		else if( modelItem instanceof MockService )
307 		{
308 			return ((MockService)modelItem).getProject() == project;
309 		}
310 		else if( modelItem instanceof MockOperation )
311 		{
312 			return ((MockOperation)modelItem).getMockService().getProject() == project;
313 		}
314 		else if( modelItem instanceof MockResponse )
315 		{
316 			return ((MockResponse)modelItem).getMockOperation().getMockService().getProject() == project;
317 		}
318 		
319 		return false;
320 	}
321 
322 	public void workspaceSwitched( Workspace workspace )
323 	{
324 		switchingWorkspace = false;
325 		
326 		String filePath = workspace.getPath();
327 		
328 		String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
329 		if( recent != null )
330 		{
331 			StringToStringMap history = StringToStringMap.fromXml( recent );
332 			history.remove( filePath );
333 			SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, history.toXml() );
334 		}
335 		
336 		for( int c = 0; c < recentWorkspacesMenu.getItemCount(); c++ )
337 		{
338 			SwingActionDelegate action = ( SwingActionDelegate ) recentWorkspacesMenu.getItem( c ).getAction();
339 			if( action == null )
340 				continue;
341 			
342 			SoapUIActionMapping mapping = action.getMapping();
343 			if( filePath.equals( mapping.getParam()) )
344 			{
345 				recentWorkspacesMenu.remove( c );
346 				break;
347 			}
348 		}
349 		
350 		if( recentWorkspacesMenu.getItemCount() == 0 )
351 			recentWorkspacesMenu.add( "- empty -" ).setEnabled( false );
352 	}
353 
354 	public void workspaceSwitching( Workspace workspace )
355 	{
356 		switchingWorkspace = true;
357 		recentEditorsMenu.removeAll();
358 		if( recentEditorsMenu.getItemCount() == 0 )
359 			recentEditorsMenu.add( "- empty -" ).setEnabled( false );
360 		
361 		String filePath = workspace.getPath();
362 		DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>( SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath );
363 		mapping.setName( workspace.getName() );
364 		mapping.setDescription( "Switches to the [" + workspace.getName() + "] workspace" );
365 		
366 		AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
367 		recentWorkspacesMenu.add( new JMenuItem( delegate ));
368 		
369 		String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
370 		StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
371 		history.put( filePath, workspace.getName() );
372 		SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, history.toXml() );
373 		
374 		SwingActionDelegate action = ( SwingActionDelegate ) recentWorkspacesMenu.getItem( 0 ).getAction();
375 		if( action == null )
376 			recentWorkspacesMenu.remove( 0 );
377 		
378 		recentEditorsMenu.removeAll();
379 	}
380 
381 	public void desktopPanelClosed( DesktopPanel desktopPanel )
382 	{
383 		ModelItem modelItem = desktopPanel.getModelItem();
384 		if( modelItem == null )
385 			return;
386 		
387 		recentEditorsMenu.add( new JMenuItem( new ShowEditorAction( modelItem) ));
388 		
389 		ShowEditorAction action = ( ShowEditorAction ) recentEditorsMenu.getItem( 0 ).getAction();
390 		if( action == null )
391 			recentEditorsMenu.remove( 0 );
392 	}
393 
394 	public void desktopPanelCreated( DesktopPanel desktopPanel )
395 	{
396 		for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
397 		{
398 			ShowEditorAction action = ( ShowEditorAction ) recentEditorsMenu.getItem( c ).getAction();
399 			if( action == null )
400 				continue;
401 			
402 			if( action.isReleased() )
403 			{
404 				recentEditorsMenu.remove( c );
405 				c--;
406 			}
407 			else if( action.getModelItem().equals( desktopPanel.getModelItem() ) )
408 			{
409 				recentEditorsMenu.remove( c );
410 				break;
411 			}
412 		}
413 		
414 		if( recentEditorsMenu.getItemCount() == 0 )
415 			recentEditorsMenu.add( "- empty -" ).setEnabled( false );
416 	}
417 
418 	public void desktopPanelSelected( DesktopPanel desktopPanel )
419 	{
420 	}
421 	
422 	private static class ShowEditorAction extends AbstractAction
423 	{
424 		private Reference<ModelItem> ref;
425 		
426 		public ShowEditorAction( ModelItem modelItem )
427 		{
428 			super( modelItem.getName() );
429 			
430 			putValue( Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]" );
431 			ref = new WeakReference<ModelItem>( modelItem );
432 		}
433 
434 		public ModelItem getModelItem()
435 		{
436 			return ref.get();
437 		}
438 
439 		public void update() 
440 		{
441 			ModelItem modelItem = ref.get();
442 			if( modelItem == null )
443 				return;
444 			
445 			putValue( Action.NAME, modelItem.getName() );
446 			putValue( Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]" );
447 		}
448 
449 		public boolean isReleased()
450 		{
451 			return ref.get() == null;
452 		}
453 
454 		public void actionPerformed( ActionEvent e )
455 		{
456 			ModelItem modelItem = ref.get();
457 			if( modelItem != null )
458 				UISupport.showDesktopPanel( modelItem  );
459 			else
460 				UISupport.showErrorMessage( "Item [" + getValue( Action.NAME )+ "] is no longer available" );
461 		}
462 	}
463 }