1
2
3
4
5
6
7
8
9
10
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.support.WorkspaceListenerAdapter;
40 import com.eviware.soapui.model.testsuite.LoadTest;
41 import com.eviware.soapui.model.testsuite.TestCase;
42 import com.eviware.soapui.model.testsuite.TestStep;
43 import com.eviware.soapui.model.testsuite.TestSuite;
44 import com.eviware.soapui.model.workspace.Workspace;
45 import com.eviware.soapui.model.workspace.WorkspaceListener;
46 import com.eviware.soapui.support.UISupport;
47 import com.eviware.soapui.support.action.SoapUIActionMapping;
48 import com.eviware.soapui.support.action.support.DefaultActionMapping;
49 import com.eviware.soapui.support.action.swing.SwingActionDelegate;
50 import com.eviware.soapui.support.types.StringToStringMap;
51 import com.eviware.soapui.ui.desktop.DesktopListener;
52 import com.eviware.soapui.ui.desktop.DesktopPanel;
53
54 /***
55 * Workspace/Deskopt Listener that updates the recent menus..
56 *
57 * @author ole.matzura
58 */
59
60 public class RecentItemsListener extends WorkspaceListenerAdapter implements WorkspaceListener, DesktopListener
61 {
62 private static final String RECENT_WORKSPACES_SETTING = "RecentWorkspaces";
63 private static final String RECENT_PROJECTS_SETTING = "RecentProjects";
64 private static final String EMPTYMARKER = "- empty -";
65 private static final String CLEAR_ITEMS = "Clear Items";
66 private JMenu recentProjectsMenu;
67 private JMenu recentWorkspacesMenu;
68 private JMenu recentEditorsMenu;
69 private boolean switchingWorkspace;
70
71 public RecentItemsListener( JMenu recentWorkspacesMenu2, JMenu recentProjectsMenu2, JMenu recentEditorsMenu2 )
72 {
73 recentWorkspacesMenu = recentWorkspacesMenu2;
74 recentProjectsMenu = recentProjectsMenu2;
75 recentEditorsMenu = recentEditorsMenu2;
76 recentEditorsMenu.add( EMPTYMARKER ).setEnabled( false );
77 recentEditorsMenu.getPopupMenu().addPopupMenuListener( new PopupMenuListener()
78 {
79
80 public void popupMenuCanceled( PopupMenuEvent e )
81 {
82 }
83
84 public void popupMenuWillBecomeInvisible( PopupMenuEvent e )
85 {
86 }
87
88 public void popupMenuWillBecomeVisible( PopupMenuEvent e )
89 {
90 int editorCount = 0;
91 for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
92 {
93 ShowEditorAction action = getShowEditorAction( recentEditorsMenu, c );
94 if( action == null )
95 continue;
96
97 editorCount++ ;
98
99 if( action.isReleased() )
100 {
101 recentEditorsMenu.remove( c );
102 c-- ;
103 }
104 else
105 {
106 try
107 {
108 action.update();
109 }
110 catch( Throwable e1 )
111 {
112 recentEditorsMenu.remove( c );
113 c-- ;
114 }
115 }
116 }
117
118
119 JMenuItem clearAllItem = null;
120 for( int i = 0; i < recentEditorsMenu.getItemCount(); ++i )
121 {
122 JMenuItem editorItem = recentEditorsMenu.getItem( i );
123 if( editorItem == null )
124 continue;
125
126 if( editorItem.getText().equals( CLEAR_ITEMS ) )
127 clearAllItem = editorItem;
128 }
129 if( clearAllItem == null )
130 {
131 clearAllItem = new JMenuItem( new ClearEditorsAction() );
132 recentEditorsMenu.addSeparator();
133 recentEditorsMenu.add( clearAllItem );
134 }
135
136 clearAllItem.setEnabled( editorCount > 0 );
137
138
139 if( editorCount == 0 && recentEditorsMenu.getItemCount() <= 2 )
140 recentEditorsMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
141
142 }
143 } );
144
145 updateRecentWorkspacesMenu();
146 updateRecentProjectsMenu();
147 }
148
149 @SuppressWarnings( "unchecked" )
150 private void updateRecentWorkspacesMenu()
151 {
152 String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
153 StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
154
155 recentWorkspacesMenu.removeAll();
156
157 if( history.size() > 0 )
158 {
159 for( Iterator<String> i = history.keySet().iterator(); i.hasNext(); )
160 {
161 String filePath = i.next();
162 DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
163 SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath );
164 String wsName = history.get( filePath );
165
166 if( SoapUI.getWorkspace().getPath().equals( filePath ) )
167 continue;
168
169 mapping.setName( wsName );
170 mapping.setDescription( "Switches to the [" + wsName + "] workspace" );
171
172 AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
173 recentWorkspacesMenu.add( new JMenuItem( delegate ) );
174 }
175 }
176 else
177 {
178 recentWorkspacesMenu.add( EMPTYMARKER ).setEnabled( false );
179 }
180
181 recentWorkspacesMenu.addSeparator();
182 recentWorkspacesMenu.add( new ClearWorkspacesAction() ).setEnabled( history.size() > 0 );
183 }
184
185 @SuppressWarnings( "unchecked" )
186 private void updateRecentProjectsMenu()
187 {
188 recentProjectsMenu.removeAll();
189
190 String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
191 StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
192
193 if( history.size() > 0 )
194 {
195 for( Iterator<String> i = history.keySet().iterator(); i.hasNext(); )
196 {
197 String filePath = i.next();
198 DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
199 ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath );
200 String wsName = history.get( filePath );
201 mapping.setName( wsName );
202 mapping.setDescription( "Switches to the [" + wsName + "] project" );
203
204 AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
205 recentProjectsMenu.add( new JMenuItem( delegate ) );
206 }
207 }
208 else
209 {
210 recentProjectsMenu.add( EMPTYMARKER ).setEnabled( false );
211 }
212
213 recentProjectsMenu.addSeparator();
214 recentProjectsMenu.add( new ClearProjectsAction() ).setEnabled( history.size() > 0 );
215 }
216
217 @SuppressWarnings( "unchecked" )
218 public void projectAdded( Project project )
219 {
220 if( switchingWorkspace )
221 return;
222
223 String filePath = ( ( WsdlProject )project ).getPath();
224 if( filePath == null )
225 return;
226
227 String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
228 if( recent != null )
229 {
230 StringToStringMap history = StringToStringMap.fromXml( recent );
231 history.remove( filePath );
232 SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, history.toXml() );
233 }
234
235 for( int c = 0; c < recentProjectsMenu.getItemCount() - 2; c++ )
236 {
237 JMenuItem item = recentProjectsMenu.getItem( c );
238 if( item == null )
239 continue;
240
241 Action action = item.getAction();
242 if( !( action instanceof SwingActionDelegate ) )
243 continue;
244
245 SwingActionDelegate actionDelegate = ( SwingActionDelegate )action;
246 if( actionDelegate == null )
247 continue;
248
249 SoapUIActionMapping mapping = actionDelegate.getMapping();
250 if( filePath.equals( mapping.getParam() ) )
251 {
252 recentProjectsMenu.remove( c );
253 break;
254 }
255 }
256
257 if( recentProjectsMenu.getItemCount() == 2 )
258 {
259 recentProjectsMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
260 recentProjectsMenu.getItem( recentProjectsMenu.getItemCount() - 1 ).setEnabled( false );
261 }
262 }
263
264 public void projectChanged( Project project )
265 {
266 }
267
268 @SuppressWarnings( "unchecked" )
269 public void projectRemoved( Project project )
270 {
271 if( switchingWorkspace )
272 return;
273
274 String filePath = ( ( WsdlProject )project ).getPath();
275
276 String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
277 StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
278 history.put( filePath, project.getName() );
279 SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, history.toXml() );
280
281 DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
282 ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath );
283 mapping.setName( project.getName() );
284 mapping.setDescription( "Switches to the [" + project.getName() + "] project" );
285
286 AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
287
288 recentProjectsMenu.add( new JMenuItem( delegate ), recentProjectsMenu.getItemCount() - 2 );
289
290 recentProjectsMenu.getItem( recentProjectsMenu.getItemCount() - 1 ).setEnabled( true );
291
292 if( isEmptyMarker( recentProjectsMenu.getItem( 0 ) ) )
293 recentProjectsMenu.remove( 0 );
294
295 removeProjectEditors( project );
296
297 }
298
299 private void removeProjectEditors( Project project )
300 {
301 for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
302 {
303 ShowEditorAction action = getShowEditorAction( recentEditorsMenu, c );
304 if( action == null )
305 continue;
306
307 if( action.isReleased() )
308 {
309 recentEditorsMenu.remove( c );
310 c-- ;
311 }
312 else
313 {
314 try
315 {
316 action.update();
317 if( dependsOnProject( action.getModelItem(), project ) )
318 {
319 recentEditorsMenu.remove( c );
320 c-- ;
321 }
322 }
323 catch( Throwable e1 )
324 {
325 recentEditorsMenu.remove( c );
326 c-- ;
327 }
328 }
329 }
330 }
331
332 private boolean dependsOnProject( ModelItem modelItem, Project project )
333 {
334 if( modelItem instanceof Interface )
335 {
336 return ( ( Interface )modelItem ).getProject() == project;
337 }
338 else if( modelItem instanceof Operation )
339 {
340 return ( ( Operation )modelItem ).getInterface().getProject() == project;
341 }
342 else if( modelItem instanceof Request )
343 {
344 return ( ( Request )modelItem ).getOperation().getInterface().getProject() == project;
345 }
346 else if( modelItem instanceof TestSuite )
347 {
348 return ( ( TestSuite )modelItem ).getProject() == project;
349 }
350 else if( modelItem instanceof TestCase )
351 {
352 return ( ( TestCase )modelItem ).getTestSuite().getProject() == project;
353 }
354 else if( modelItem instanceof TestStep )
355 {
356 return ( ( TestStep )modelItem ).getTestCase().getTestSuite().getProject() == project;
357 }
358 else if( modelItem instanceof LoadTest )
359 {
360 return ( ( LoadTest )modelItem ).getTestCase().getTestSuite().getProject() == project;
361 }
362 else if( modelItem instanceof MockService )
363 {
364 return ( ( MockService )modelItem ).getProject() == project;
365 }
366 else if( modelItem instanceof MockOperation )
367 {
368 return ( ( MockOperation )modelItem ).getMockService().getProject() == project;
369 }
370 else if( modelItem instanceof MockResponse )
371 {
372 return ( ( MockResponse )modelItem ).getMockOperation().getMockService().getProject() == project;
373 }
374
375 return false;
376 }
377
378 @SuppressWarnings( "unchecked" )
379 public void workspaceSwitched( Workspace workspace )
380 {
381 switchingWorkspace = false;
382
383 String filePath = workspace.getPath();
384
385 String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
386 if( recent != null )
387 {
388 StringToStringMap history = StringToStringMap.fromXml( recent );
389 history.remove( filePath );
390 SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, history.toXml() );
391 }
392
393 for( int c = 0; c < recentWorkspacesMenu.getItemCount(); c++ )
394 {
395 JMenuItem item = recentWorkspacesMenu.getItem( c );
396 if( item == null )
397 continue;
398
399 Action action = item.getAction();
400 if( !( action instanceof SwingActionDelegate ) )
401 continue;
402
403 SwingActionDelegate actionDelegate = ( SwingActionDelegate )action;
404 if( actionDelegate == null )
405 continue;
406
407 SoapUIActionMapping mapping = actionDelegate.getMapping();
408 if( filePath.equals( mapping.getParam() ) )
409 {
410 recentWorkspacesMenu.remove( c );
411 break;
412 }
413 }
414
415 if( recentWorkspacesMenu.getItemCount() == 2 )
416 recentWorkspacesMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
417 }
418
419 @SuppressWarnings( "unchecked" )
420 public void workspaceSwitching( Workspace workspace )
421 {
422 switchingWorkspace = true;
423 recentEditorsMenu.removeAll();
424 if( recentEditorsMenu.getItemCount() == 0 )
425 recentEditorsMenu.add( EMPTYMARKER ).setEnabled( false );
426
427 String filePath = workspace.getPath();
428 DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
429 SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath );
430 mapping.setName( workspace.getName() );
431 mapping.setDescription( "Switches to the [" + workspace.getName() + "] workspace" );
432
433 AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
434 recentWorkspacesMenu.add( new JMenuItem( delegate ), recentWorkspacesMenu.getItemCount() - 2 );
435
436 recentWorkspacesMenu.getItem( recentWorkspacesMenu.getItemCount() - 1 ).setEnabled( true );
437 System.out.println( recentWorkspacesMenu.getItem( recentWorkspacesMenu.getItemCount() - 1 ).getText() );
438
439 String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
440 StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
441 history.put( filePath, workspace.getName() );
442 SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, history.toXml() );
443
444 if( isEmptyMarker( recentWorkspacesMenu.getItem( 0 ) ) )
445 recentWorkspacesMenu.remove( 0 );
446
447 recentEditorsMenu.removeAll();
448 }
449
450 public void desktopPanelClosed( DesktopPanel desktopPanel )
451 {
452 ModelItem modelItem = desktopPanel.getModelItem();
453 if( modelItem == null || recentEditorsMenu.getItemCount() == 0 )
454 return;
455
456 if( isEmptyMarker( recentEditorsMenu.getItem( 0 ) ) )
457 recentEditorsMenu.remove( 0 );
458
459 recentEditorsMenu.add( new JMenuItem( new ShowEditorAction( modelItem ) ), 0 );
460 }
461
462 public void desktopPanelCreated( DesktopPanel desktopPanel )
463 {
464 for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
465 {
466 ShowEditorAction action = getShowEditorAction( recentEditorsMenu, c );
467 if( action == null )
468 continue;
469
470 if( action.isReleased() )
471 {
472 recentEditorsMenu.remove( c );
473 c-- ;
474 }
475 else if( action.getModelItem().equals( desktopPanel.getModelItem() ) )
476 {
477 recentEditorsMenu.remove( c );
478 break;
479 }
480 }
481
482 if( recentEditorsMenu.getItemCount() == 2 )
483 recentEditorsMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
484 }
485
486 public void desktopPanelSelected( DesktopPanel desktopPanel )
487 {
488 }
489
490 private static class ShowEditorAction extends AbstractAction
491 {
492 private Reference<ModelItem> ref;
493
494 public ShowEditorAction( ModelItem modelItem )
495 {
496 super( modelItem.getName() );
497
498 putValue( Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]" );
499 ref = new WeakReference<ModelItem>( modelItem );
500 }
501
502 public ModelItem getModelItem()
503 {
504 return ref.get();
505 }
506
507 public void update()
508 {
509 ModelItem modelItem = ref.get();
510 if( modelItem == null )
511 return;
512
513 putValue( Action.NAME, modelItem.getName() );
514 putValue( Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]" );
515 }
516
517 public boolean isReleased()
518 {
519 return ref.get() == null;
520 }
521
522 public void actionPerformed( ActionEvent e )
523 {
524 ModelItem modelItem = ref.get();
525 if( modelItem != null )
526 UISupport.showDesktopPanel( modelItem );
527 else
528 UISupport.showErrorMessage( "Item [" + getValue( Action.NAME ) + "] is no longer available" );
529 }
530 }
531
532
533
534 /***
535 * Confirms that the item of index i in menu is a ShowEditorAction, and
536 * extracts the ShowEditorAction.
537 *
538 * @param menu
539 * The menu to get the JMenuItem, containing the action from.
540 * @param i
541 * The index where the JMenuItem is located in menu.
542 * @return The ShowEditorAction if confirmed. Otherwise null.
543 */
544 private ShowEditorAction getShowEditorAction( JMenu menu, int i )
545 {
546 JMenuItem menuItem = recentEditorsMenu.getItem( i );
547 if( menuItem == null )
548 return null;
549
550 Action unknownAction = menuItem.getAction();
551
552 if( unknownAction == null || !( unknownAction instanceof ShowEditorAction ) )
553 return null;
554
555 return ( ShowEditorAction )unknownAction;
556 }
557
558 /***
559 * Checks whether a JMenuItem is an Empty marker (marking an empty list).
560 *
561 * @param item
562 * The item to check.
563 * @return True if item is an Empty marker. False otherwise (including if
564 * item is null).
565 */
566 private boolean isEmptyMarker( JMenuItem item )
567 {
568 if( item == null )
569 return false;
570 if( item.getText().equals( EMPTYMARKER ) )
571 return true;
572 return false;
573 }
574
575
576
577
578
579
580 @SuppressWarnings( "serial" )
581 private class ClearProjectsAction extends AbstractAction
582 {
583 public ClearProjectsAction()
584 {
585 super( CLEAR_ITEMS );
586 putValue( Action.SHORT_DESCRIPTION, "Clear all recent projects" );
587 }
588
589 public void actionPerformed( ActionEvent e )
590 {
591 if( !UISupport.confirm( "Remove all Projects from this menu?", "Question" ) )
592 return;
593
594 StringToStringMap emptyMap = new StringToStringMap();
595
596 SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, emptyMap.toXml() );
597 updateRecentProjectsMenu();
598
599 }
600 }
601
602 @SuppressWarnings( "serial" )
603 private class ClearWorkspacesAction extends AbstractAction
604 {
605 public ClearWorkspacesAction()
606 {
607 super( CLEAR_ITEMS );
608 putValue( Action.SHORT_DESCRIPTION, "Clear all recent workspaces" );
609 }
610
611 public void actionPerformed( ActionEvent e )
612 {
613 if( !UISupport.confirm( "Remove all Workspaces from this menu?", "Question" ) )
614 return;
615
616 StringToStringMap emptyMap = new StringToStringMap();
617
618 SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, emptyMap.toXml() );
619 updateRecentWorkspacesMenu();
620
621 }
622 }
623
624 @SuppressWarnings( "serial" )
625 private class ClearEditorsAction extends AbstractAction
626 {
627 public ClearEditorsAction()
628 {
629 super( CLEAR_ITEMS );
630 putValue( Action.SHORT_DESCRIPTION, "Clear all recent Editors" );
631 }
632
633 public void actionPerformed( ActionEvent e )
634 {
635 if( !UISupport.confirm( "Remove all Editors from this menu?", "Question" ) )
636 return;
637
638 recentEditorsMenu.removeAll();
639 recentEditorsMenu.add( EMPTYMARKER ).setEnabled( false );
640 recentEditorsMenu.addSeparator();
641 recentEditorsMenu.add( new ClearEditorsAction() );
642 }
643 }
644
645 }