View Javadoc

    1   /*
    2    *  soapUI, copyright (C) 2004-2007 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 }