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