/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui;
import java.awt.event.ActionEvent;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import com.eviware.soapui.impl.WorkspaceImpl;
import com.eviware.soapui.impl.actions.ImportWsdlProjectAction;
import com.eviware.soapui.impl.actions.SwitchWorkspaceAction;
import com.eviware.soapui.impl.wsdl.WsdlProject;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.iface.Interface;
import com.eviware.soapui.model.iface.Operation;
import com.eviware.soapui.model.iface.Request;
import com.eviware.soapui.model.mock.MockOperation;
import com.eviware.soapui.model.mock.MockResponse;
import com.eviware.soapui.model.mock.MockService;
import com.eviware.soapui.model.project.Project;
import com.eviware.soapui.model.support.WorkspaceListenerAdapter;
import com.eviware.soapui.model.testsuite.LoadTest;
import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.model.testsuite.TestSuite;
import com.eviware.soapui.model.workspace.Workspace;
import com.eviware.soapui.model.workspace.WorkspaceListener;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.action.SoapUIActionMapping;
import com.eviware.soapui.support.action.support.DefaultActionMapping;
import com.eviware.soapui.support.action.swing.SwingActionDelegate;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.ui.desktop.DesktopListener;
import com.eviware.soapui.ui.desktop.DesktopPanel;
/**
* Workspace/Deskopt Listener that updates the recent menus..
*
* @author ole.matzura
*/
public class RecentItemsListener extends WorkspaceListenerAdapter implements WorkspaceListener, DesktopListener
{
private static final String RECENT_WORKSPACES_SETTING = "RecentWorkspaces";
private static final String RECENT_PROJECTS_SETTING = "RecentProjects";
private static final String EMPTYMARKER = "- empty -";
private static final String CLEAR_ITEMS = "Clear Items";
private JMenu recentProjectsMenu;
private JMenu recentWorkspacesMenu;
private JMenu recentEditorsMenu;
private boolean switchingWorkspace;
public RecentItemsListener( JMenu recentWorkspacesMenu2, JMenu recentProjectsMenu2, JMenu recentEditorsMenu2 )
{
recentWorkspacesMenu = recentWorkspacesMenu2;
recentProjectsMenu = recentProjectsMenu2;
recentEditorsMenu = recentEditorsMenu2;
recentEditorsMenu.add( EMPTYMARKER ).setEnabled( false );
recentEditorsMenu.getPopupMenu().addPopupMenuListener( new PopupMenuListener()
{
public void popupMenuCanceled( PopupMenuEvent e )
{
}
public void popupMenuWillBecomeInvisible( PopupMenuEvent e )
{
}
public void popupMenuWillBecomeVisible( PopupMenuEvent e )
{
int editorCount = 0;
for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
{
ShowEditorAction action = getShowEditorAction( recentEditorsMenu, c );
if( action == null )
continue;
editorCount++ ;
if( action.isReleased() )
{
recentEditorsMenu.remove( c );
c-- ;
}
else
{
try
{
action.update();
}
catch( Throwable e1 )
{
recentEditorsMenu.remove( c );
c-- ;
}
}
}
// Look for a Clear Items JMenuItem, and create it if not existing
JMenuItem clearAllItem = null;
for( int i = 0; i < recentEditorsMenu.getItemCount(); ++i )
{
JMenuItem editorItem = recentEditorsMenu.getItem( i );
if( editorItem == null )
continue;
if( editorItem.getText().equals( CLEAR_ITEMS ) )
clearAllItem = editorItem;
}
if( clearAllItem == null )
{
clearAllItem = new JMenuItem( new ClearEditorsAction() );
recentEditorsMenu.addSeparator();
recentEditorsMenu.add( clearAllItem );
}
clearAllItem.setEnabled( editorCount > 0 );
// Create Empty Marker if needed.
if( editorCount == 0 && recentEditorsMenu.getItemCount() <= 2 )
recentEditorsMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
}
} );
updateRecentWorkspacesMenu();
updateRecentProjectsMenu();
}
@SuppressWarnings( "unchecked" )
private void updateRecentWorkspacesMenu()
{
String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
recentWorkspacesMenu.removeAll();
if( history.size() > 0 )
{
for( Iterator<String> i = history.keySet().iterator(); i.hasNext(); )
{
String filePath = i.next();
DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath );
String wsName = history.get( filePath );
if( SoapUI.getWorkspace().getPath().equals( filePath ) )
continue;
mapping.setName( wsName );
mapping.setDescription( "Switches to the [" + wsName + "] workspace" );
AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
recentWorkspacesMenu.add( new JMenuItem( delegate ) );
}
}
else
{
recentWorkspacesMenu.add( EMPTYMARKER ).setEnabled( false );
}
recentWorkspacesMenu.addSeparator();
recentWorkspacesMenu.add( new ClearWorkspacesAction() ).setEnabled( history.size() > 0 );
}
@SuppressWarnings( "unchecked" )
private void updateRecentProjectsMenu()
{
recentProjectsMenu.removeAll();
String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
if( history.size() > 0 )
{
for( Iterator<String> i = history.keySet().iterator(); i.hasNext(); )
{
String filePath = i.next();
DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath );
String wsName = history.get( filePath );
mapping.setName( wsName );
mapping.setDescription( "Switches to the [" + wsName + "] project" );
AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
recentProjectsMenu.add( new JMenuItem( delegate ) );
}
}
else
{
recentProjectsMenu.add( EMPTYMARKER ).setEnabled( false );
}
recentProjectsMenu.addSeparator();
recentProjectsMenu.add( new ClearProjectsAction() ).setEnabled( history.size() > 0 );
}
@SuppressWarnings( "unchecked" )
public void projectAdded( Project project )
{
if( switchingWorkspace )
return;
String filePath = ( ( WsdlProject )project ).getPath();
if( filePath == null )
return;
String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
if( recent != null )
{
StringToStringMap history = StringToStringMap.fromXml( recent );
history.remove( filePath );
SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, history.toXml() );
}
for( int c = 0; c < recentProjectsMenu.getItemCount() - 2; c++ )
{
JMenuItem item = recentProjectsMenu.getItem( c );
if( item == null )
continue;
Action action = item.getAction();
if( !( action instanceof SwingActionDelegate ) )
continue;
SwingActionDelegate actionDelegate = ( SwingActionDelegate )action;
if( actionDelegate == null )
continue;
SoapUIActionMapping mapping = actionDelegate.getMapping();
if( filePath.equals( mapping.getParam() ) )
{
recentProjectsMenu.remove( c );
break;
}
}
if( recentProjectsMenu.getItemCount() == 2 )
{
recentProjectsMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
recentProjectsMenu.getItem( recentProjectsMenu.getItemCount() - 1 ).setEnabled( false );
}
}
public void projectChanged( Project project )
{
}
@SuppressWarnings( "unchecked" )
public void projectRemoved( Project project )
{
if( switchingWorkspace )
return;
String filePath = ( ( WsdlProject )project ).getPath();
String recent = SoapUI.getSettings().getString( RECENT_PROJECTS_SETTING, null );
StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
history.put( filePath, project.getName() );
SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, history.toXml() );
DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
ImportWsdlProjectAction.SOAPUI_ACTION_ID, null, null, false, filePath );
mapping.setName( project.getName() );
mapping.setDescription( "Switches to the [" + project.getName() + "] project" );
AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
recentProjectsMenu.add( new JMenuItem( delegate ), recentProjectsMenu.getItemCount() - 2 );
recentProjectsMenu.getItem( recentProjectsMenu.getItemCount() - 1 ).setEnabled( true );
if( isEmptyMarker( recentProjectsMenu.getItem( 0 ) ) )
recentProjectsMenu.remove( 0 );
removeProjectEditors( project );
}
private void removeProjectEditors( Project project )
{
for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
{
ShowEditorAction action = getShowEditorAction( recentEditorsMenu, c );
if( action == null )
continue;
if( action.isReleased() )
{
recentEditorsMenu.remove( c );
c-- ;
}
else
{
try
{
action.update();
if( dependsOnProject( action.getModelItem(), project ) )
{
recentEditorsMenu.remove( c );
c-- ;
}
}
catch( Throwable e1 )
{
recentEditorsMenu.remove( c );
c-- ;
}
}
}
}
private boolean dependsOnProject( ModelItem modelItem, Project project )
{
if( modelItem instanceof Interface )
{
return ( ( Interface )modelItem ).getProject() == project;
}
else if( modelItem instanceof Operation )
{
return ( ( Operation )modelItem ).getInterface().getProject() == project;
}
else if( modelItem instanceof Request )
{
return ( ( Request )modelItem ).getOperation().getInterface().getProject() == project;
}
else if( modelItem instanceof TestSuite )
{
return ( ( TestSuite )modelItem ).getProject() == project;
}
else if( modelItem instanceof TestCase )
{
return ( ( TestCase )modelItem ).getTestSuite().getProject() == project;
}
else if( modelItem instanceof TestStep )
{
return ( ( TestStep )modelItem ).getTestCase().getTestSuite().getProject() == project;
}
else if( modelItem instanceof LoadTest )
{
return ( ( LoadTest )modelItem ).getTestCase().getTestSuite().getProject() == project;
}
else if( modelItem instanceof MockService )
{
return ( ( MockService )modelItem ).getProject() == project;
}
else if( modelItem instanceof MockOperation )
{
return ( ( MockOperation )modelItem ).getMockService().getProject() == project;
}
else if( modelItem instanceof MockResponse )
{
return ( ( MockResponse )modelItem ).getMockOperation().getMockService().getProject() == project;
}
return false;
}
@SuppressWarnings( "unchecked" )
public void workspaceSwitched( Workspace workspace )
{
switchingWorkspace = false;
String filePath = workspace.getPath();
String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
if( recent != null )
{
StringToStringMap history = StringToStringMap.fromXml( recent );
history.remove( filePath );
SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, history.toXml() );
}
for( int c = 0; c < recentWorkspacesMenu.getItemCount(); c++ )
{
JMenuItem item = recentWorkspacesMenu.getItem( c );
if( item == null )
continue;
Action action = item.getAction();
if( !( action instanceof SwingActionDelegate ) )
continue;
SwingActionDelegate actionDelegate = ( SwingActionDelegate )action;
if( actionDelegate == null )
continue;
SoapUIActionMapping mapping = actionDelegate.getMapping();
if( filePath.equals( mapping.getParam() ) )
{
recentWorkspacesMenu.remove( c );
break;
}
}
if( recentWorkspacesMenu.getItemCount() == 2 )
recentWorkspacesMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
}
@SuppressWarnings( "unchecked" )
public void workspaceSwitching( Workspace workspace )
{
switchingWorkspace = true;
recentEditorsMenu.removeAll();
if( recentEditorsMenu.getItemCount() == 0 )
recentEditorsMenu.add( EMPTYMARKER ).setEnabled( false );
String filePath = workspace.getPath();
DefaultActionMapping<WorkspaceImpl> mapping = new DefaultActionMapping<WorkspaceImpl>(
SwitchWorkspaceAction.SOAPUI_ACTION_ID, null, null, false, filePath );
mapping.setName( workspace.getName() );
mapping.setDescription( "Switches to the [" + workspace.getName() + "] workspace" );
AbstractAction delegate = new SwingActionDelegate( mapping, SoapUI.getWorkspace() );
recentWorkspacesMenu.add( new JMenuItem( delegate ), recentWorkspacesMenu.getItemCount() - 2 );
recentWorkspacesMenu.getItem( recentWorkspacesMenu.getItemCount() - 1 ).setEnabled( true );
System.out.println( recentWorkspacesMenu.getItem( recentWorkspacesMenu.getItemCount() - 1 ).getText() );
String recent = SoapUI.getSettings().getString( RECENT_WORKSPACES_SETTING, null );
StringToStringMap history = recent == null ? new StringToStringMap() : StringToStringMap.fromXml( recent );
history.put( filePath, workspace.getName() );
SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, history.toXml() );
if( isEmptyMarker( recentWorkspacesMenu.getItem( 0 ) ) )
recentWorkspacesMenu.remove( 0 );
recentEditorsMenu.removeAll();
}
public void desktopPanelClosed( DesktopPanel desktopPanel )
{
ModelItem modelItem = desktopPanel.getModelItem();
if( modelItem == null || recentEditorsMenu.getItemCount() == 0 )
return;
if( isEmptyMarker( recentEditorsMenu.getItem( 0 ) ) )
recentEditorsMenu.remove( 0 );
recentEditorsMenu.add( new JMenuItem( new ShowEditorAction( modelItem ) ), 0 );
}
public void desktopPanelCreated( DesktopPanel desktopPanel )
{
for( int c = 0; c < recentEditorsMenu.getItemCount(); c++ )
{
ShowEditorAction action = getShowEditorAction( recentEditorsMenu, c );
if( action == null )
continue;
if( action.isReleased() )
{
recentEditorsMenu.remove( c );
c-- ;
}
else if( action.getModelItem().equals( desktopPanel.getModelItem() ) )
{
recentEditorsMenu.remove( c );
break;
}
}
if( recentEditorsMenu.getItemCount() == 2 )
recentEditorsMenu.add( new JMenuItem( EMPTYMARKER ), 0 ).setEnabled( false );
}
public void desktopPanelSelected( DesktopPanel desktopPanel )
{
}
private static class ShowEditorAction extends AbstractAction
{
private Reference<ModelItem> ref;
public ShowEditorAction( ModelItem modelItem )
{
super( modelItem.getName() );
putValue( Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]" );
ref = new WeakReference<ModelItem>( modelItem );
}
public ModelItem getModelItem()
{
return ref.get();
}
public void update()
{
ModelItem modelItem = ref.get();
if( modelItem == null )
return;
putValue( Action.NAME, modelItem.getName() );
putValue( Action.SHORT_DESCRIPTION, "Reopen editor for [" + modelItem.getName() + "]" );
}
public boolean isReleased()
{
return ref.get() == null;
}
public void actionPerformed( ActionEvent e )
{
ModelItem modelItem = ref.get();
if( modelItem != null )
UISupport.showDesktopPanel( modelItem );
else
UISupport.showErrorMessage( "Item [" + getValue( Action.NAME ) + "] is no longer available" );
}
}
/* Helper methods */
/**
* Confirms that the item of index i in menu is a ShowEditorAction, and
* extracts the ShowEditorAction.
*
* @param menu
* The menu to get the JMenuItem, containing the action from.
* @param i
* The index where the JMenuItem is located in menu.
* @return The ShowEditorAction if confirmed. Otherwise null.
*/
private ShowEditorAction getShowEditorAction( JMenu menu, int i )
{
JMenuItem menuItem = recentEditorsMenu.getItem( i );
if( menuItem == null )
return null;
Action unknownAction = menuItem.getAction();
if( unknownAction == null || !( unknownAction instanceof ShowEditorAction ) )
return null;
return ( ShowEditorAction )unknownAction;
}
/**
* Checks whether a JMenuItem is an Empty marker (marking an empty list).
*
* @param item
* The item to check.
* @return True if item is an Empty marker. False otherwise (including if
* item is null).
*/
private boolean isEmptyMarker( JMenuItem item )
{
if( item == null )
return false;
if( item.getText().equals( EMPTYMARKER ) )
return true;
return false;
}
/*
* Action classes for clearing all items in the Recent
* Editors/Projects/Workspaces submenu
*/
@SuppressWarnings( "serial" )
private class ClearProjectsAction extends AbstractAction
{
public ClearProjectsAction()
{
super( CLEAR_ITEMS );
putValue( Action.SHORT_DESCRIPTION, "Clear all recent projects" );
}
public void actionPerformed( ActionEvent e )
{
if( !UISupport.confirm( "Remove all Projects from this menu?", "Question" ) )
return;
StringToStringMap emptyMap = new StringToStringMap();
SoapUI.getSettings().setString( RECENT_PROJECTS_SETTING, emptyMap.toXml() );
updateRecentProjectsMenu();
}
}
@SuppressWarnings( "serial" )
private class ClearWorkspacesAction extends AbstractAction
{
public ClearWorkspacesAction()
{
super( CLEAR_ITEMS );
putValue( Action.SHORT_DESCRIPTION, "Clear all recent workspaces" );
}
public void actionPerformed( ActionEvent e )
{
if( !UISupport.confirm( "Remove all Workspaces from this menu?", "Question" ) )
return;
StringToStringMap emptyMap = new StringToStringMap();
SoapUI.getSettings().setString( RECENT_WORKSPACES_SETTING, emptyMap.toXml() );
updateRecentWorkspacesMenu();
}
}
@SuppressWarnings( "serial" )
private class ClearEditorsAction extends AbstractAction
{
public ClearEditorsAction()
{
super( CLEAR_ITEMS );
putValue( Action.SHORT_DESCRIPTION, "Clear all recent Editors" );
}
public void actionPerformed( ActionEvent e )
{
if( !UISupport.confirm( "Remove all Editors from this menu?", "Question" ) )
return;
recentEditorsMenu.removeAll();
recentEditorsMenu.add( EMPTYMARKER ).setEnabled( false );
recentEditorsMenu.addSeparator();
recentEditorsMenu.add( new ClearEditorsAction() );
}
}
}