/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * * 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: * * Yann Tanguy (CEA LIST) yann.tanguy@cea.fr - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.uml.service.types.helper; import java.util.ArrayList; import java.util.List; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; import org.eclipse.papyrus.infra.services.edit.service.ElementEditServiceUtils; import org.eclipse.papyrus.infra.services.edit.service.IElementEditService; import org.eclipse.papyrus.uml.service.types.command.MessageAsyncReorientCommand; import org.eclipse.papyrus.uml.service.types.command.MessageCreateReorientCommand; import org.eclipse.papyrus.uml.service.types.command.MessageDeleteReorientCommand; import org.eclipse.papyrus.uml.service.types.command.MessageFoundReorientCommand; import org.eclipse.papyrus.uml.service.types.command.MessageLostReorientCommand; import org.eclipse.papyrus.uml.service.types.command.MessageReplyReorientCommand; import org.eclipse.papyrus.uml.service.types.command.MessageSyncReorientCommand; import org.eclipse.papyrus.uml.tools.utils.ExecutionSpecificationUtil; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.ExecutionSpecification; import org.eclipse.uml2.uml.Gate; import org.eclipse.uml2.uml.Lifeline; import org.eclipse.uml2.uml.Message; import org.eclipse.uml2.uml.MessageEnd; import org.eclipse.uml2.uml.MessageKind; import org.eclipse.uml2.uml.MessageOccurrenceSpecification; import org.eclipse.uml2.uml.MessageSort; import org.eclipse.uml2.uml.OccurrenceSpecification; import org.eclipse.uml2.uml.UMLPackage; /** * <pre> * * This helper provides edit commands for UML {@link Message}. * * </pre> */ public class MessageEditHelper extends ElementEditHelper { /** * <pre> * This method build a re-orient command depending on the kind of Message, * and compose this basic command with another which updates the MessageEnd. * </pre> * * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelper#getReorientRelationshipCommand(org.eclipse.gmf.runtime.emf.type.core.requests.ReorientRelationshipRequest) * * @param req * the re-orient request * @return the re-orient command */ @Override protected ICommand getReorientRelationshipCommand(ReorientRelationshipRequest req) { ICommand reorientCommand = null; // Build the initial re-orient command depending on the kind of Message Message msgToReorient = (Message)req.getRelationship(); if(msgToReorient.getMessageKind() == MessageKind.LOST_LITERAL) { reorientCommand = new MessageLostReorientCommand(req); } else if(msgToReorient.getMessageKind() == MessageKind.FOUND_LITERAL) { reorientCommand = new MessageFoundReorientCommand(req); } else if(msgToReorient.getMessageSort() == MessageSort.SYNCH_CALL_LITERAL) { reorientCommand = new MessageSyncReorientCommand(req); } else if(msgToReorient.getMessageSort() == MessageSort.ASYNCH_CALL_LITERAL) { reorientCommand = new MessageAsyncReorientCommand(req); } else if(msgToReorient.getMessageSort() == MessageSort.ASYNCH_SIGNAL_LITERAL) { reorientCommand = new MessageAsyncReorientCommand(req); } else if(msgToReorient.getMessageSort() == MessageSort.REPLY_LITERAL) { reorientCommand = new MessageReplyReorientCommand(req); } else if(msgToReorient.getMessageSort() == MessageSort.CREATE_MESSAGE_LITERAL) { reorientCommand = new MessageCreateReorientCommand(req); } else if(msgToReorient.getMessageSort() == MessageSort.DELETE_MESSAGE_LITERAL) { // Forbid the target re-orient command of delete Message. // The re-orient command is provided but the MessageEnd update is not correctly implemented. if(req.getDirection() == ReorientRelationshipRequest.REORIENT_SOURCE) { reorientCommand = new MessageDeleteReorientCommand(req); } else if(req.getDirection() == ReorientRelationshipRequest.REORIENT_TARGET) { // Not correctly implemented - Forbid this kind of re-orient for now. reorientCommand = UnexecutableCommand.INSTANCE; } } // Build the command that will update the message end ICommand updateMessageEndCommand = null; MessageEnd msgEndToUpdate = null; if(req.getDirection() == ReorientRelationshipRequest.REORIENT_SOURCE) { msgEndToUpdate = msgToReorient.getSendEvent(); } else if(req.getDirection() == ReorientRelationshipRequest.REORIENT_TARGET) { msgEndToUpdate = msgToReorient.getReceiveEvent(); } updateMessageEndCommand = getUpdateMessageEndCommand(msgEndToUpdate, (Element)req.getOldRelationshipEnd(), (Element)req.getNewRelationshipEnd()); // Compose both commands reorientCommand = CompositeCommand.compose(reorientCommand, updateMessageEndCommand); return reorientCommand.reduce(); } /** * <pre> * This method provides a command to update the {@link MessageEnd} concerned by a re-orient request. * </pre> * * @param messageEnd * the {@link MessageEnd} concerned by the re-orient command * @param oldElement * the old {@link Element} graphically attached to the {@link Message} * @param newElement * the new {@link Element} graphically attached to the {@link Message} * @return the update command */ private ICommand getUpdateMessageEndCommand(MessageEnd messageEnd, Element oldElement, Element newElement) { ICommand updateCommand = null; if(messageEnd instanceof MessageOccurrenceSpecification) { updateCommand = getUpdateMessageOccurenceSpecificationCommand((MessageOccurrenceSpecification)messageEnd, oldElement, newElement); } else if(messageEnd instanceof Gate) { // Gate case is not currently implemented updateCommand = getUpdateGateCommand((Gate)messageEnd, oldElement, newElement); } return updateCommand; } /** * <pre> * This method provides a command to update the {@link MessageOccurrenceSpecification} concerned by a re-orient request. * </pre> * * @param messageEnd * the {@link MessageOccurrenceSpecification} concerned by the re-orient command * @param oldElement * the old {@link Element} graphically attached to the {@link Message} * @param newElement * the new {@link Element} graphically attached to the {@link Message} * @return the update command */ private ICommand getUpdateMessageOccurenceSpecificationCommand(MessageOccurrenceSpecification messageEnd, Element oldElement, Element newElement) { ICommand updateCommand = null; if(newElement instanceof Lifeline) { updateCommand = getUpdateOccurenceSpecificationCommand(messageEnd, (Lifeline)newElement); } else if(newElement instanceof ExecutionSpecification) { Lifeline lifeline = ExecutionSpecificationUtil.getExecutionSpecificationLifeline((ExecutionSpecification)newElement); if(lifeline != null) { updateCommand = getUpdateOccurenceSpecificationCommand(messageEnd, lifeline); } } return updateCommand; } /** * <pre> * This method provides a command to update the {@link OccurrenceSpecification} concerned by a re-orient request. * </pre> * * @param os * the {@link OccurrenceSpecification} concerned by the re-orient command * @param newLifeline * the new {@link Lifeline} graphically covered by the {@link OccurrenceSpecification} * @return the update command */ private ICommand getUpdateOccurenceSpecificationCommand(OccurrenceSpecification os, Lifeline newLifeline) { ICommand updateCommand = null; List<Lifeline> covereds = new ArrayList<Lifeline>(); covereds.add(newLifeline); IElementEditService provider = ElementEditServiceUtils.getCommandProvider(os); if(provider != null) { // Create a command the set the OccurenceSpecification covered EReference with the newLifeline SetRequest setCoveredRequest = new SetRequest(os, UMLPackage.eINSTANCE.getInteractionFragment_Covered(), covereds); updateCommand = provider.getEditCommand(setCoveredRequest); } return updateCommand; } /** * <pre> * This method provides a command to update the {@link Gate} concerned by a re-orient request. * * TODO : Not currently implemented. * </pre> * * @param gate * the {@link Gate} concerned by the re-orient command * @param oldElement * the old {@link Element} graphically attached to the {@link Message} * @param newElement * the new {@link Element} graphically attached to the {@link Message} * @return the update command */ private ICommand getUpdateGateCommand(Gate gate, Element oldElement, Element newElement) { return null; } }