/***************************************************************************** * 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: * Saadia Dhouib saadia.dhouib@cea.fr - adapted from composite structure diagram (DestroyGeneralizationAdvice class) * *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.communication.custom.advices; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.emf.core.util.CrossReferenceAdapter; import org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice; import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyDependentsRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest; import org.eclipse.gmf.runtime.notation.DecorationNode; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.communication.edit.parts.ModelEditPart; import org.eclipse.uml2.uml.Message; /** * The Class DestroyMessageAdvice. */ public class DestroyMessageAdvice extends AbstractEditHelperAdvice { /** * * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getBeforeEditCommand(org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest) * * @param request * @return ICommand */ @Override public ICommand getBeforeEditCommand(IEditCommandRequest request) { if(request instanceof DestroyDependentsRequest) { return getBeforeDestroyDependentsCommand((DestroyDependentsRequest)request); } return null; } /** * * @see org.eclipse.gmf.runtime.emf.type.core.edithelper.AbstractEditHelperAdvice#getBeforeDestroyDependentsCommand(org.eclipse.gmf.runtime.emf.type.core.requests.DestroyDependentsRequest) * * @param request * @return */ @Override protected ICommand getBeforeDestroyDependentsCommand(DestroyDependentsRequest request) { EObject destructee = request.getElementToDestroy(); Set<EObject> set = null; if(destructee instanceof Message) { //get all view for the destructee CrossReferenceAdapter crossReferenceAdapter = getCrossReferenceAdapter(request, destructee); if(crossReferenceAdapter != null) { Collection<Setting> revRefs = crossReferenceAdapter.getNonNavigableInverseReferences(destructee); if(!revRefs.isEmpty()) { for(Setting current : revRefs) { //test if the view is linked with the removed message if(current.getEObject() instanceof View) { View view = (View)current.getEObject(); //we remove the view only if they are owned by the CompositeStructureDiagram if(isOwnedByCommunicationDiagram(view)) { if(set == null) { set = new HashSet<EObject>(); } set.add(view); if(isLastMessageOnConnection(view)) { //remove the connector set.add((View)view.eContainer()); } } } } } } } //return the command to destroy all these views if(set != null) { return request.getDestroyDependentsCommand(set); } return null; } /** * Returns the {@link CrossReferenceAdapter} corresponding to the element to destroy * * @param request * the request * @param destructee * the destroyed element * @return * the {@link CrossReferenceAdapter} corresponding to this element */ protected CrossReferenceAdapter getCrossReferenceAdapter(DestroyDependentsRequest request, EObject destructee) { CrossReferenceAdapter crossReferenceAdapter = null; @SuppressWarnings("rawtypes") Map cacheMaps = (Map)request.getParameter("Cache_Maps");//$NON-NLS-1$ RequestCacheEntries.Cache_Maps if(cacheMaps != null) { crossReferenceAdapter = (CrossReferenceAdapter)cacheMaps.get("CrossRefAdapter");//$NON-NLS-1$ RequestCacheEntries.CrossRefAdapter } if(crossReferenceAdapter == null) { crossReferenceAdapter = CrossReferenceAdapter.getExistingCrossReferenceAdapter(destructee); if(crossReferenceAdapter == null) { TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(destructee); if(domain != null) { crossReferenceAdapter = CrossReferenceAdapter.getCrossReferenceAdapter(domain.getResourceSet()); } } } return crossReferenceAdapter; } /** * Tests if the view is owned by the CommunicationDiagram * * @param view * a view * @return * <code>true</code> if the view is owned by the CompositeStructureDiagram, <code>false</code> if not */ protected boolean isOwnedByCommunicationDiagram(View view) { EObject diagram = view.eContainer(); while(!(diagram instanceof Diagram)) { diagram = diagram.eContainer(); } String type = ((Diagram)diagram).getType(); return type == ModelEditPart.MODEL_ID; } /** * Tests if the view is is the last label (ie. message) on the connection * * @param view * a view * @return * <code>true</code> if the view is is the last label (ie. message) on the connection, <code>false</code> if not */ protected boolean isLastMessageOnConnection(View view) { //Verify if this view is the last label (ie. message) on the connection //if true remove the parent view (ie. the connector view) if(view instanceof DecorationNode) { View parentView = (View)view.eContainer(); // --------------------------------------------------------- // help to debug //System.err.println("+-> parent View :" + parentView); // --------------------------------------------------------- //get children of the parent view @SuppressWarnings("unchecked") EList<View> children = parentView.getChildren(); //Local variable messageChildren to count the number of labels ( representing a message) on the connection Integer messageChildren = 0; done: for(View child : children) { if((child instanceof DecorationNode) && (child.getElement() instanceof Message)) { messageChildren++; if(messageChildren > 1) { //System.err.println("+-> not the last message on the connection"); break done; } } } //if this is the last message on the connection, return true. return messageChildren == 1; } return false; } }