/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.actions; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.provider.INotifyChangedListener; import org.eclipse.emf.edit.provider.ItemProvider; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.teiid.core.designer.ModelerCoreException; import org.teiid.core.designer.PluginUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.association.AssociationDescriptor; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceException; import org.teiid.designer.jdbc.JdbcImportSettings; import org.teiid.designer.jdbc.JdbcSource; import org.teiid.designer.metamodels.core.ModelAnnotation; import org.teiid.designer.metamodels.core.ModelImport; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.ui.UiConstants; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.common.AbstractUiPlugin; import org.teiid.designer.ui.common.actions.AbstractActionService; import org.teiid.designer.ui.common.actions.GlobalActionsMap; import org.teiid.designer.ui.common.eventsupport.SelectionUtilities; import org.teiid.designer.ui.editors.IEditorActionExporter; import org.teiid.designer.ui.editors.ModelObjectEditorPage; import org.teiid.designer.ui.editors.MultiPageModelEditor; import org.teiid.designer.ui.product.IModelerProductContexts; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * The <code>ModelerActionService</code> class is the Modeler Plugin's action service. It is responsible for managing all actions * for this plugin. * * @since 8.0 */ public final class ModelerActionService extends AbstractActionService implements IModelerActionConstants, UiConstants.ExtensionPoints.ModelObjectActionContributor, IModelerRcpActionIds, IModelerProductContexts { /** The logging prefix. */ public static final String PREFIX = "ModelerActionService."; //$NON-NLS-1$ /** * */ public static final String MODELING_LABEL = UiConstants.Util.getString("ModelerSpecialActionManager.specialLabel"); //$NON-NLS-1$ /** A list version of <code>IModelerActionConstants.EclipseGlobalActions.ALL_ACTIONS</code>. */ private static final List ECLIPSE_GLOBAL_ACTION_IDS; /** * The action identifiers for the eclipse global actions. Used in the <code>getAction</code> method. * <p> * <strong>Must be in the same order as in <code>IModelerActionConstants.EclipseGlobalActions.ALL_ACTIONS</code>.</strong> */ private static final List MAPPED_ACTION_IDS; static { ECLIPSE_GLOBAL_ACTION_IDS = Arrays.asList(EclipseGlobalActions.ALL_ACTIONS); // // must keep these in order with IModelerActionConstants.EclipseGlobalActions.ALL_ACTIONS // String[] ACTION_CLASSES = new String[] { CutAction.class.getName(), CopyAction.class.getName(), PasteAction.class.getName(), PrintAction.class.getName(), DeleteAction.class.getName(), FindAction.class.getName(), SelectAllAction.class.getName(), BookmarkAction.class.getName(), RenameAction.class.getName()}; MAPPED_ACTION_IDS = Arrays.asList(ACTION_CLASSES); } /** Collection of <code>IModelObjectActionContributors</code>. */ private List modelObjectContributors; /** Map of default global actions. This map actually contains action for each action identifier. */ private ModelerGlobalActionsMap defaultActionsMap; /** Utilities used for logging and localization. */ private PluginUtil utils; /** Array of all extensions to the NewChildAction extension point */ private INewChildAction[] newChildExtensions; /** Array of all extensions to the NewSiblingAction extension point */ private INewSiblingAction[] newSiblingExtensions; /** * Constructs a <code>ModelerActionService</code> associated with the given <code>IWorkbenchWindow</code>. * * @param page the associated workbench page */ public ModelerActionService( IWorkbenchPage page ) { this(UiPlugin.getDefault(), UiPlugin.getDefault().getPluginUtil(), page); } /** * @param plugin the plugin requesting action service * @param utility the plugin logging and i18n utility class * @param page the workbench page */ public ModelerActionService( AbstractUiPlugin plugin, PluginUtil utility, IWorkbenchPage page ) { super(plugin, page); utils = utility; // Need to wire any Special Actions to selection listener ModelerSpecialActionManager.wireActionsForSelection(this); } /** * Adds the given listener to the list receiving workspace container {@link org.eclipse.emf.common.notify.Notification}s. This * is a pass-through helper method to the {@link org.teiid.designer.ui.viewsupport.ModelUtilities} method. * * @param theListener the listener being added */ public void addNotifyChangedListener( INotifyChangedListener theListener ) { ModelUtilities.addNotifyChangedListener(theListener); } /** * Gives the <code>IModelObjectActionContributor</code>s a chance to contribute to the context menu * * @param theMenuMgr the context menu being contributed to * @param theSelection the current selection */ @Override public void contributePermanentActionsToContextMenu( IMenuManager theMenuMgr, ISelection theSelection ) { List contributors = getModelObjectActionContributors(); for (int size = contributors.size(), i = 0; i < size; i++) { IModelObjectActionContributor contributor = (IModelObjectActionContributor)modelObjectContributors.get(i); contributor.contributeToContextMenu(theMenuMgr, theSelection); } } /** * Fills the given menu with the standard items appropriate for a context menu of a part in the Modeler. * * @param theMenuMgr the menu being contributed to (should be a context menu) * @param theActionsMap the map of global action handlers * @param theSelection the selection used to determine how to build the new child and new sibling menus */ @Override public void contributeToContextMenu( IMenuManager theMenuMgr, GlobalActionsMap theActionsMap, ISelection theSelection ) { // if current page has global actions put them in here // if not, use default action GlobalActionsMap actionsMap = (theActionsMap == null) ? new ModelerGlobalActionsMap() : theActionsMap; // // Menu item group for insert child and sibling // theMenuMgr.add(new GroupMarker(ContextMenu.INSERT_START)); theMenuMgr.add(getInsertChildMenu(theSelection)); theMenuMgr.add(getInsertSiblingMenu(theSelection)); theMenuMgr.add(getCreateAssociationMenu(theSelection)); MenuManager modelingActionMenu = getModelingActionMenu(theSelection); if (modelingActionMenu != null && modelingActionMenu.getItems().length > 0) { theMenuMgr.add(modelingActionMenu); } theMenuMgr.add(new GroupMarker(ContextMenu.INSERT_END)); theMenuMgr.add(new Separator()); // // Menu item group for cut, copy, paste, clone, copyFullName, and copyName // theMenuMgr.add(new GroupMarker(ContextMenu.CUT_START)); theMenuMgr.add(getAction(EclipseGlobalActions.CUT, actionsMap)); theMenuMgr.add(getAction(EclipseGlobalActions.COPY, actionsMap)); theMenuMgr.add(getAction(EclipseGlobalActions.PASTE, actionsMap)); theMenuMgr.add(getAction(ModelerGlobalActions.CLONE, actionsMap)); MenuManager copyNameMenu = getCopyNameSubMenu(theSelection); if (!copyNameMenu.isEmpty()) { theMenuMgr.add(copyNameMenu); } theMenuMgr.add(new GroupMarker(ContextMenu.CUT_END)); theMenuMgr.add(new Separator()); // // Menu item group for delete, rename // theMenuMgr.add(new GroupMarker(ContextMenu.DELETE_START)); theMenuMgr.add(getAction(EclipseGlobalActions.DELETE, actionsMap)); theMenuMgr.add(getAction(EclipseGlobalActions.RENAME, actionsMap)); theMenuMgr.add(new GroupMarker(ContextMenu.DELETE_END)); theMenuMgr.add(new Separator()); // // Menu item group for open, edit // theMenuMgr.add(new GroupMarker(ContextMenu.OPEN_START)); theMenuMgr.add(getAction(ModelerGlobalActions.OPEN, actionsMap)); theMenuMgr.add(getAction(ModelerGlobalActions.EDIT, actionsMap)); theMenuMgr.add(new GroupMarker(ContextMenu.OPEN_END)); theMenuMgr.add(new Separator()); // Let any model object actions contribute at this time contributePermanentActionsToContextMenu(theMenuMgr, theSelection); // // Group to allow adding to the context menu // theMenuMgr.add(new Separator(ContextMenu.ADDITIONS)); } /** * Obtains the Edit Menu. * * @return the edit menu * @since 4.4 */ public IMenuManager getEditMenu() { IMenuManager menuMgr = getActionBars().getMenuManager(); return menuMgr.findMenuUsingPath(ModelerActionBarIdManager.getEditMenuId()); } /** * Obtains the Validate Menu. * * @return the menu or <code>null</code> if not found * @since 5.0 */ public IMenuManager getValidateMenu() { IMenuManager menuMgr = getActionBars().getMenuManager(); return menuMgr.findMenuUsingPath(ModelerActionBarIdManager.getValidateMenuId()); } /** * Obtains the File Menu. * * @return the menu or <code>null</code> if not found * @since 5.0 */ public IMenuManager getFileMenu() { IMenuManager menuMgr = getActionBars().getMenuManager(); return menuMgr.findMenuUsingPath(ModelerActionBarIdManager.getFileMenuId()); } /** * Indicates if the preconditions needed to insert a child have not been met. If one of the following is <code>true</code>, * the preconditions have not been met: * <ul> * <li>Selection is null, * <li>Selection is empty, * <li>Selection is a multi-selection, or * <li>Selected object is not an EObject or not a model. * </ul> * * @param theSelection the selection being checked * @return <code>true</code> if insert preconditions have not been met; <code>false</code> otherwise. */ private boolean failedInsertChildPreconditions( ISelection theSelection ) { boolean result = (theSelection == null) || theSelection.isEmpty() || SelectionUtilities.isMultiSelection(theSelection); if (!result) { Object obj = SelectionUtilities.getSelectedObject(theSelection); // sometimes an ItemProvider gets displayed; defer to its parent if (obj instanceof ItemProvider) { obj = ((ItemProvider)obj).getParent(); } if ((obj instanceof IResource) && ModelUtilities.isModelFile((IResource)obj)) { result = false; } else if (obj instanceof Diagram) { result = true; } else if (obj instanceof EObject) { result = false; if (obj instanceof ModelImport || obj instanceof JdbcSource || obj instanceof JdbcImportSettings) { result = true; } } else { result = true; } } return result; } /** * Indicates if the preconditions needed to insert a sibling have not been met. If one of the following is <code>true</code>, * the preconditions have not been met: * <ul> * <li>Selection is null, * <li>Selection is empty, * <li>Selection is a multi-selection, or * <li>Selected object is not an EObject. * </ul> * * @param theSelection the selection being checked * @return <code>true</code> if insert preconditions have not been met; <code>false</code> otherwise. */ private boolean failedInsertSiblingPreconditions( ISelection theSelection ) { boolean failed = false; failed = ((theSelection == null) || theSelection.isEmpty()); if( !failed ) { if( SelectionUtilities.isMultiSelection(theSelection)) { // One more check for same parent siblings failed = ! SelectionUtilities.isAllEObjects(theSelection) || !ModelObjectUtilities.shareCommonParent(SelectionUtilities.getSelectedEObjects(theSelection)); } else { failed = SelectionUtilities.getSelectedEObject(theSelection) == null; } } if (!failed) { EObject eObj = SelectionUtilities.getSelectedEObject(theSelection); if (eObj != null) { if (eObj instanceof Diagram) { Diagram diagram = (Diagram)SelectionUtilities.getSelectedEObject(theSelection); EObject target = diagram.getTarget(); // disallow for root level diagrams, ModelImport, and JDBC Import objects if (target == null || target instanceof ModelAnnotation) { failed = true; } } else if (eObj instanceof ModelImport || eObj instanceof JdbcSource || eObj instanceof JdbcImportSettings) { failed = true; } } } return failed; } /** * Indicates if the preconditions needed to create an Association have not been met. If one of the following is * <code>true</code>, the preconditions have not been met: * <ul> * <li>Selection is null, * <li>Selection is empty, * <li>Selection is not multi-selection, or * <li>Selected objects are not all EObjects or not a model. , or * <li>Selected objects all have the same parent, or * <li>Selected objects have more than 2 parents. * </ul> * * @param theSelection the selection being checked * @return <code>true</code> if insert preconditions have not been met; <code>false</code> otherwise. */ private boolean failedCreateAssociationPreconditions( ISelection theSelection ) { boolean result = (theSelection == null) || theSelection.isEmpty() || SelectionUtilities.isSingleSelection(theSelection); if (!result) { List objects = SelectionUtilities.getSelectedObjects(theSelection); for (Iterator iter = objects.iterator(); iter.hasNext();) { Object obj = iter.next(); if ((obj instanceof IResource) && !ModelUtilities.isModelFile((IResource)obj)) { result = true; break; } else if (obj instanceof Diagram) { result = true; } else if (obj instanceof EObject) { result = false; } else { result = true; break; } } } return result; } /** * Indicates if the preconditions needed to refactor have not been met. If one of the following is <code>true</code>, the * preconditions have not been met: * <ul> * <li>Selection is null, * <li>Selection is empty, * <li>Selection is a multi-selection, or * <li>Selected object is not an IResource * </ul> * * @param theSelection the selection being checked * @return <code>true</code> if refactor preconditions have not been met; <code>false</code> otherwise. */ private boolean failedRefactorPreconditions( ISelection theSelection ) { // fail if null, empty if (theSelection == null || theSelection.isEmpty()) return true; List resourceObjects = SelectionUtilities.getSelectedIResourceObjects(theSelection); IProject project = null; for (Object obj : resourceObjects) { // fail if NOT an IResource if (!(obj instanceof IResource)) { return true; } IResource resource = (IResource) obj; if (project == null) { project = resource.getProject(); } else if (! project.equals(resource.getProject())) { // 2 resources are not part of the same project return true; } } return false; } /** * @see org.teiid.designer.ui.common.actions.AbstractActionService#getAction(String) */ @Override public IAction getAction( String theActionId ) throws CoreException { // registering actions to receive events is done by the getAction(Class) method return super.getAction(getActionId(theActionId)); } /** * If the key represents an Eclipse global action a second lookup is needed to get the actual action class name which is * needed by the action service to construct the action. For non-Eclipse global action, the key is already the action class * name. * * @param theKey the action identifier whose "real" action identifier is being requested * @return the action identifier used by the action service */ public String getActionId( String theKey ) { String result = theKey; if (GlobalActionsMap.isEclipseGlobalAction(theKey)) { int index = ECLIPSE_GLOBAL_ACTION_IDS.indexOf(theKey); result = (String)MAPPED_ACTION_IDS.get(index); } return result; } /** * Gets the default action for the given identifier. The set of default action identifiers can be found by combining * {@link org.teiid.designer.ui.actions.IModelerActionConstants.ModelerGlobalActions} and * * @param theActionId the identifier of the default action being requested * @return the default action or <code>null</code> if not found */ @Override public IAction getDefaultAction( String theActionId ) { return defaultActionsMap.getAction(theActionId); } /** * Gets an insert child menu appropriate for the given input parameter. * * @param theSelection the selection whose insert child menu is being requested * @return the insert child menu */ public MenuManager getInsertChildMenu( ISelection theSelection ) { MenuManager menu = new MenuManager(utils.getString(PREFIX + "NewChildMenu.title"), //$NON-NLS-1$ ModelerActionBarIdManager.getInsertChildMenuId()); if (failedInsertChildPreconditions(theSelection)) { menu.add(new NewChildAction()); } else { // object will either be an EObject or a model since it passed preconditions Object obj = SelectionUtilities.getSelectedObject(theSelection); try { // descriptors are Commands Collection descriptors = null; // sometimes an ItemProvider gets displayed; defer to its parent if (obj instanceof ItemProvider) { obj = ((ItemProvider)obj).getParent(); } if (obj instanceof EObject) { boolean isReadOnly = ModelObjectUtilities.isReadOnly((EObject)obj); // get the allowable child types // Defect 19197 - If obj instanceof Import Container, don't get descriptors descriptors = ModelerCore.getModelEditor().getNewChildCommands((EObject)obj); if ((descriptors == null) || (descriptors.isEmpty())) { // there are none - make an empty NewChildAction menu.add(new NewChildAction()); } else { // we need to sort the actions alphabetically, so put them all in a HashMap HashMap actionMap = new HashMap(); // create a NewChildAction for every new child type Iterator iter = descriptors.iterator(); while (iter.hasNext()) { NewChildAction action = new NewChildAction((EObject)obj, (Command)iter.next()); actionMap.put(action.getText(), action); action.selectionChanged(getWorkbenchWindow().getPartService().getActivePart(), theSelection); // disable if read-only. obj should be EObject or an IResource. action.setEnabled(!isReadOnly); } // sort the keys of the actionMap to put them in alphabetical order TreeSet set = new TreeSet(actionMap.keySet()); iter = set.iterator(); while (iter.hasNext()) { // add each action to the menu menu.add((IAction)actionMap.get(iter.next())); } // get the NewChildAction extensions and populate with any actions // Note: these should not be sorted - they always go on the bottom of the menu for (int i = 0; i < getNewChildExtensions().length; ++i) { INewChildAction action = getNewChildExtensions()[i]; if (action.canCreateChild((EObject)obj)) { menu.add(action); action.setEnabled(!isReadOnly); } } } } else if (obj instanceof IFile) { try { // models are files ModelResource modelResource = ModelUtil.getModelResource((IFile)obj, false); if (modelResource != null && !modelResource.hasErrors()) { Resource resource = modelResource.getEmfResource(); descriptors = ModelerCore.getModelEditor().getNewRootObjectCommands(resource); boolean isReadOnly = ModelUtil.isIResourceReadOnly((IResource)obj); boolean addedExtension = false; // we need to sort the actions alphabetically, so put them all in a HashMap HashMap actionMap = new HashMap(); Iterator iter = descriptors.iterator(); while (iter.hasNext()) { Command nextCommand = (Command)iter.next(); if( !nextCommand.getLabel().equalsIgnoreCase("schema") //$NON-NLS-1$ && !nextCommand.getLabel().equalsIgnoreCase("catalog") ) { //$NON-NLS-1$ NewChildAction action = new NewChildAction(resource, nextCommand); actionMap.put(action.getText(), action); action.selectionChanged(getWorkbenchWindow().getPartService().getActivePart(), theSelection); // disable if read-only. obj should be EObject or an IResource. action.setEnabled(!isReadOnly); } } // sort the keys of the actionMap to put them in alphabetical order TreeSet set = new TreeSet(actionMap.keySet()); iter = set.iterator(); while (iter.hasNext()) { // add each action to the menu menu.add((IAction)actionMap.get(iter.next())); } // get the NewChildAction extensions and populate with any actions // Note: these should not be sorted - they always go on the bottom of the menu for (int i = 0; i < getNewChildExtensions().length; ++i) { INewChildAction action = getNewChildExtensions()[i]; if( i == 0 ) { menu.add(new Separator()); } if (action.canCreateChild((IFile)obj)) { addedExtension = true; menu.add(action); action.setEnabled(!isReadOnly); } } if( (descriptors.isEmpty()) && !addedExtension ) { menu.add(new NewChildAction()); } } else { menu.add(new NewChildAction()); } } catch (ModelWorkspaceException theException) { utils.log(IStatus.ERROR, theException, utils.getString(PREFIX + "NewChildMenu.problem", //$NON-NLS-1$ new Object[] {theSelection})); } } } catch (ModelerCoreException theException) { utils.log(IStatus.ERROR, theException, utils.getString(PREFIX + "NewChildMenu.problem", //$NON-NLS-1$ new Object[] {theSelection})); } } return menu; } /** * Gets an insert sibling menu appropriate for the given input parameter. * * @param theSelection the selection whose insert sibling menu is being requested * @return the insert sibling menu */ public MenuManager getInsertSiblingMenu( ISelection theSelection ) { MenuManager menu = new MenuManager(utils.getString(PREFIX + "NewSiblingMenu.title"), //$NON-NLS-1$ ModelerActionBarIdManager.getInsertSiblingMenuId()); if (failedInsertSiblingPreconditions(theSelection)) { menu.add(new NewSiblingAction()); } else { // should be guaranteed to have an EObject at this point // Could be multi-selection List<EObject> eObjects = SelectionUtilities.getSelectedEObjects(theSelection); EObject eObj = eObjects.get(0); if (eObj instanceof Diagram) { eObj = ((Diagram)eObj).getTarget(); } boolean isReadOnly = ModelObjectUtilities.isReadOnly(eObj); try { // descriptors are Commands Collection commands = ModelerCore.getModelEditor().getNewSiblingCommands(eObj); boolean addedExtension = false; // we need to sort the actions alphabetically, so put them all in a HashMap if( commands != null ) { HashMap actionMap = new HashMap(); Iterator iter = commands.iterator(); while (iter.hasNext()) { Command cmd = (Command)iter.next(); NewSiblingAction action = new NewSiblingAction(eObj, cmd); actionMap.put(action.getText(), action); action.selectionChanged(getWorkbenchWindow().getPartService().getActivePart(), theSelection); // disable if read-only action.setEnabled(!isReadOnly); } // sort the keys of the actionMap to put them in alphabetical order TreeSet set = new TreeSet(actionMap.keySet()); iter = set.iterator(); while (iter.hasNext()) { // add each action to the menu menu.add((IAction)actionMap.get(iter.next())); } } // get the NewSiblingAction extensions and populate with any actions // Note: these should not be sorted - they always go on the bottom of the menu for (int i = 0; i < getNewSiblingExtensions().length; ++i) { INewSiblingAction action = getNewSiblingExtensions()[i]; if (action.canCreateSibling(eObj)) { if( i == 0 ) { menu.add(new Separator()); } menu.add(action); addedExtension = true; action.setEnabled(!isReadOnly); } } if( commands.isEmpty() && !addedExtension ) { menu.add(new NewSiblingAction()); } } catch (ModelerCoreException theException) { utils.log(IStatus.ERROR, theException, utils.getString(PREFIX + "NewSiblingMenu.problem", //$NON-NLS-1$ new Object[] {theSelection})); } } return menu; } /** * Gets a create association menu appropriate for the given input parameter. * * @param theSelection the selection whose insert sibling menu is being requested * @return the insert sibling menu */ public MenuManager getCreateAssociationMenu( ISelection theSelection ) { MenuManager menu = new MenuManager(utils.getString(PREFIX + "NewAssociationMenu.title"), //$NON-NLS-1$ ModelerActionBarIdManager.getInsertAssociationMenuId()); if (failedCreateAssociationPreconditions(theSelection)) { menu.add(new NewAssociationAction()); } else { try { // association descriptors are AssociationDescriptor objects List selectedEObjects = SelectionUtilities.getSelectedEObjects(theSelection); Collection descriptors = ModelerCore.getModelEditor().getNewAssociationDescriptors(selectedEObjects); if ((descriptors != null) && (!descriptors.isEmpty())) { // disable if read-only boolean isReadOnly = false; for (Iterator iter = selectedEObjects.iterator(); iter.hasNext();) { if (ModelObjectUtilities.isReadOnly((EObject)iter.next())) { isReadOnly = true; break; } } int index = 0; for (Iterator iter = descriptors.iterator(); iter.hasNext();) { AssociationDescriptor ad = (AssociationDescriptor)iter.next(); if (ad.isAmbiguous()) { MenuManager submenu = new MenuManager(ad.getText()); String groupName = "associationSubmenuGroup" + (index++); //$NON-NLS-1$ menu.insert(0, new GroupMarker(groupName)); menu.appendToGroup(groupName, submenu); AssociationDescriptor[] children = ad.getChildren(); for (int i = 0; i < children.length; ++i) { NewAssociationAction action = new NewAssociationAction(children[i]); submenu.add(action); action.selectionChanged(getWorkbenchWindow().getPartService().getActivePart(), theSelection); } } else { IAction action = new NewAssociationAction(ad); menu.add(action); action.setEnabled(!isReadOnly); } } } else { menu.add(new NewAssociationAction()); } } catch (ModelerCoreException theException) { utils.log(IStatus.ERROR, theException, utils.getString(PREFIX + "NewAssociationMenu.problem", //$NON-NLS-1$ new Object[] {theSelection})); } } return menu; } // convenience method to get exported modeling actions from ModelEditor and multi-page editors. private List getExportedActions( ISelection selection ) { List expActions = new ArrayList(); // // If current editor is a IEditorActionExporter, get it's exported actions // IEditorPart editor = getWorkbenchWindow().getActivePage().getActiveEditor(); if (editor instanceof IEditorActionExporter) { List newActions = ((IEditorActionExporter)editor).getAdditionalModelingActions(selection); if (!newActions.isEmpty()) { expActions.addAll(newActions); } } // // Check for ModelObject Editor and get it's exported actions // if (editor instanceof MultiPageModelEditor) { ModelObjectEditorPage moep = ((MultiPageModelEditor)editor).getActiveObjectEditor(); if (moep != null) { List newActions = moep.getAdditionalModelingActions(selection); if (!newActions.isEmpty()) { expActions.addAll(newActions); } } } return expActions; } /** * Allows access to a full modeling action menu based on a supplied selection * * @param theSelection the selection object * @return the menu manager * @since 5.0 */ public MenuManager getModelingActionMenu( ISelection theSelection ) { MenuManager menu = new MenuManager(MODELING_LABEL, ModelerActionBarIdManager.getModelingMenuId()); MenuManager mosaMenu = ModelerSpecialActionManager.getModeObjectSpecialActionMenu(theSelection); if (mosaMenu != null && mosaMenu.getItems().length > 0) { Object[] items = mosaMenu.getItems(); for (int i = 0; i < items.length; i++) { menu.add(mosaMenu.getItems()[i]); } menu.add(new Separator()); } List exportedActions = getExportedActions(theSelection); if (!exportedActions.isEmpty()) { for (int j = 0; j < exportedActions.size(); j++) { Object nextItem = exportedActions.get(j); if (nextItem instanceof IAction) { menu.add((IAction)nextItem); } else if (nextItem instanceof ActionContributionItem) { menu.add((ActionContributionItem)nextItem); } } menu.add(new Separator()); } boolean foundModelActions = false; MenuManager mraMenu = ModelResourceActionManager.getModelResourceActionMenu(theSelection); if (mraMenu != null && mraMenu.getItems().length > 0) { Object[] items = mraMenu.getItems(); for (int i = 0; i < items.length; i++) { menu.add(mraMenu.getItems()[i]); foundModelActions = true; } } // MenuManager connMenu = ModelResourceActionManager.getModelResourceConnectionActionMenu(theSelection); // if (connMenu != null && connMenu.getItems().length > 0) { // Object[] items = connMenu.getItems(); // for (int i = 0; i < items.length; i++) { // menu.add(connMenu.getItems()[i]); // foundModelActions = true; // } // } if( foundModelActions ) { menu.add(new Separator()); } // get permanent action contributors List contributors = getModelObjectActionContributors(); boolean addedActions = false; for (int size = contributors.size(), i = 0; i < size; i++) { IModelObjectActionContributor contributor = (IModelObjectActionContributor)modelObjectContributors.get(i); List additionalActions = contributor.getAdditionalModelingActions(theSelection); if (!additionalActions.isEmpty()) { for (int j = 0; j < additionalActions.size(); j++) { if (!addedActions) { addedActions = true; } menu.add((IAction)additionalActions.get(j)); } } } if (addedActions) { menu.add(new Separator()); } if (menu.isEmpty()) { // just add a disabled "none allowed" item so menu is not empty menu.add(new NewChildAction()); } return menu; } /** * Gets the Copy Name menu. * @param selection the selected object * * @return the Copy Name submenu */ public MenuManager getCopyNameSubMenu( Object selection) { MenuManager menu = new MenuManager(utils.getString(PREFIX + "copyNameSubMenu.title")); //$NON-NLS-1$ CopyFullNameAction action1 = new CopyFullNameAction(); action1.getActionWorker().selectionChanged(selection); menu.add(action1); CopyNameAction action2 = new CopyNameAction(); action1.getActionWorker().selectionChanged(selection); menu.add(action2); return menu; } /** * Gets a list of the extension for the ModelObjectActionContributor extension point. * * @return the list of <code>IModelObjectActionContributor</code> implementations */ public List getModelObjectActionContributors() { if (modelObjectContributors == null) { // get the ModelObjectActionContributor extension point from the plugin class IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(UiConstants.PLUGIN_ID, ID); // get the all extensions to the ModelObjectActionContributor extension point IExtension[] extensions = extensionPoint.getExtensions(); if (extensions.length > 0) { modelObjectContributors = new ArrayList(extensions.length); // for each extension get their contributor for (int i = 0; i < extensions.length; i++) { IConfigurationElement[] elements = extensions[i].getConfigurationElements(); Object extension = null; for (int j = 0; j < elements.length; j++) { try { extension = elements[j].createExecutableExtension(CLASSNAME); if (extension instanceof IModelObjectActionContributor) { modelObjectContributors.add(extension); } else { utils.log(IStatus.ERROR, utils.getString(PREFIX + "wrongContributorClass", //$NON-NLS-1$ new Object[] {extension.getClass().getName()})); } } catch (Exception theException) { utils.log(IStatus.ERROR, theException, utils.getString(PREFIX + "contributorProblem", //$NON-NLS-1$ new Object[] {elements[j].getAttribute(CLASSNAME)})); } } } } else { modelObjectContributors = Collections.EMPTY_LIST; } } return modelObjectContributors; } /** * Initializes the <code>Map</code> of all global actions. Must be called after construction to get actions to take the place * of the default eclipse actions. */ public void initializeGlobalActions() { // need to put the real actions into the map as the new constructed map only // contains identifiers which stand for "use default" action defaultActionsMap = new ModelerGlobalActionsMap(); // load all default global actions since the map doesn't really have the default actions // as values. it just has a marker. for (int i = 0; i < ModelerGlobalActionsMap.ALL_GLOBAL_ACTIONS.length; i++) { String actionId = ModelerGlobalActionsMap.ALL_GLOBAL_ACTIONS[i]; try { // the call to getAction(String) throws a CoreException if the action cannot be constructed // also the call to getAction(String) registers the action to receive appropriate events IAction action = getAction(actionId); defaultActionsMap.put(actionId, action); } catch (CoreException e) { String message = UiConstants.Util.getString(PREFIX + "getActionErrorMessage", actionId); //$NON-NLS-1$ UiConstants.Util.log(IStatus.ERROR, e, message); } } } /** * @see org.teiid.designer.ui.common.actions.AbstractActionService#registerEventHandler(org.eclipse.jface.action.IAction) */ @Override protected void registerEventHandler( IAction theAction ) { // first let super register super.registerEventHandler(theAction); // EObject notifier events if (theAction instanceof INotifyChangedListener) { addNotifyChangedListener((INotifyChangedListener)theAction); } } /** * Registers the Modeler's default global actions for the given <code>IPageSite</code>'s <code>IActionBars</code>. * * @param bars the action bars to register global actions */ public void registerDefaultGlobalActions( IActionBars bars ) { Iterator itr = defaultActionsMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry = (Map.Entry)itr.next(); bars.setGlobalActionHandler((String)entry.getKey(), (IAction)entry.getValue()); } } /** * Removes the given listener from receiving workspace container {@link org.eclipse.emf.common.notify.Notification}s. This is * a pass-through helper method to the {@link org.teiid.designer.ui.viewsupport.ModelUtilities} method. * * @param theListener the listener being removed */ public void removeNotifyChangedListener( INotifyChangedListener theListener ) { ModelUtilities.removeNotifyChangedListener(theListener); } /** * @see org.teiid.designer.ui.common.actions.AbstractActionService#unregisterEventHandler(org.eclipse.jface.action.IAction) */ @Override protected void unregisterEventHandler( IAction theAction ) { // first let super unregister super.unregisterEventHandler(theAction); // unregister EObject notifier events if (theAction instanceof INotifyChangedListener) { removeNotifyChangedListener((INotifyChangedListener)theAction); } } private INewChildAction[] getNewChildExtensions() { if (newChildExtensions == null) { // get the NewChildAction extension point from the plugin class String id = UiConstants.ExtensionPoints.NewChildExtension.ID; String classTag = UiConstants.ExtensionPoints.NewChildExtension.CLASS; String className = UiConstants.ExtensionPoints.NewChildExtension.CLASSNAME; IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(UiConstants.PLUGIN_ID, id); // get the all extensions to the NewChildAction extension point IExtension[] extensions = extensionPoint.getExtensions(); ArrayList actionList = new ArrayList(); // walk through the extensions and find all INewChildAction implementations for (int i = 0; i < extensions.length; ++i) { IConfigurationElement[] elements = extensions[i].getConfigurationElements(); try { // first, find the content provider instance and add it to the instance list for (int j = 0; j < elements.length; ++j) { if (elements[j].getName().equals(classTag)) { Object action = elements[j].createExecutableExtension(className); if (action instanceof INewChildAction) { actionList.add(action); } } } } catch (Exception e) { // catch any Exception that occurred obtaining the configuration and log it String message = UiConstants.Util.getString("ModelerActionService.configurationErrorMessage", //$NON-NLS-1$ extensions[i].getUniqueIdentifier()); UiConstants.Util.log(IStatus.ERROR, e, message); } } newChildExtensions = new INewChildAction[actionList.size()]; for (int i = 0; i < actionList.size(); ++i) { newChildExtensions[i] = (INewChildAction)actionList.get(i); } } return newChildExtensions; } private INewSiblingAction[] getNewSiblingExtensions() { if (newSiblingExtensions == null) { // get the NewSiblingAction extension point from the plugin class String id = UiConstants.ExtensionPoints.NewSiblingExtension.ID; String classTag = UiConstants.ExtensionPoints.NewSiblingExtension.CLASS; String className = UiConstants.ExtensionPoints.NewSiblingExtension.CLASSNAME; IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(UiConstants.PLUGIN_ID, id); // get the all extensions to the NewSiblingAction extension point IExtension[] extensions = extensionPoint.getExtensions(); ArrayList actionList = new ArrayList(); // walk through the extensions and find all INewSiblingAction implementations for (int i = 0; i < extensions.length; ++i) { IConfigurationElement[] elements = extensions[i].getConfigurationElements(); try { // first, find the content provider instance and add it to the instance list for (int j = 0; j < elements.length; ++j) { if (elements[j].getName().equals(classTag)) { Object action = elements[j].createExecutableExtension(className); if (action instanceof INewSiblingAction) { actionList.add(action); } } } } catch (Exception e) { // catch any Exception that occurred obtaining the configuration and log it String message = UiConstants.Util.getString("ModelerActionService.configurationErrorMessage", //$NON-NLS-1$ extensions[i].getUniqueIdentifier()); UiConstants.Util.log(IStatus.ERROR, e, message); } } newSiblingExtensions = new INewSiblingAction[actionList.size()]; for (int i = 0; i < actionList.size(); ++i) { newSiblingExtensions[i] = (INewSiblingAction)actionList.get(i); } } return newSiblingExtensions; } }