/*****************************************************************************
* 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:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.service.types.helper.advice;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
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.DestroyElementRequest;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyReferenceRequest;
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.uml2.uml.Collaboration;
import org.eclipse.uml2.uml.CollaborationUse;
import org.eclipse.uml2.uml.ConnectableElement;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.UMLPackage;
/**
* Helper advice for all {@link Collaboration} elements.
*/
public class CollaborationHelperAdvice extends AbstractEditHelperAdvice {
/**
* {@inheritDoc}
*/
@Override
protected ICommand getBeforeDestroyDependentsCommand(DestroyDependentsRequest request) {
List<EObject> dependentsToDestroy = new ArrayList<EObject>();
Collaboration collaboration = (Collaboration)request.getElementToDestroy();
dependentsToDestroy.addAll(getRelatedRoleBindings(collaboration, null));
// return command to destroy dependents
if(!dependentsToDestroy.isEmpty()) {
return request.getDestroyDependentsCommand(dependentsToDestroy);
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
protected ICommand getBeforeDestroyReferenceCommand(DestroyReferenceRequest request) {
ICommand gmfCommand = null;
EObject elementToEdit = request.getContainer();
// Test if current destroy reference is removing a Role from Collaboration role, and destroy related role bindings
if((elementToEdit instanceof Collaboration) && (request.getContainingFeature() == UMLPackage.eINSTANCE.getCollaboration_CollaborationRole())) {
Collaboration collaboration = (Collaboration)elementToEdit;
// Parse relatedBindings
Iterator<Dependency> bindingsIt = getRelatedRoleBindings(collaboration, (ConnectableElement)request.getReferencedObject()).iterator();
while(bindingsIt.hasNext()) {
Dependency binding = bindingsIt.next();
IElementEditService provider = ElementEditServiceUtils.getCommandProvider(binding.eContainer());
if(provider != null) {
// Retrieve delete command from the Element Edit service
DestroyElementRequest req = new DestroyElementRequest(binding, false);
ICommand deleteCommand = provider.getEditCommand(req);
// Add current EObject destroy command to the global command
gmfCommand = CompositeCommand.compose(gmfCommand, deleteCommand);
}
}
}
if(gmfCommand != null) {
gmfCommand = gmfCommand.reduce();
}
return gmfCommand;
}
/**
* {@inheritDoc}
*/
@Override
protected ICommand getBeforeSetCommand(SetRequest request) {
ICommand gmfCommand = null;
EObject elementToEdit = request.getElementToEdit();
// Test if current destroy reference is removing a Role from Collaboration role, and destroy related role bindings
if((elementToEdit instanceof Collaboration) && (request.getFeature() == UMLPackage.eINSTANCE.getCollaboration_CollaborationRole())) {
Collaboration collaboration = (Collaboration)elementToEdit;
// Parse removed roles and find related RoleBindings that need to be deleted
Set<ConnectableElement> deletedRoles = new HashSet<ConnectableElement>();
deletedRoles.addAll(collaboration.getRoles());
if(request.getValue() instanceof ConnectableElement) {
deletedRoles.remove((ConnectableElement)request.getValue());
} else if(request.getValue() instanceof List<?>) {
deletedRoles.removeAll((List<?>)request.getValue());
}
// Parse roles and create deletion command for related bindings
Iterator<ConnectableElement> it = deletedRoles.iterator();
while(it.hasNext()) {
ConnectableElement role = it.next();
// Parse relatedBindings
Iterator<Dependency> bindingsIt = getRelatedRoleBindings(collaboration, role).iterator();
while(bindingsIt.hasNext()) {
Dependency binding = bindingsIt.next();
IElementEditService provider = ElementEditServiceUtils.getCommandProvider(binding.eContainer());
if(provider != null) {
// Retrieve delete command from the Element Edit service
DestroyElementRequest req = new DestroyElementRequest(binding, false);
ICommand deleteCommand = provider.getEditCommand(req);
// Add current EObject destroy command to the global command
gmfCommand = CompositeCommand.compose(gmfCommand, deleteCommand);
}
}
}
}
if(gmfCommand != null) {
gmfCommand = gmfCommand.reduce();
}
return gmfCommand;
}
/**
* <pre>
* This method retrieve all the role bindings related to a specific role.
* </pre>
*
* @param collaboration
* the {@link Collaboration} owning the role
* @param role
* the role (if null, all roles are considered)
* @return role bindings connecting the role
*/
private Set<Dependency> getRelatedRoleBindings(Collaboration collaboration, ConnectableElement role) {
Set<Dependency> roleBindings = new HashSet<Dependency>();
EReference[] ref = { UMLPackage.eINSTANCE.getCollaborationUse_Type() };
Collection<?> refs = EMFCoreUtil.getReferencers(collaboration, ref);
Iterator<?> it = refs.iterator();
while(it.hasNext()) {
Object object = it.next();
if(object instanceof CollaborationUse) {
CollaborationUse collaborationUse = (CollaborationUse)object;
Iterator<Dependency> itBindings = collaborationUse.getRoleBindings().iterator();
while(itBindings.hasNext()) {
Dependency roleBinding = itBindings.next();
if((role == null) || (roleBinding.getClients().contains(role))) {
roleBindings.add(roleBinding);
}
}
}
}
return roleBindings;
}
}