/***************************************************************************** * Copyright (c) 2010 CEA * * * 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 Origin - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.sequence.util; import java.util.ArrayList; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.draw2d.PositionConstants; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.ConnectionEditPart; import org.eclipse.gef.EditPart; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CompoundCommand; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand; import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.ConnectionNodeEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IBorderItemEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.requests.EditCommandRequestWrapper; import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; import org.eclipse.papyrus.uml.diagram.common.util.DiagramEditPartsUtil; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractExecutionSpecificationEditPart; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.ObservationLinkEditPart; import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.TimeObservationLabelEditPart; import org.eclipse.uml2.uml.DestructionOccurrenceSpecification; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.ExecutionSpecification; import org.eclipse.uml2.uml.Lifeline; import org.eclipse.uml2.uml.Message; import org.eclipse.uml2.uml.MessageEnd; import org.eclipse.uml2.uml.OccurrenceSpecification; import org.eclipse.uml2.uml.TimeObservation; /** * An Helper to get deleting command for the sequence diagram elements. */ public class SequenceDeleteHelper { /** * Complete an ICommand which destroys an DestructionEvent element to also destroy dependent time/duration constraint/observation linked with * these ends * * @param deleteViewsCmd * the command to complete * @param editingDomain * the editing domain * @param destructionEventPart * the execution specification edit part on which the request is called * @return the deletion command deleteViewsCmd for convenience */ public static CompoundCommand completeDeleteDestructionOccurenceViewCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, EditPart destructionEventPart) { if(destructionEventPart instanceof IGraphicalEditPart) { EObject obj = ((IGraphicalEditPart)destructionEventPart).resolveSemanticElement(); if(obj instanceof DestructionOccurrenceSpecification) { LifelineEditPart lifelinePart = SequenceUtil.getParentLifelinePart(destructionEventPart); if(lifelinePart != null) { for(Object lifelineChild : lifelinePart.getChildren()) { if(lifelineChild instanceof IBorderItemEditPart) { final IBorderItemEditPart timePart = (IBorderItemEditPart)lifelineChild; //At most one destruction event. Only parts linked to it can not move for now. boolean isNotLinked = OccurrenceSpecificationMoveHelper.canTimeElementPartBeYMoved(timePart); if(!isNotLinked) { // time part is linked, delete the view Command deleteTimeViewCommand = new ICommandProxy(new DeleteCommand(editingDomain, (View)timePart.getModel())); deleteViewsCmd.add(deleteTimeViewCommand); } } } } } } return deleteViewsCmd; } /** * Complete an ICommand which destroys an ExecutionSpecification element to also destroy dependent finish and start events and time/duration * constraint/observation linked with these ends * * @param deleteViewsCmd * the command to complete * @param editingDomain * the editing domain * @param executionPart * the execution specification edit part on which the request is called * @return the deletion command deleteViewsCmd for convenience */ public static CompoundCommand completeDeleteMessageViewCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, EditPart messagePart) { if(messagePart instanceof IGraphicalEditPart) { EObject obj = ((IGraphicalEditPart)messagePart).resolveSemanticElement(); if(obj instanceof Message) { Message message = (Message)obj; LifelineEditPart srcLifelinePart = SequenceUtil.getParentLifelinePart(((ConnectionNodeEditPart)messagePart).getSource()); MessageEnd send = message.getSendEvent(); addDeleteRelatedTimePartsToCommand(deleteViewsCmd, editingDomain, srcLifelinePart, send); LifelineEditPart tgtLifelinePart = SequenceUtil.getParentLifelinePart(((ConnectionNodeEditPart)messagePart).getTarget()); MessageEnd receive = message.getReceiveEvent(); addDeleteRelatedTimePartsToCommand(deleteViewsCmd, editingDomain, tgtLifelinePart, receive); // also delete time observation links which are related to message end if (send instanceof OccurrenceSpecification) { addDeleteRelatedTimeObservationLinkCommand(deleteViewsCmd, editingDomain,(OccurrenceSpecification) send, srcLifelinePart,false); } if (receive instanceof OccurrenceSpecification) { addDeleteRelatedTimeObservationLinkCommand(deleteViewsCmd, editingDomain,(OccurrenceSpecification) receive, tgtLifelinePart,false); } } } return deleteViewsCmd; } private static void addDeleteRelatedTimePartsToCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, LifelineEditPart lifelineEP, MessageEnd messageEnd) { if(lifelineEP != null && messageEnd instanceof OccurrenceSpecification) { for(Object lifelineChild : lifelineEP.getChildren()) { if(lifelineChild instanceof IBorderItemEditPart) { final IBorderItemEditPart timePart = (IBorderItemEditPart)lifelineChild; int positionForEvent = SequenceUtil.positionWhereEventIsLinkedToPart((OccurrenceSpecification)messageEnd, timePart); if(positionForEvent != PositionConstants.NONE) { // time part is linked, delete the view Command deleteTimeViewCommand = new ICommandProxy(new DeleteCommand(editingDomain, (View)timePart.getModel())); deleteViewsCmd.add(deleteTimeViewCommand); } } } } } /** * Complete an ICommand which destroys an ExecutionSpecification element to also destroy dependent finish and start events and time/duration * constraint/observation linked with these ends * * @param deleteViewsCmd * the command to complete * @param editingDomain * the editing domain * @param executionPart * the execution specification edit part on which the request is called * @return the deletion command deleteViewsCmd for convenience */ public static CompoundCommand completeDeleteExecutionSpecificationViewCommand(CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, EditPart executionPart) { if(executionPart instanceof IGraphicalEditPart) { EObject obj = ((IGraphicalEditPart)executionPart).resolveSemanticElement(); if(obj instanceof ExecutionSpecification) { ExecutionSpecification execution = (ExecutionSpecification)obj; LifelineEditPart lifelinePart = SequenceUtil.getParentLifelinePart(executionPart); if(lifelinePart != null) { for(Object lifelineChild : lifelinePart.getChildren()) { if(lifelineChild instanceof IBorderItemEditPart) { final IBorderItemEditPart timePart = (IBorderItemEditPart)lifelineChild; OccurrenceSpecification start = execution.getStart(); OccurrenceSpecification finish = execution.getStart(); int positionForStart = SequenceUtil.positionWhereEventIsLinkedToPart(start, timePart); int positionForFinish = SequenceUtil.positionWhereEventIsLinkedToPart(finish, timePart); if(positionForStart != PositionConstants.NONE || positionForFinish != PositionConstants.NONE) { // time part is linked, delete the view Command deleteTimeViewCommand = new ICommandProxy(new DeleteCommand(editingDomain, (View)timePart.getModel())); deleteViewsCmd.add(deleteTimeViewCommand); } } } // delete each observation linked time element for(Object targetConnection : lifelinePart.getTargetConnections()){ if(targetConnection instanceof ObservationLinkEditPart){ ObservationLinkEditPart observationLinkEditPart = (ObservationLinkEditPart)targetConnection; TimeObservationLabelEditPart source = (TimeObservationLabelEditPart)observationLinkEditPart.getSource(); OccurrenceSpecification start = execution.getStart(); OccurrenceSpecification finish = execution.getFinish(); int positionForStart = SequenceUtil.positionWhereEventIsLinkedToPart(start, source); int positionForFinish = SequenceUtil.positionWhereEventIsLinkedToPart(finish, source); if(positionForStart != PositionConstants.NONE) { // time part is linked, delete the view //Command deleteTimeViewCommand = new ICommandProxy(new DeleteCommand(editingDomain, (View)source.getModel())); //deleteViewsCmd.add(deleteTimeViewCommand); addDeleteRelatedTimeObservationLinkCommand(deleteViewsCmd, editingDomain, start, lifelinePart,false); } if(positionForFinish != PositionConstants.NONE) { addDeleteRelatedTimeObservationLinkCommand(deleteViewsCmd, editingDomain, finish, lifelinePart,false); } } } } } } return deleteViewsCmd; } /** * Delete the views associated with a list of elements. * * @param cmd * the CompositeTransactionalCommand * @param element * the list of model elements * @param editingDomain * the editing domain to use. */ public static void deleteView(CompositeTransactionalCommand cmd, List<Element> elements, TransactionalEditingDomain editingDomain) { for(Element element : elements) { deleteView(cmd, element, editingDomain); } } /** * Delete the views associated with an element. * * @param cmd * the CompositeTransactionalCommand * @param element * the model element referenced by the views * @param editingDomain * the editing domain to use. */ public static void deleteView(CompositeTransactionalCommand cmd, Element element, TransactionalEditingDomain editingDomain) { // Destroy its views @SuppressWarnings("rawtypes") List views = DiagramEditPartsUtil.getEObjectViews(element); for(Object object : views) { if(object instanceof View) { cmd.add(new DeleteCommand(editingDomain, (View)object)); } } } /** * apex updated * * Add complete delete message command * @param req * @param editPart * @return Command */ public static Command completeDeleteMessageCommand(DestroyElementRequest req,EditPart editPart) { EObject selectedEObject = req.getElementToDestroy(); IElementEditService provider = ElementEditServiceUtils .getCommandProvider(selectedEObject); if (provider != null) { // Retrieve delete command from the Element Edit service ICommand deleteCommand = provider.getEditCommand(req); if (deleteCommand != null) { CompositeCommand command = new CompositeCommand( deleteCommand.getLabel()); command.add(deleteCommand); Message message = (Message) selectedEObject; MessageEnd receiveEvent = message.getReceiveEvent(); if (receiveEvent != null) { DestroyElementRequest myReq = new DestroyElementRequest( req.getEditingDomain(), receiveEvent, false); command.add(new DestroyElementCommand(myReq)); } MessageEnd sendEvent = message.getSendEvent(); if (sendEvent != null) { DestroyElementRequest myReq = new DestroyElementRequest( req.getEditingDomain(), sendEvent, false); command.add(new DestroyElementCommand(myReq)); } addDeleteMessageRelatedTimeObservationLinkCommand(req.getEditingDomain(), editPart, command, receiveEvent,true); addDeleteMessageRelatedTimeObservationLinkCommand(req.getEditingDomain(), editPart, command, sendEvent,true); /* apex added start */ // connection의 Target EditPart(ExecutionSpecification)도 함께 삭제 if (editPart instanceof ConnectionEditPart) { EditPart target = ((ConnectionEditPart)editPart).getTarget(); if (target instanceof AbstractExecutionSpecificationEditPart) { Command tgtDeleteCommand = target.getCommand(new EditCommandRequestWrapper(new DestroyElementRequest(false))); command.add(new CommandProxy(tgtDeleteCommand)); } } /* apex added end */ return new ICommandProxy(command); } } return UnexecutableCommand.INSTANCE; } /** * Add delete message related time observation link command * @param editingDomain * @param editPart * @param command * @param messageEnd * @param deleteRelatedEvent */ public static void addDeleteMessageRelatedTimeObservationLinkCommand( TransactionalEditingDomain editingDomain, EditPart editPart, CompositeCommand command, MessageEnd messageEnd,boolean deleteRelatedEvent) { if(messageEnd != null){ OccurrenceSpecification occurrenceSpecification = (OccurrenceSpecification) messageEnd; EList<Lifeline> receiveCovereds = occurrenceSpecification.getCovereds(); CompoundCommand CompoundCommand = new CompoundCommand(); CompoundCommand.add(new ICommandProxy(command)); LifelineEditPart srcLifelinePart = (LifelineEditPart) SequenceUtil.getEditPart(editPart,receiveCovereds.get(0), LifelineEditPart.class); addDeleteRelatedTimeObservationLinkCommand(CompoundCommand, editingDomain, occurrenceSpecification, srcLifelinePart,deleteRelatedEvent); } } /** * Add command for deleting time observation link which related to occurence specification * @param deleteViewsCmd * @param editingDomain * @param os * @param srcLifelinePart * @param deleteRelatedEvent */ private static void addDeleteRelatedTimeObservationLinkCommand( CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain, OccurrenceSpecification os, LifelineEditPart srcLifelinePart,boolean deleteRelatedEvent) { List<OccurrenceSpecification> oss = new ArrayList<OccurrenceSpecification>(); oss.add(os); addDeleteRelatedTimeObservationLinkCommand(deleteViewsCmd, editingDomain,srcLifelinePart, oss,deleteRelatedEvent); } /** * Add command for deleting time observation link which related to occurence specification * @param deleteViewsCmd * @param editingDomain * @param srcLifelinePart * @param oss * @param deleteRelatedEvent */ public static void addDeleteRelatedTimeObservationLinkCommand( CompoundCommand deleteViewsCmd, TransactionalEditingDomain editingDomain,LifelineEditPart srcLifelinePart,List<OccurrenceSpecification> oss,boolean deleteRelatedEvent) { List<TimeObservationLabelEditPart> timeObservationEditParts = SequenceUtil.findOccurenceSpecificationRelatedTimeObservationPart(srcLifelinePart,oss); for (final TimeObservationLabelEditPart timeObservationEditPart : timeObservationEditParts) { View view = (View) timeObservationEditPart.getModel(); EList sourceEdges = view.getSourceEdges(); for (Object sourceEdge : sourceEdges) { Command deleteTimeViewCommand = new ICommandProxy( new DeleteCommand(editingDomain, (View) sourceEdge)); deleteViewsCmd.add(deleteTimeViewCommand); } if(deleteRelatedEvent){ deleteViewsCmd.add(new ICommandProxy(new AbstractTransactionalCommand(editingDomain,"Remove TimeObservation related event",null){ @Override protected CommandResult doExecuteWithResult( IProgressMonitor monitor, IAdaptable info) throws ExecutionException { TimeObservation timeObservation = (TimeObservation)(timeObservationEditPart.resolveSemanticElement()); timeObservation.setEvent(null); return CommandResult.newOKCommandResult(); } })); } } } }