/***************************************************************************** * 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.diagram.profile.custom.policies; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.draw2d.geometry.Point; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; 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.gef.requests.ChangeBoundsRequest; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.core.commands.AddCommand; import org.eclipse.gmf.runtime.diagram.core.commands.DeleteCommand; 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.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.GroupEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.LabelEditPart; 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.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.common.util.DiagramEditPartsUtil; import org.eclipse.papyrus.uml.diagram.profile.custom.commands.CustomMetaClassCreateCommand; import org.eclipse.papyrus.uml.diagram.profile.custom.commands.CustomSemanticCreateCommand; import org.eclipse.papyrus.uml.diagram.profile.custom.helper.MetaclassHelper; import org.eclipse.papyrus.uml.diagram.profile.custom.requests.CustomCreateElementRequestAdapter; import org.eclipse.papyrus.uml.diagram.profile.custom.requests.CustomCreateViewAndElementRequest; import org.eclipse.papyrus.uml.diagram.profile.custom.requests.CustomCreateViewAndElementRequest.ViewAndElementDescriptor; import org.eclipse.papyrus.uml.diagram.profile.custom.requests.CustomCreateViewRequest; import org.eclipse.papyrus.uml.diagram.profile.edit.parts.MetaclassEditPart; import org.eclipse.papyrus.uml.diagram.profile.edit.parts.MetaclassEditPartCN; import org.eclipse.papyrus.uml.diagram.profile.edit.parts.ProfileDiagramEditPart; import org.eclipse.papyrus.uml.diagram.profile.edit.parts.ProfilePackageableElementCompartmentEditPartCN; import org.eclipse.papyrus.uml.diagram.profile.edit.parts.ProfilePackageableElementCompartmentEditPartTN; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.ElementImport; import org.eclipse.uml2.uml.Profile; /** * This class provides a custom creation for the metaclass element. * It's needed because with the class creation view, the UMLViewProvider doesn't find the good superClass to create it. * (Class and Metaclass are represented by an uml class both and it's a probleme for GMF) * * * */ public class CustomCreationRoleEditPolicy extends org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy { /** * the IDs of the metaclasses */ private int[] metaclassesEP_ID = { MetaclassEditPart.VISUAL_ID, MetaclassEditPartCN.VISUAL_ID }; /** * list the metaclasses EditPart */ private ArrayList<String> metaclassesEP_ID_List = new ArrayList<String>(); /** * the requestAdapterList */ private ArrayList<CreateElementRequestAdapter> requestAdapterList; /** * * Constructor. * */ public CustomCreationRoleEditPolicy() { super(); init(this.metaclassesEP_ID); this.requestAdapterList = new ArrayList<CreateElementRequestAdapter>(); } /** * * @param metaclassesID */ private void init(int[] metaclassesID) { for(int i = 0; i < metaclassesID.length; i++) { this.metaclassesEP_ID_List.add(new String(new Integer(metaclassesID[i]).toString())); } } /** * custom method for the creation of metaclass element * * * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy#getCreateElementAndViewCommand(org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest) * * @param request * @return */ @Override protected Command getCreateElementAndViewCommand(CreateViewAndElementRequest request) { //we test if it's a command to create a metaclass if(!(this.metaclassesEP_ID_List.contains((request).getViewDescriptors().get(0).getSemanticHint()))) { return super.getCreateElementAndViewCommand(request); } // get the element descriptor CreateElementRequestAdapter requestAdapter = request.getViewAndElementDescriptor().getCreateElementRequestAdapter(); /** * We create our own request! */ CustomCreateElementRequestAdapter customRequestAdapter = new CustomCreateElementRequestAdapter((CreateElementRequest)requestAdapter.getAdapter(CreateElementRequest.class)); CustomCreateViewAndElementRequest.ViewAndElementDescriptor viewDescriptor = new ViewAndElementDescriptor(customRequestAdapter, request.getViewDescriptors().get(0).getViewKind(), request.getViewDescriptors().get(0).getSemanticHint(), request.getViewDescriptors().get(0).getPreferencesHint()); CustomCreateViewAndElementRequest requestNEW = new CustomCreateViewAndElementRequest(viewDescriptor); requestNEW.setExtendedData(request.getExtendedData()); requestNEW.setLocation(request.getLocation()); // get the semantic request CreateElementRequest createElementRequest = (CreateElementRequest)customRequestAdapter.getAdapter(CreateElementRequest.class, 0); //createElementRequest = customCreateElementRequest; if(createElementRequest.getContainer() == null) { // complete the semantic request by filling in the host's semantic // element as the context 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; } createElementRequest.setContainer(hostElement); } // get the create element command based on the elementdescriptor's // request //Command createElementCommand = getHost().getCommand(new EditCommandRequestWrapper((CreateElementRequest)requestAdapter.getAdapter(CreateElementRequest.class), request.getExtendedData())); Command createElementCommand = getHost().getCommand(new EditCommandRequestWrapper((CreateElementRequest)customRequestAdapter.getAdapter(CreateElementRequest.class, 0), request.getExtendedData())); if(createElementCommand == null) { return UnexecutableCommand.INSTANCE; } if(!createElementCommand.canExecute()) { return createElementCommand; } // create the semantic create wrapper command Profile profile = (Profile)createElementRequest.getContainer(); /** * We use our custom command */ TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(profile); CustomSemanticCreateCommand semanticCommand = new CustomSemanticCreateCommand(domain, customRequestAdapter, profile); Command viewCommand = getCreateCommand(requestNEW); //Command refreshConnectionCommand = getHost().getCommand(new RefreshConnectionsRequest(((List)request.getNewObject()))); // form the compound command and return CompositeCommand cc = new CompositeCommand(semanticCommand.getLabel()); cc.compose(semanticCommand); cc.compose(new CommandProxy(viewCommand)); // if(refreshConnectionCommand != null) { // cc.compose(new CommandProxy(refreshConnectionCommand)); // } return new ICommandProxy(cc); } /** * custom method for the CreateViewAndElementRequest (if it's a metaclass) * * @see org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy#getCommand(org.eclipse.gef.Request) * * @param request * @return */ @Override public Command getCommand(Request request) { if(understandsRequest(request)) { if(request instanceof CreateViewAndElementRequest) { if(this.metaclassesEP_ID_List.contains(((CreateViewAndElementRequest)request).getViewDescriptors().get(0).getSemanticHint())) { //get the correct location for the new metaclass Point location = ((CreateViewAndElementRequest)request).getLocation().getCopy(); ((GraphicalEditPart)getHost()).getContentPane().translateToRelative(location); ((GraphicalEditPart)getHost()).getContentPane().translateFromParent(location); location.translate(((GraphicalEditPart)getHost()).getContentPane().getClientArea().getLocation().getNegated()); ((CreateViewAndElementRequest)request).setLocation(location); return getCreateElementAndViewCommand((CreateViewAndElementRequest)request); } } return super.getCommand(request); } return null; } /** * custom method for the metaclass element * * Called in response to a <tt>REQ_CREATE</tt> request. * * Creates a compound command and populated with the following commands for * each element to be created: <BR> * <OL> * <LI>a {@link CreateCommand}for each of the request's view descriptor. * </OL> * * @param request * a create request (understands instances of {@link CreateViewRequest}). * @param metaclasses * @return a command to satisfy the request; <tt>null</tt> if the request * is not understood. */ private Command getCreateCommand(CustomCreateViewAndElementRequest request) { TransactionalEditingDomain editingDomain = ((IGraphicalEditPart)getHost()).getEditingDomain(); CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label); Iterator descriptors = request.getViewDescriptors().iterator(); while(descriptors.hasNext()) { CustomCreateViewRequest.ViewDescriptor descriptorNEW = (CustomCreateViewRequest.ViewDescriptor)descriptors.next(); CustomMetaClassCreateCommand createCommand = new CustomMetaClassCreateCommand(editingDomain, descriptorNEW, (View)(getHost().getModel()), request.getLocation()); cc.compose(createCommand); } return new ICommandProxy(cc.reduce()); } /** Return a command to reparent both the semantic and view elements. */ /** * return a command to reparent both the semantic and view elements. * * @param request * the request * @return command */ @Override protected Command getReparentCommand(ChangeBoundsRequest request) { Iterator editParts = request.getEditParts().iterator(); View container = (View)getHost().getAdapter(View.class); EObject context = container == null ? null : ViewUtil.resolveSemanticElement(container); CompositeCommand cc = new CompositeCommand(DiagramUIMessages.AddCommand_Label); while(editParts.hasNext()) { EditPart ep = (EditPart)editParts.next(); if(ep instanceof LabelEditPart) { continue; } if(ep instanceof GroupEditPart) { cc.compose(getReparentGroupCommand((GroupEditPart)ep)); } View view = (View)ep.getAdapter(View.class); if(view == null) { continue; } EObject semantic = ViewUtil.resolveSemanticElement(view); if(semantic == null) { cc.compose(getReparentViewCommand((IGraphicalEditPart)ep)); } else if(context != null && shouldReparent(semantic, context)) { cc.compose(getReparentCommand((IGraphicalEditPart)ep)); } } return cc.isEmpty() ? null : new ICommandProxy(cc.reduce()); } /** * Return the command to reparent the supplied editpart's semantic and notation * elements. * * @param gep * the editpart being reparented * @return A CompositeCommand2 that will reparent both the semantic and notation elements. */ @Override protected ICommand getReparentCommand(IGraphicalEditPart gep) { if(!(gep instanceof MetaclassEditPart) && !(gep instanceof MetaclassEditPartCN)) { return super.getReparentCommand(gep); } if(!(getHost() instanceof ProfilePackageableElementCompartmentEditPartTN) && !(getHost() instanceof ProfilePackageableElementCompartmentEditPartCN) && !(getHost() instanceof ProfileDiagramEditPart)) { return org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand.INSTANCE; } CompositeCommand cc = new CompositeCommand(DiagramUIMessages.AddCommand_Label); View container = (View)getHost().getModel(); EObject context = ViewUtil.resolveSemanticElement(container); View view = (View)gep.getModel(); EObject element = ViewUtil.resolveSemanticElement(view); TransactionalEditingDomain editingDomain = ((IGraphicalEditPart)getHost()).getEditingDomain(); String qName = null; EditPart parent = gep.getParent(); EditPart profileEP = null; // Profile parentProfile = null; //TODO : faire une fonction! //ce code est d�j� utilis� dans CustomMetaclassItemSemanticEditPolicy (et p� aussi ailleurs encore) /** * Obtain the parent profile */ Profile parentProfile = MetaclassHelper.getParentProfile(gep.getParent()); EObject elementToMove = gep.getPrimaryView().getElement(); if(elementToMove instanceof Class) { qName = ((Class)elementToMove).getQualifiedName(); } EList<ElementImport> elements = parentProfile.getElementImports(); for(ElementImport elementImport : elements) { if(elementImport.getImportedElement().getQualifiedName().equals(qName)) { element = elementImport; break; } } cc.compose(getReparentViewCommand(gep)); return cc; } /** * Return the command to reparent the supplied editpart's view only. * * @param gep * the editpart being reparented * @return A command to reparent the notation element. */ @Override protected ICommand getReparentViewCommand(IGraphicalEditPart gep) { if(!(gep instanceof MetaclassEditPart) && !(gep instanceof MetaclassEditPartCN)) { return super.getReparentViewCommand(gep); } CompositeCommand deleteViewCmd = new CompositeCommand("Reparent one metaclass view and delete the others"); //$NON-NLS-1$ /* * If a metaclass (ElementImport) has dropped many times, we need to reparent the selected view and delete the others! * * The RemoveOrphanViewEditPolicy can't make it, because it runs too early and short-circuits the AddCommand */ /** * 1/ get the element * */ View metaclassView = (View)gep.getModel(); EObject element = metaclassView.getElement(); /** * 2/ get all views for this element view */ List<View> elementViews = DiagramEditPartsUtil.getEObjectViews(element); /** * 3/ delete all the view excepted one */ for(View view : elementViews) { if(view != metaclassView) { deleteViewCmd.add(new DeleteCommand(gep.getEditingDomain(), view)); } } View parent = (View)getHost().getModel(); deleteViewCmd.add(new AddCommand(gep.getEditingDomain(), new EObjectAdapter(parent), new EObjectAdapter(metaclassView))); return deleteViewCmd; } }