/***************************************************************************** * Copyright (c) 2011 Atos Origin. * * * 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.common.groups.edit.policies; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.UnexecutableCommand; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy; import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; 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.EditCommandRequestWrapper; import org.eclipse.gmf.runtime.diagram.ui.requests.RefreshConnectionsRequest; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.commands.EditElementCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.common.groups.commands.utlis.CommandsUtils; import org.eclipse.papyrus.uml.diagram.common.groups.core.groupcontainment.GroupContainmentRegistry; import org.eclipse.papyrus.uml.diagram.common.groups.core.utils.Utils; import org.eclipse.papyrus.uml.diagram.common.groups.groupcontainment.AbstractContainerNodeDescriptor; import org.eclipse.papyrus.uml.diagram.common.groups.utils.GroupRequestConstants; import org.eclipse.papyrus.uml.diagram.common.util.DiagramEditPartsUtil; /** * This Edit Policy applies on the compartment of a group (which hold elements by reference or containment). It enables to recover the correct model * container in * order to create the element at the right place in the model, before linking it to the referencing group. * * In order to do so, the semantic creation command, inheriting {@link EditElementCommand}, must recover the * {@link GroupRequestConstants#MODEL_CONTAINER} parameter from the request to know the model container of the created element and assign it itself. * * @author vhemery and adaussy */ public class CreateInGroupEditPolicy extends CreationEditPolicy { /** List of the IGraphicalEditPart of the graphical parents available */ private List<IGraphicalEditPart> graphicalParents; /** List of the IGraphicalEditPart of the model parents available */ private List<IGraphicalEditPart> modelParents; /** * Get the command to create a group referenced child and create it in the appropriate place. * * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy#getCreateElementAndViewCommand(org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest) * * @param request * the creation request * @return the creation command or null */ @SuppressWarnings("unchecked") @Override protected Command getCreateElementAndViewCommand(CreateViewAndElementRequest request) { CreateElementRequestAdapter requestAdapter = request.getViewAndElementDescriptor().getCreateElementRequestAdapter(); CreateElementRequest createElementRequest = (CreateElementRequest)requestAdapter.getAdapter(CreateElementRequest.class); //Needed to create transactionnal command TransactionalEditingDomain editingDomain = ((GraphicalEditPart)getHost()).getEditingDomain(); //Command in creation CompositeCommand handleChildren = null; View view = (View)getHost().getModel(); EObject hostElement = ViewUtil.resolveSemanticElement(view); if(hostElement == null && view.getElement() == null) { hostElement = view; } // Returns null if host is unresolvable so that trying to create a // new element in an unresolved shape will not be allowed. if(hostElement == null) { return null; } EditPart currentEditPart = getHost(); if(currentEditPart instanceof IGraphicalEditPart) { /* * Handling parents */ DiagramEditPart diagramPart = DiagramEditPartsUtil.getDiagramEditPart(currentEditPart); /* * Find the edit part which can be model and graphical parent of the new element */ graphicalParents = new ArrayList<IGraphicalEditPart>(); modelParents = new ArrayList<IGraphicalEditPart>(); Utils.createComputedListsOfParents(graphicalParents, modelParents, request, diagramPart, createElementRequest.getElementType().getEClass()); CommandsUtils.setRequestParentsParameters(request, graphicalParents, modelParents, getHost()); /* * If the current host is not a model parent of the element in creation then the request is send to suitable one */ Command relocatedCommand = CommandsUtils.sendRequestSuitableHost(request, createElementRequest, (IGraphicalEditPart)getHost(), modelParents); if(relocatedCommand != null) { return relocatedCommand; } /* * handling sons if the creation is a group */ Set<AbstractContainerNodeDescriptor> descriptors = GroupContainmentRegistry.getDescriptorsWithContainerEClass(createElementRequest.getElementType().getEClass()); handleChildren = CommandsUtils.getHandleChildrenCommand(descriptors, request, diagramPart, editingDomain, requestAdapter, modelParents, (IGraphicalEditPart)getHost()); /* * Request Part Creation * 1 - Create Semantic Request * 2 - Create View Request * 3 - Create Choice request (If there is any choice to make) */ Command createElementCommand = getHost().getCommand(new EditCommandRequestWrapper((CreateElementRequest)requestAdapter.getAdapter(CreateElementRequest.class), request.getExtendedData())); if(createElementCommand == null || !createElementCommand.canExecute()) { return UnexecutableCommand.INSTANCE; } /* * Create View Command */ Command viewCommand = getCreateCommand(request); /* * Refresh Connection command */ Command refreshConnectionCommand = getHost().getCommand(new RefreshConnectionsRequest(((List<?>)request.getNewObject()))); /* * create the semantic global command */ CompositeCommand semanticCommand = CommandsUtils.getSemanticCommand(requestAdapter, editingDomain, createElementRequest, createElementCommand, graphicalParents); /* * ChooseParentNotificationCommand */ CompositeCommand choiceCommand = CommandsUtils.getChooseParentNotification(editingDomain, request, graphicalParents, modelParents, (IGraphicalEditPart)getHost()); /* * form the compound command and return */ CompositeCommand cc = new CompositeCommand(semanticCommand.getLabel()); cc.compose(semanticCommand); cc.compose(new CommandProxy(viewCommand)); if(choiceCommand != null) { cc.compose(choiceCommand); } if(handleChildren != null) { cc.compose(handleChildren); } if(refreshConnectionCommand != null) { cc.compose(new CommandProxy(refreshConnectionCommand)); } return new ICommandProxy(cc); } return super.getCreateElementAndViewCommand(request); } /** * Create a request in order to handle graphic creation * * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy#getCreateCommand(org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest) * * @param request * @param getHost * @return */ @Override public Command getCreateCommand(CreateViewRequest request) { /* * Get default graphical parent */ IGraphicalEditPart newParentPart = (IGraphicalEditPart)getHost(); Object graphicalParents = request.getExtendedData().get(GroupRequestConstants.GRAPHICAL_CONTAINERS); if(graphicalParents instanceof List<?> && !((List<?>)graphicalParents).isEmpty()) { Object parentPart = ((List<?>)graphicalParents).get(0); if(parentPart instanceof IGraphicalEditPart) { newParentPart = (IGraphicalEditPart)parentPart; } } request.getExtendedData().put(CommandsUtils.GRAPHICAL_PARENT, newParentPart); View parent = (View)newParentPart.getModel(); // construct command as in super method (except parent) TransactionalEditingDomain editingDomain = ((IGraphicalEditPart)getHost()).getEditingDomain(); CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label); Iterator<? extends CreateViewRequest.ViewDescriptor> descriptors = request.getViewDescriptors().iterator(); while(descriptors.hasNext()) { CreateViewRequest.ViewDescriptor descriptor = (CreateViewRequest.ViewDescriptor)descriptors.next(); CreateCommand createCommand = new CreateCommand(editingDomain, descriptor, parent); cc.compose(createCommand); } return new ICommandProxy(cc.reduce()); } }