/***************************************************************************** * Copyright (c) 2012 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.dnd.strategy.instancespecification.command; import java.util.List; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gmf.runtime.common.core.command.AbstractCommand; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.common.core.command.ICommand; import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest.ViewAndElementDescriptor; import org.eclipse.gmf.runtime.emf.type.core.commands.CreateElementCommand; import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.jface.window.Window; import org.eclipse.papyrus.infra.emf.utils.EMFHelper; import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.InstanceSpecificationSlotCompartmentEditPart; import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.InstanceSpecificationSlotCompartmentEditPartCN; import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.SlotEditPart; import org.eclipse.papyrus.uml.diagram.clazz.part.UMLVisualIDRegistry; import org.eclipse.papyrus.uml.diagram.clazz.providers.UMLElementTypes; import org.eclipse.papyrus.uml.diagram.dnd.strategy.instancespecification.ui.SlotSelectionDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.InstanceSpecification; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.Slot; import org.eclipse.uml2.uml.UMLPackage; import org.eclipse.uml2.uml.ValueSpecification; /** * An interactive Command to create slots in an InstanceSpecification. * A dialog will be opened for the user to select the properties he wishes * to instantiate. * * @author Camille Letavernier * */ public class SelectAndCreateSlotsCommand extends AbstractCommand { protected final List<Classifier> classifiers; protected final EditPart targetEditPart; protected final InstanceSpecification specification; public SelectAndCreateSlotsCommand(List<Classifier> classifiers, EditPart targetEditPart) { super("Create slots"); this.classifiers = classifiers; this.targetEditPart = targetEditPart; specification = (InstanceSpecification)EMFHelper.getEObject(targetEditPart); } @Override protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { //Open the dialog to select the slots SlotSelectionDialog dialog = new SlotSelectionDialog(Display.getCurrent().getActiveShell(), specification, classifiers); if(dialog.open() != Window.OK) { return CommandResult.newCancelledCommandResult(); } Object[] result = dialog.getResult(); //For each selected property, create the corresponding slot for(Object propertyObject : result) { Property property = (Property)propertyObject; //Creates the slot TransactionalEditingDomain domain = (TransactionalEditingDomain)EMFHelper.resolveEditingDomain(targetEditPart); CreateElementRequest createElementRequest = new CreateElementRequest(domain, specification, UMLElementTypes.Slot_3030); ICommand slotCreationCommand; //If the slot compartment is visible, create the slot graphically if(isSlotCompartmentAvailable(targetEditPart)) { CreateElementRequestAdapter adapter = new CreateElementRequestAdapter(createElementRequest); ViewAndElementDescriptor descriptor = new ViewAndElementDescriptor(adapter, Node.class, UMLVisualIDRegistry.getType(SlotEditPart.VISUAL_ID), ((IGraphicalEditPart)targetEditPart).getDiagramPreferencesHint()); Request createRequest = new CreateViewAndElementRequest(descriptor); Command gefCommand = targetEditPart.getCommand(createRequest); if(gefCommand instanceof ICommandProxy) { slotCreationCommand = ((ICommandProxy)gefCommand).getICommand(); slotCreationCommand = slotCreationCommand.reduce(); } else { return CommandResult.newErrorCommandResult("Impossible to create slots"); } } else { //The compartment is not visible ; only create the semantic slot slotCreationCommand = new CreateElementCommand(createElementRequest); } slotCreationCommand.execute(new NullProgressMonitor(), null); CommandResult commandResult = slotCreationCommand.getCommandResult(); if(commandResult != null) { if(!commandResult.getStatus().isOK()) { return commandResult; } } //Retrieve the created slot, and update its properties ( Slot newSlot = getNewSlot(commandResult); if(newSlot != null) { updateSlotProperties(newSlot, property); } else { return CommandResult.newErrorCommandResult("Could not create the slot for property " + property.getName()); } //Initialize properties: feature & name & default value } return CommandResult.newOKCommandResult(); } // Retrieves a slot from a CommandResult protected Slot getNewSlot(CommandResult commandResult) { Object objectResult = commandResult.getReturnValue(); if(objectResult instanceof List) { //Result of the semantic + graphical creation command List<?> listResult = (List<?>)objectResult; for(Object elementResult : listResult) { if(elementResult instanceof CreateElementRequestAdapter) { CreateElementRequest request = (CreateElementRequest)((CreateElementRequestAdapter)elementResult).getAdapter(CreateElementRequest.class); if(request != null) { EObject newElement = request.getNewElement(); if(newElement instanceof Slot) { Slot slot = (Slot)newElement; return slot; } } } } } else if(commandResult.getReturnValue() instanceof Slot) { //Result of the semantic creation command return (Slot)commandResult.getReturnValue(); } return null; } //Sets the slot's property (definingFeature) and initialize its value (property#defaultValue) protected void updateSlotProperties(Slot slot, Property property) throws ExecutionException { SetRequest setFeatureRequest = new SetRequest(slot, UMLPackage.eINSTANCE.getSlot_DefiningFeature(), property); SetValueCommand setFeatureCommand = new SetValueCommand(setFeatureRequest); setFeatureCommand.execute(new NullProgressMonitor(), null); if(property.getDefaultValue() != null) { ValueSpecification defaultValue = property.getDefaultValue(); ValueSpecification currentValue = EcoreUtil.copy(defaultValue); currentValue.setName(property.getName()); SetRequest setValueRequest = new SetRequest(slot, UMLPackage.eINSTANCE.getSlot_Value(), currentValue); SetValueCommand setValueCommand = new SetValueCommand(setValueRequest); setValueCommand.execute(new NullProgressMonitor(), null); } } //Tests whether the slot compartment edit part is available protected boolean isSlotCompartmentAvailable(EditPart targetEditPart) { if(targetEditPart instanceof InstanceSpecificationSlotCompartmentEditPart || targetEditPart instanceof InstanceSpecificationSlotCompartmentEditPartCN) { return true; } for(Object editPartObject : targetEditPart.getChildren()) { if(isSlotCompartmentAvailable((EditPart)editPartObject)) { return true; } } return false; } @Override protected CommandResult doRedoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { return null; } @Override protected CommandResult doUndoWithResult(IProgressMonitor progressMonitor, IAdaptable info) throws ExecutionException { return null; } }