/*****************************************************************************
* 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.edit.policies;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
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.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
import org.eclipse.gmf.runtime.emf.type.core.IHintedType;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.AbstractExecutionSpecificationEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.CombinedFragmentEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.InteractionOperandEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.providers.UMLElementTypes;
import org.eclipse.papyrus.uml.diagram.sequence.util.OperandBoundsComputeHelper;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceRequestConstant;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceUtil;
import org.eclipse.uml2.uml.CombinedFragment;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.InteractionOperand;
import org.eclipse.uml2.uml.InteractionOperatorKind;
import org.eclipse.uml2.uml.Lifeline;
/**
* This creation policy is used to move covered interaction fragments into the interaction operand
* when creating a new combined fragment.
*
* @author mvelten
*
*/
public class CombinedFragmentCreationEditPolicy extends CreationEditPolicy {
/**
* apex updated
*/
@Override
public Command getCommand(Request request) {
Command command = super.getCommand(request);
if (request instanceof CreateUnspecifiedTypeRequest &&
command instanceof ICommandProxy) {
ICommand iCommand = ((ICommandProxy)command).getICommand();
CommandResult result = iCommand.getCommandResult();
}
return command;
}
/**
* apex updated
*
* CombinedFragment 의 생성 처리
*/
@SuppressWarnings("unchecked")
@Override
/* apex improved start */
protected Command getCreateElementAndViewCommand(CreateViewAndElementRequest request) {
Command createElementAndViewCmd = super.getCreateElementAndViewCommand(request);
if(isDerivedCombinedFragment(request.getViewAndElementDescriptor().getSemanticHint())) {
Rectangle selectionRect = getSelectionRectangle(request);
// CombinedFragment 생성 시 ExecSpec과의 교차는 무시되도록 처리
if ( selectionRect.width > 0 && selectionRect.height > 0) {
Set<InteractionFragment> ignoreInteractionFragments = new HashSet<InteractionFragment>();
EditPart targetEditPart = getTargetEditPart(request);
// 중첩 CombinedFragment 생성, 즉 다른 CF의 Operand내에서 CF 생성하는 경우
// 직접 InteractionOperandEditPart에서 ExecSpec을 추출하여 ignoreInteractionFragments 직접 추가
if ( targetEditPart instanceof InteractionOperandEditPart ) {
EObject eObj = ((InteractionOperandEditPart) targetEditPart).getNotationView().getElement();
if ( eObj instanceof InteractionOperand ) {
InteractionOperand io = (InteractionOperand)eObj;
List fragList = io.getFragments();
Iterator fragIter = fragList.iterator();
while ( fragIter.hasNext() ) {
Object obj = fragIter.next();
if ( obj instanceof ExecutionSpecification ) {
ignoreInteractionFragments.add((InteractionFragment)obj);
}
}
}
// 중첩 생성이 아닌 경우 InteractionCompartmentEditPart에서 children 추출하여 ignoreInteractionFragments 생성
} else {
List childrenList = targetEditPart.getChildren();
Iterator iter = childrenList.iterator();
while (iter.hasNext()) {
ShapeEditPart ep = (ShapeEditPart)iter.next();
EObject eObj = ep.getNotationView().getElement();
if ( eObj instanceof Lifeline ) {
Iterator iter1 = ep.getChildren().iterator();
while ( iter1.hasNext() ) {
EditPart lifelineChild = (EditPart)iter1.next();
if ( lifelineChild instanceof AbstractExecutionSpecificationEditPart ) {
ShapeEditPart sep = (ShapeEditPart)lifelineChild;
EObject eObj2 = sep.getNotationView().getElement();
ignoreInteractionFragments.add((InteractionFragment)eObj2);
}
}
}
}
}
// 생성 할 CombinedFragment가 ignoreFragments 외에 다른 요소와 겹치면 null을 return 받음
Set<InteractionFragment> coveredInteractionFragments = SequenceUtil.getCoveredInteractionFragments(selectionRect, getHost(), ignoreInteractionFragments);
request.getExtendedData().put(SequenceRequestConstant.COVERED_INTERACTIONFRAGMENTS, coveredInteractionFragments);
if (coveredInteractionFragments == null) {
return UnexecutableCommand.INSTANCE;
}
if ( targetEditPart instanceof InteractionOperandEditPart ) {
InteractionOperandEditPart ioep = (InteractionOperandEditPart)targetEditPart;
CombinedFragmentEditPart cfep = (CombinedFragmentEditPart)ioep.getParent().getParent();
CombinedFragment cf = (CombinedFragment)cfep.resolveSemanticElement();
InteractionOperatorKind ioKind = cf.getInteractionOperator();
// Operator가 복수의 Operand를 허용하는 것이 아니면
if ( InteractionOperatorKind.OPT_LITERAL.equals(ioKind)
|| InteractionOperatorKind.LOOP_LITERAL.equals(ioKind)
|| InteractionOperatorKind.BREAK_LITERAL.equals(ioKind)
|| InteractionOperatorKind.NEG_LITERAL.equals(ioKind)
) {
// UnexecutableCommand.INSTANCE 리턴해도 X 표시 되지 않음 ㅠㅜ
return UnexecutableCommand.INSTANCE;
}
}
}
// 아래는 0.9에서 추가된 로직
// Add updating bounds command for Combined fragment createment
String hint = request.getViewAndElementDescriptor().getSemanticHint();
if(OperandBoundsComputeHelper.isDerivedCombinedFragment(hint)){
if (createElementAndViewCmd instanceof ICommandProxy) {
ICommandProxy commandProxy = (ICommandProxy) createElementAndViewCmd;
ICommand realCmd = commandProxy.getICommand();
if (realCmd instanceof CompositeCommand) {
ICommand createUpdateBoundsCmd = OperandBoundsComputeHelper.createUpdateCFAndIOBoundsForCFCreationCommand(this.getHost(),request);
if (createUpdateBoundsCmd != null)
((CompositeCommand) realCmd)
.add(createUpdateBoundsCmd);
}
}
}
}
return createElementAndViewCmd;
}
/* apex improved end */
/* apex replaced
protected Command getCreateElementAndViewCommand(CreateViewAndElementRequest request) {
Command createElementAndViewCmd = super.getCreateElementAndViewCommand(request);
if(isDerivedCombinedFragment(request.getViewAndElementDescriptor().getSemanticHint())) {
Rectangle selectionRect = getSelectionRectangle(request);
Set<InteractionFragment> coveredInteractionFragments = SequenceUtil.getCoveredInteractionFragments(selectionRect, getHost(), null);
request.getExtendedData().put(SequenceRequestConstant.COVERED_INTERACTIONFRAGMENTS, coveredInteractionFragments);
// Add updating bounds command for Combined fragment createment
String hint = request.getViewAndElementDescriptor().getSemanticHint();
if(OperandBoundsComputeHelper.isDerivedCombinedFragment(hint)){
if (createElementAndViewCmd instanceof ICommandProxy) {
ICommandProxy commandProxy = (ICommandProxy) createElementAndViewCmd;
ICommand realCmd = commandProxy.getICommand();
if (realCmd instanceof CompositeCommand) {
ICommand createUpdateBoundsCmd = OperandBoundsComputeHelper.createUpdateCFAndIOBoundsForCFCreationCommand(this.getHost(),request);
if (createUpdateBoundsCmd != null)
((CompositeCommand) realCmd)
.add(createUpdateBoundsCmd);
}
}
}
}
return createElementAndViewCmd;
}
*/
@Override
protected Command getCreateCommand(CreateViewRequest request) {
Command createViewCmd = super.getCreateCommand(request);
if (createViewCmd instanceof ICommandProxy) {
ICommandProxy commandProxy = (ICommandProxy) createViewCmd;
CompositeCommand compositeCommand = null;
ICommand realCmd = commandProxy.getICommand();
if (realCmd instanceof CompositeCommand) {
compositeCommand = (CompositeCommand) realCmd;
} else {
compositeCommand = new CompositeCommand(commandProxy.getLabel());
compositeCommand.add(realCmd);
realCmd = compositeCommand;
}
for (ViewDescriptor viewDescriptor : request.getViewDescriptors()) {
String hint = viewDescriptor.getSemanticHint();
if(isDerivedCombinedFragment(hint)) {
// Add updating bounds command for Combined fragment createment
if(OperandBoundsComputeHelper.isDerivedCombinedFragment(hint)){
ICommand createUpdateBoundsCmd = OperandBoundsComputeHelper.createUpdateCFAndIOBoundsForCFCreationCommand(this.getHost(), request);
if (createUpdateBoundsCmd != null)
((CompositeCommand) realCmd)
.add(createUpdateBoundsCmd);
}
}
}
createViewCmd = new ICommandProxy(compositeCommand.reduce());
}
return createViewCmd;
}
/**
* apex updated
*
* default size 를 0,0으로 수정
*
* Retrieve the selection rectangle associated with the request.
*
* @param request
* the request
* @return
*/
private Rectangle getSelectionRectangle(CreateViewAndElementRequest request) {
Rectangle selectionRect = new Rectangle();
Point location = request.getLocation();
Dimension size = request.getSize();
if(location != null) {
selectionRect.x = location.x;
selectionRect.y = location.y;
} else {
// default values (should not be triggered)
selectionRect.x = 100;
selectionRect.y = 100;
}
if(size != null) {
selectionRect.height = size.height;
selectionRect.width = size.width;
} else {
/* apex improved start */
// hardcode 값으로 rect가 생성되어 포함 관련 문제 발생하여 0 처리
selectionRect.height = 0;
selectionRect.width = 0;
/* apex improved end */
/* apex replaced
// default values hardcoded...
selectionRect.height = 61;
selectionRect.width = 112;
*/
}
return selectionRect;
}
/**
* Check if it is a combined fragment or something similar which needs this policy to move ift in the correct container.
*
* @param hint
* the semantic hint
* @return
*/
private static boolean isDerivedCombinedFragment(String hint) {
if(((IHintedType)UMLElementTypes.InteractionOperand_3005).getSemanticHint().equals(hint)) {
return true;
}
if(((IHintedType)UMLElementTypes.CombinedFragment_3004).getSemanticHint().equals(hint)) {
return true;
}
if(((IHintedType)UMLElementTypes.ConsiderIgnoreFragment_3007).getSemanticHint().equals(hint)) {
return true;
}
return false;
}
}