/*****************************************************************************
* Copyright (c) 2011 Atos.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Atos - Initial API and implementation
* Arthur Daussy Bug 366159 - [ActivityDiagram] Activity Diagram should be able to handle correctly Interruptible Edge
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.activity.edit.policies;
import java.util.Collections;
import java.util.Map;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.Transaction;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.workspace.AbstractEMFOperation;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.AbstractEditPolicy;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.common.core.util.StringStatics;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.diagram.core.services.ViewService;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIStatusCodes;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.util.EditPartUtil;
import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.activity.edit.part.interfaces.InterruptibleEdge;
import org.eclipse.papyrus.uml.diagram.activity.part.UMLDiagramEditorPlugin;
import org.eclipse.papyrus.uml.diagram.activity.part.UMLVisualIDRegistry;
import org.eclipse.uml2.uml.ActivityEdge;
/**
* InterruptibleEdgeEditPolicy handle all action relative to interruptible Edge.
* WARNING : All EditPart where this EditPolicy is installed has to implement {@link InterruptibleEdge}
*
* @author arthur daussy
*
*/
public class InterruptibleEdgeEditPolicy extends AbstractEditPolicy {
/** constant for this edit policy role */
public static String INTERRUPTIBLE_ICON_POLICY = "interruptibleIconPolicy";
/**
* Validate the consistency of the view of the Interruptible Edge Icon
*/
@Override
public void activate() {
validateConsistency();
super.activate();
}
/**
* Validate the Consistency of the InterruptibleEdgeIcon
*/
protected void validateConsistency() {
try {
final IGraphicalEditPart graphicalHost = (IGraphicalEditPart)getHost();
final InterruptibleEdge interruptibleEdge = (InterruptibleEdge)getHost();
EObject resolveSemanticElement = graphicalHost.resolveSemanticElement();
ActivityEdge activityEdgeAux;
if(resolveSemanticElement instanceof ActivityEdge) {
activityEdgeAux = (ActivityEdge)resolveSemanticElement;
} else {
activityEdgeAux = null;
}
final ActivityEdge activityEdge = activityEdgeAux;
final View interruptbleEdgeIcon = getInterruptbleEdgeIcon(graphicalHost, interruptibleEdge);
//If property == null and there is an view => delete
if(activityEdge != null) {
if(activityEdge.getInterrupts() == null && interruptbleEdgeIcon != null) {
ICommand destroyCommand = new AbstractTransactionalCommand(graphicalHost.getEditingDomain(), "Destroy Interruptible Edge Icon", null) {
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
ViewUtil.destroy(interruptbleEdgeIcon);
return CommandResult.newOKCommandResult();
}
};
executeCommand(new ICommandProxy(destroyCommand));
}
//If property is set and no view exist => create a view
if(activityEdge.getInterrupts() != null && interruptbleEdgeIcon == null) {
ICommand createCommand = new AbstractTransactionalCommand(graphicalHost.getEditingDomain(), "Create Interruptible Edge Icon", null) {
@Override
protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
Object model = graphicalHost.getModel();
if(model != null) {
Node node = ViewService.createNode((View)model, UMLVisualIDRegistry.getType(interruptibleEdge.getInterruptibleEdgeIconVisualID()), UMLDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT);
if(node != null) {
return CommandResult.newOKCommandResult(node);
} else {
return CommandResult.newErrorCommandResult("Unable to create the view for Interruptible Edge label");
}
}
return null;
}
};
executeCommand(new ICommandProxy(createCommand));
}
}
} catch (ClassCastException e) {
throw new RuntimeException("The host of InterruptibleEdgeEditPolicy should implement IGraphicalEditPart and InterruptibleEdge which refer to an ActivityEdge");////$NON-NLS-0$
}
}
/**
* Retreive the view corresponding to interruptible edge icon
*/
private View getInterruptbleEdgeIcon(IGraphicalEditPart graphicalHost, InterruptibleEdge interruptibleEdge) {
View view = graphicalHost.getNotationView();
if(view != null) {
return ViewUtil.getChildBySemanticHint(view, String.valueOf(interruptibleEdge.getInterruptibleEdgeIconVisualID()));
}
return null;
}
/**
* Executes the supplied command inside an <code>unchecked action</code> COPIED FROM CANONICAL EDIT POLICY
*
* @param cmd
* command that can be executed (i.e., cmd.canExecute() == true)
*/
protected void executeCommand(final Command cmd) {
Map<String, Boolean> options = null;
EditPart ep = getHost();
boolean isActivating = true;
// use the viewer to determine if we are still initializing the diagram
// do not use the DiagramEditPart.isActivating since ConnectionEditPart's
// parent will not be a diagram edit part
EditPartViewer viewer = ep.getViewer();
if(viewer instanceof DiagramGraphicalViewer) {
isActivating = ((DiagramGraphicalViewer)viewer).isInitializing();
}
if(isActivating || !EditPartUtil.isWriteTransactionInProgress((IGraphicalEditPart)getHost(), false, false))
options = Collections.singletonMap(Transaction.OPTION_UNPROTECTED, Boolean.TRUE);
AbstractEMFOperation operation = new AbstractEMFOperation(((IGraphicalEditPart)getHost()).getEditingDomain(), StringStatics.BLANK, options) {
protected IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
cmd.execute();
return Status.OK_STATUS;
}
};
try {
operation.execute(new NullProgressMonitor(), null);
} catch (ExecutionException e) {
Trace.catching(DiagramUIPlugin.getInstance(), DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(), "executeCommand", e); //$NON-NLS-1$
Log.warning(DiagramUIPlugin.getInstance(), DiagramUIStatusCodes.IGNORED_EXCEPTION_WARNING, "executeCommand", e); //$NON-NLS-1$
}
}
@Override
public EditPart getTargetEditPart(Request request) {
return getHost();
}
/**
* Get the type of the node to create
*
* @return
*/
protected int getInterruptibleEdgeIconID() {
return getInterruptibleEdgeIcon().getInterruptibleEdgeIconVisualID();
}
/**
* Get the interruptible Edge
*/
protected InterruptibleEdge getInterruptibleEdgeIcon() {
return ((InterruptibleEdge)getHost());
}
/**
* Get the Actvity Edge
*/
protected ActivityEdge getActivtyEdge() {
EObject eObject = ((IGraphicalEditPart)getHost()).resolveSemanticElement();
if(eObject instanceof ActivityEdge) {
return (ActivityEdge)eObject;
}
return null;
}
/**
* Get the {@link TransactionalEditingDomain}
*
* @return
*/
protected TransactionalEditingDomain getEditingDomain() {
EditPart getHost = getHost();
if(getHost instanceof GraphicalEditPart) {
GraphicalEditPart host = (GraphicalEditPart)getHost;
return host.getEditingDomain();
}
Object view = getHost.getModel();
if(view instanceof EObject) {
EditingDomain editinDomain = AdapterFactoryEditingDomain.getEditingDomainFor((EObject)view);
if(editinDomain instanceof TransactionalEditingDomain) {
return (TransactionalEditingDomain)editinDomain;
}
}
return null;
}
}