Skip to content

Commit

Permalink
[2242] NPE on Move diagram from the view Activity Explorer
Browse files Browse the repository at this point in the history
Re-implements how the menu group "Move Diagrams" and its items are
constructed. If the selection changed, remove all contribution items of
the menu "Move Diagrams" and re-construct based on the new selection.

Added 2 RCPTT tests for testing with fragmented model:
- 1 for menu on Capella Project Explorer
- 1 for menu on Activity Explorer

Bug: 2242
Change-Id: Iab1e60d996b91f7903c9d2445e757a674b5a0e66
Signed-off-by: cong-bang.do <docongbang1993@gmail.com>
  • Loading branch information
bang-dc committed Oct 24, 2018
1 parent d39b896 commit dfa1d54
Show file tree
Hide file tree
Showing 20 changed files with 798 additions and 249 deletions.
Expand Up @@ -17,8 +17,6 @@
import org.eclipse.amalgam.explorer.activity.ui.api.editor.pages.viewers.DiagramViewer;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.DoubleClickEvent;
Expand All @@ -43,7 +41,7 @@
import org.polarsys.capella.core.platform.sirius.ui.navigator.CapellaNavigatorPlugin;
import org.polarsys.capella.core.platform.sirius.ui.navigator.actions.CloneAction;
import org.polarsys.capella.core.platform.sirius.ui.navigator.actions.LocateInCapellaExplorerAction;
import org.polarsys.capella.core.platform.sirius.ui.navigator.actions.move.representation.MoveRepresentationAction;
import org.polarsys.capella.core.platform.sirius.ui.navigator.actions.move.representation.MoveRepresentationMenuManager;
import org.polarsys.capella.core.platform.sirius.ui.navigator.viewer.CapellaNavigatorLabelProvider;
import org.polarsys.capella.core.sirius.ui.actions.DeleteRepresentationAction;
import org.polarsys.capella.core.sirius.ui.actions.OpenRepresentationsAction;
Expand All @@ -52,7 +50,7 @@
public class CapellaDiagramViewer extends DiagramViewer {

private static final String GROUP_MOVE = "Move"; //$NON-NLS-1$
private MoveRepresentationAction moveDiagramAction;
private MoveRepresentationMenuManager moveRepresentationMenu;
private OpenRepresentationsAction openRepresentation;
private RenameRepresentationAction renameRepresentationAction;
private BaseSelectionListenerAction showInCapellaExplorerAction;
Expand Down Expand Up @@ -89,27 +87,6 @@ protected MenuManager initMenuToViewer(final TreeViewer treeViewer) {
Menu contextMenu = contextMenuManager.createContextMenu(control);
control.setMenu(contextMenu);

contextMenuManager.addMenuListener(new IMenuListener2() {
/**
* {@inheritDoc}
*/
@SuppressWarnings("synthetic-access")
public void menuAboutToHide(IMenuManager manager) {
manager.remove(MoveRepresentationAction.MOVE_DIAGRAMS_MENU_ID);
// Make sure action contained list are freed at each selection
// time.
moveDiagramAction.dispose();
}

/**
* {@inheritDoc}
*/
@SuppressWarnings("synthetic-access")
public void menuAboutToShow(IMenuManager manager) {
manager.appendToGroup(GROUP_MOVE, moveDiagramAction.fillContextMenu((IStructuredSelection) treeViewer.getSelection()));
}
});

return contextMenuManager;
}

Expand Down Expand Up @@ -177,8 +154,10 @@ protected boolean updateSelection(IStructuredSelection selection) {
contextMenuManager.add(deleteRepresentationAction);

contextMenuManager.add(new Separator(GROUP_MOVE));
moveDiagramAction = new MoveRepresentationAction();
SelectionHelper.registerToSelectionChanges(moveDiagramAction, selectionProvider);
moveRepresentationMenu = new MoveRepresentationMenuManager();
SelectionHelper.registerToSelectionChanges(moveRepresentationMenu, selectionProvider);
contextMenuManager.appendToGroup(GROUP_MOVE, moveRepresentationMenu);

renameRepresentationAction = new RenameRepresentationAction() {

@Override
Expand Down Expand Up @@ -219,10 +198,10 @@ public void dispose() {
selectionProvider.removeSelectionChangedListener(openRepresentation);
openRepresentation = null;
}
if (null != moveDiagramAction) {
selectionProvider.removeSelectionChangedListener(moveDiagramAction);
moveDiagramAction.dispose();
moveDiagramAction = null;
if (null != moveRepresentationMenu) {
selectionProvider.removeSelectionChangedListener(moveRepresentationMenu);
moveRepresentationMenu.dispose();
moveRepresentationMenu = null;
}
if (null != cloneAction) {
selectionProvider.removeSelectionChangedListener(cloneAction);
Expand Down
Expand Up @@ -39,7 +39,9 @@ Require-Bundle: org.eclipse.amalgam.explorer.activity.ui,
org.polarsys.capella.core.platform.sirius.clipboard,
com.google.guava,
org.polarsys.capella.common.tools.report.appenders.file,
org.polarsys.capella.common.tools.report.appenders.usage;visibility:=reexport
org.polarsys.capella.common.tools.report.appenders.usage;visibility:=reexport,
org.eclipse.jface,
org.eclipse.ui.workbench
Bundle-ActivationPolicy: lazy
Export-Package: org.polarsys.capella.core.platform.sirius.ui.navigator,
org.polarsys.capella.core.platform.sirius.ui.navigator.actions,
Expand Down
Expand Up @@ -10,233 +10,85 @@
*******************************************************************************/
package org.polarsys.capella.core.platform.sirius.ui.navigator.actions.move.representation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.business.api.session.SessionManager;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.sirius.business.api.session.danalysis.DAnalysisSession;
import org.eclipse.sirius.ui.business.api.session.IEditingSession;
import org.eclipse.sirius.ui.business.api.session.SessionUIManager;
import org.eclipse.sirius.viewpoint.DAnalysis;
import org.eclipse.sirius.viewpoint.DRepresentationDescriptor;
import org.eclipse.sirius.viewpoint.ViewpointPackage;
import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.actions.BaseSelectionListenerAction;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.polarsys.capella.common.ef.ExecutionManager;
import org.polarsys.capella.common.ef.command.AbstractReadWriteCommand;
import org.polarsys.capella.common.helpers.TransactionHelper;
import org.polarsys.capella.common.mdsofa.common.constant.ICommonConstants;
import org.polarsys.capella.core.model.handler.helpers.RepresentationHelper;

/**
* Move a representation between airds owned by the same session.
*/
public class MoveRepresentationAction extends BaseSelectionListenerAction {
/**
* Menu manager id created to contain available move actions.
*/
public static final String MOVE_DIAGRAMS_MENU_ID = "MoveDiagrams.Menu.ID"; //$NON-NLS-1$
public class MoveRepresentationAction extends Action {

/**
* Constructor.
*/
public MoveRepresentationAction() {
super(ICommonConstants.EMPTY_STRING); // This action is not displayed.
}

/**
* Latest selection of representation descriptors to move.
*/
private Collection<DRepresentationDescriptor> _descriptorsToMove;

private Session _session;

private Collection<Resource> _availableTargetResources;

public void run(IAction action) {
// Do nothing because this action is not run.
}

public void dispose() {
if (null != _descriptorsToMove) {
_descriptorsToMove.clear();
}
if (null != _availableTargetResources) {
_availableTargetResources.clear();
}
_session = null;
}

/**
* @see org.eclipse.ui.actions.BaseSelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection)
*/
@Override
public boolean updateSelection(IStructuredSelection selection) {
if (selection.isEmpty()) {
return false;
}
boolean enabled = true;
// Clean previous execution.
_descriptorsToMove = new ArrayList<DRepresentationDescriptor>(0);
_session = null;

List<?> selectionList = ((IStructuredSelection) selection).toList();

// Retrieve descriptors from selection
Collection<DRepresentationDescriptor> descriptors = RepresentationHelper.getSelectedDescriptors(selectionList);

// Retrieve given sessions. If they belongs to the same session, we continue
List<Session> sessions = descriptors.stream().map(descriptor -> descriptor.getTarget())
.map(t -> SessionManager.INSTANCE.getSession(t)).distinct().filter(s -> s != null).collect(Collectors.toList());

enabled = false;

// If all selected elements were EObjects, retrieve editing domain if elements are from the same session
if (selectionList.size() == descriptors.size() && sessions.size() == 1) {
_session = sessions.get(0);
_descriptorsToMove = descriptors;
enabled = true;
}

if (enabled) {
private static final ImageDescriptor ACTION_IMAGE_DESCRIPTOR = AbstractUIPlugin
.imageDescriptorFromPlugin(SiriusEditPlugin.ID, "/icons/full/others/forward.gif"); //$NON-NLS-1$

_availableTargetResources = new ArrayList<Resource>(((DAnalysisSession) _session).getAllSessionResources());
private DAnalysis targetAnalysis;
private DAnalysisSession session;
private Collection<DRepresentationDescriptor> descriptors;

// Retrieve resources of descriptors
Collection<Resource> representationResources = _descriptorsToMove.stream().map(d -> d.eResource()).distinct()
.collect(Collectors.toList());
public MoveRepresentationAction(DAnalysisSession session, Collection<DRepresentationDescriptor> descriptors,
DAnalysis targetAnalysis) {

_availableTargetResources.removeAll(representationResources);
String actionLabel = Messages.MoveRepresentationAction_Title + targetAnalysis.eResource().getURI();
setId(actionLabel);
setText(actionLabel);
setImageDescriptor(ACTION_IMAGE_DESCRIPTOR);

// Check if a common target resource exist to move on.
enabled = !_availableTargetResources.isEmpty();
}
// Return the action enablement state.
return enabled;
this.targetAnalysis = targetAnalysis;
this.session = session;
this.descriptors = descriptors;
}

/**
* Get all available move actions.
*
* @return a not <code>null</code> collection.
*/
public Collection<IAction> getMoveActions() {
ArrayList<IAction> actions = new ArrayList<IAction>(0);
for (final Resource availableTargetResource : _availableTargetResources) {
Collection<DAnalysis> availableDAnalysys = EcoreUtil.getObjectsByType(availableTargetResource.getContents(),
ViewpointPackage.eINSTANCE.getDAnalysis());
for (DAnalysis dAnalysis : availableDAnalysys) {
actions.add(createMoveRepresentationsActions((DAnalysisSession) _session, _descriptorsToMove, dAnalysis));
}
@Override
public void run() {
ExecutionManager executionManager = TransactionHelper.getExecutionManager(descriptors);

if (executionManager == null) {
return;
}
return actions;
}

/**
* @see {@link org.eclipse.sirius.ui.tools.internal.views.sessionview.DesignerSessionView#createMoveRepresentationsActions(DAnalysisSession, Collection, DAnalysis)}
* @param session
* @param descriptors
* @param targetAnalysis
* @return
*/
private Action createMoveRepresentationsActions(final DAnalysisSession session,
Collection<DRepresentationDescriptor> descriptors, final DAnalysis targetAnalysis) {
ImageDescriptor descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(SiriusEditPlugin.ID,
"/icons/full/others/forward.gif"); //$NON-NLS-1$

return new Action(Messages.MoveRepresentationAction_Title + targetAnalysis.eResource().getURI(), descriptor) {
/**
* @see org.eclipse.jface.action.Action#run()
*/
@Override
executionManager.execute(new AbstractReadWriteCommand() {
public void run() {
TransactionHelper.getExecutionManager(descriptors).execute(new AbstractReadWriteCommand() {
/**
* @see java.lang.Runnable#run()
*/
public void run() {
IEditingSession uiSession = SessionUIManager.INSTANCE.getUISession(session);
if (uiSession != null) {
for (DRepresentationDescriptor descriptor : descriptors) {
closeOpenedEditor(uiSession, descriptor);
}
}
for (DRepresentationDescriptor descriptor : descriptors) {
session.moveRepresentation(targetAnalysis, descriptor);
}
}

private void closeOpenedEditor(IEditingSession uiSession, DRepresentationDescriptor descriptor) {
if (descriptor.isLoadedRepresentation()) {
IEditorPart editor = uiSession.getEditor(descriptor.getRepresentation());
if (editor != null) {
editor.getEditorSite().getPage().closeEditor(editor, false);
}
}
IEditingSession uiSession = SessionUIManager.INSTANCE.getUISession(session);
if (uiSession != null) {
for (DRepresentationDescriptor descriptor : descriptors) {
closeOpenedEditor(uiSession, descriptor);
}
});
}
};
}

/**
* Fill context sub menu for move diagrams action.
*
* @param structuredSelection
* @return a sub menu manager with all real move actions.
*/
public IMenuManager fillContextMenu(IStructuredSelection structuredSelection) {
IMenuManager subMenuManager = new MenuManager(Messages.RepresentationActionProvider_MovediagramSubMenu_Title,
MOVE_DIAGRAMS_MENU_ID);
updateSelection(structuredSelection);
// In this case, check really if the action is compatible with current selection.
if (isEnabled()) {
for (IAction containedAction : getMoveActions()) {
addAction(subMenuManager, null, containedAction);
}
for (DRepresentationDescriptor descriptor : descriptors) {
session.moveRepresentation(targetAnalysis, descriptor);
}

// The representation is moved to a new resource, so the menu item needs to be updated as well.
// Reset the selection so that the menu will be re-built.
try {
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart().getSite()
.getSelectionProvider().setSelection(StructuredSelection.EMPTY);
} catch (NullPointerException e) {
// Safely to do nothing.
}

}
}
return subMenuManager;
}

/**
* Add a dynamic action
*
* @param menu
* @param groupId
* @param action
*/
protected void addAction(IMenuManager menu, String groupId, IAction action) {
// Override the action contribution item to force the context menu to be
// refreshed even if the selected object has not changed.
ActionContributionItem item = new ActionContributionItem(action) {
@Override
public boolean isDirty() {
return true;
}

@Override
public boolean isDynamic() {
return true;

private void closeOpenedEditor(IEditingSession uiSession, DRepresentationDescriptor descriptor) {
if (descriptor.isLoadedRepresentation()) {
IEditorPart editor = uiSession.getEditor(descriptor.getRepresentation());
if (editor != null) {
editor.getEditorSite().getPage().closeEditor(editor, false);
}
}
}
};
// Append the action to a group if provided.
if (null != groupId) {
menu.appendToGroup(groupId, item);
} else {
menu.add(item);
}
});
}
}

0 comments on commit dfa1d54

Please sign in to comment.