| /***************************************************************************** |
| * Copyright (c) 2019 CEA LIST. |
| * |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Xavier Le Pallec (for CEA LIST) xlepallec@lilo.org - Bug 558456 |
| * |
| *****************************************************************************/ |
| |
| package org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.mapping.js2java; |
| |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.emf.common.command.Command; |
| import org.eclipse.emf.transaction.RecordingCommand; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.gmf.runtime.notation.View; |
| import org.eclipse.papyrus.infra.core.services.ServiceException; |
| import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; |
| import org.eclipse.papyrus.infra.gmfdiag.common.editpart.ResizeableListCompartmentEditPart; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassAttributeCompartmentEditPart; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassAttributeCompartmentEditPartCN; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassOperationCompartmentEditPart; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassOperationCompartmentEditPartCN; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.OperationForClassEditPart; |
| import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.PropertyForClassEditPart; |
| import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.Activator; |
| import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.mapping.jsonstructures.JsonUmlClass; |
| import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.mapping.jsonstructures.JsonUmlOperation; |
| import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.mapping.jsonstructures.JsonUmlProperty; |
| import org.eclipse.papyrus.uml.diagram.clazz.lf.classtextualedition.messages.Messages; |
| //import org.eclipse.papyrus.uml.diagram.clazz.edit.parts.ClassEditPart; |
| import org.eclipse.papyrus.uml.diagram.common.editparts.ClassEditPart; |
| import org.eclipse.uml2.uml.Operation; |
| import org.eclipse.uml2.uml.Property; |
| |
| /** |
| * This class aims at fulfilling the class edit part according to a textual |
| * definition of a class (UmlClass) with cascading actions for properties and |
| * operations.<BR> |
| * It has to add new properties/operations and removing previous existing ones |
| * that do not appear in the textual definition anymore. That's the reason there |
| * are a lot of java attributes: to memorize previous existing elements. |
| * |
| */ |
| public class JsonUmlClassToEditPart { |
| |
| private static final Activator LOGGER = Activator.getDefault(); |
| |
| private JsonUmlClass theClass; |
| private ClassEditPart editPart; |
| private org.eclipse.uml2.uml.Class papyrusUmlClass; |
| private TransactionalEditingDomain editingDomain; |
| private ResizeableListCompartmentEditPart attributeCompartment; |
| private ResizeableListCompartmentEditPart operationCompartment; |
| private Map<String, org.eclipse.uml2.uml.Property> properties; |
| private Map<String, PropertyForClassEditPart> propertyEditParts; |
| private Map<String, OperationForClassEditPart> operationEditParts; |
| private Map<String, org.eclipse.uml2.uml.Operation> operations; |
| |
| /** |
| * This constructor takes a textual definition (UmlClass) and a Papyrus Class |
| * (referenced by the class edit part).<BR> |
| * The constructor creates all the structures to remember the state of the class |
| * before the edition.<BR> |
| * Finally the constructor launches all the process: fetch previous existing |
| * element and the mapping (replacing/adding/removing). |
| * |
| * @param theClass |
| * textual definition. |
| * @param editPart |
| * a Papyrus Class (GEF-level) |
| */ |
| public JsonUmlClassToEditPart(JsonUmlClass theClass, ClassEditPart editPart) { |
| super(); |
| try { |
| this.editPart = editPart; |
| this.theClass = theClass; |
| this.properties = new HashMap<>(); |
| this.propertyEditParts = new HashMap<>(); |
| this.operations = new HashMap<>(); |
| this.operationEditParts = new HashMap<>(); |
| |
| fetchPapyrusUmlElements(); |
| updatePapyrusUmlClassAccordingTextualVersion(); |
| } catch (Exception ex) { |
| LOGGER.logError(ex.toString(), ex); |
| } |
| } |
| |
| /** |
| * Load all the elements of the Papyrus class (the update is not done yet). This |
| * method calls the other fetch methods. |
| */ |
| private void fetchPapyrusUmlElements() { |
| |
| if (this.editPart.getModel() instanceof View) { |
| |
| View model = View.class.cast(this.editPart.getModel()); |
| |
| if (model.getElement() instanceof org.eclipse.uml2.uml.Class) { |
| |
| this.papyrusUmlClass = org.eclipse.uml2.uml.Class.class.cast(model.getElement()); |
| |
| List<?> children = editPart.getChildren(); |
| for (Object child : children) { |
| if (child instanceof ClassAttributeCompartmentEditPart || child instanceof ClassAttributeCompartmentEditPartCN) { |
| this.attributeCompartment = ResizeableListCompartmentEditPart.class.cast(child); |
| fetchAllAttributes(); |
| } else if (child instanceof ClassOperationCompartmentEditPart || child instanceof ClassOperationCompartmentEditPartCN) { |
| this.operationCompartment = ResizeableListCompartmentEditPart.class.cast(child); |
| fetchAllOperations(); |
| } |
| } |
| |
| try { |
| this.editingDomain = ServiceUtilsForEObject.getInstance() |
| .getTransactionalEditingDomain(papyrusUmlClass); |
| } catch (ServiceException ex) { |
| LOGGER.logError(ex.toString(), ex); |
| } |
| } else { |
| LOGGER.logCastProblem("model.getElement()", org.eclipse.uml2.uml.Class.class); //$NON-NLS-1$ |
| } |
| } else { |
| LOGGER.logCastProblem("editPart.getModel()", View.class); //$NON-NLS-1$ |
| } |
| |
| } |
| |
| /** |
| * This methods create a global command encapsulating the commands for updating |
| * the name, the properties and the operations. It calls the process* methods. |
| */ |
| private void updatePapyrusUmlClassAccordingTextualVersion() { |
| |
| Command globalCommand = createGlobalCommand(); |
| if (!theClass.getName().equals(papyrusUmlClass.getName())) { |
| globalCommand = globalCommand.chain(commandForSettingName()); |
| } |
| globalCommand = processProperties(globalCommand); |
| globalCommand = processOperations(globalCommand); |
| |
| editingDomain.getCommandStack().execute(globalCommand); |
| |
| } |
| |
| /** |
| * This method creates an empty command that will be used to give a name to the |
| * global command. |
| * |
| * @return the empty/naming command. |
| */ |
| private RecordingCommand createGlobalCommand() { |
| |
| return new RecordingCommand(editingDomain, Messages.JsonUmlClassToEditPart_TextualEditionOf_TitleCommand + this.papyrusUmlClass.getName()) { |
| @Override |
| protected void doExecute() { |
| // no actions to perform |
| // it's just a command to give a name to the global command. |
| } |
| }; |
| } |
| |
| /** |
| * This method creates a command to updating/setting the name of the class. |
| * |
| * @return the naming command. |
| */ |
| private Command commandForSettingName() { |
| return new RecordingCommand(editingDomain, Messages.JsonUmlClassToEditPart_SetNameCommand_TitleCommand) { |
| @Override |
| protected void doExecute() { |
| papyrusUmlClass.setName(theClass.getName()); |
| } |
| }; |
| } |
| |
| /** |
| * This method call {@link JsonUmlClassToEditPart#fetchAttribute(Object)} for each |
| * attribute in the properties compartment. |
| */ |
| private void fetchAllAttributes() { |
| for (Object child : attributeCompartment.getChildren()) { |
| if (child instanceof PropertyForClassEditPart) { |
| fetchAttribute(PropertyForClassEditPart.class.cast(child)); |
| } |
| } |
| } |
| |
| /** |
| * This method call {@link JsonUmlClassToEditPart#fetchOperation(Object)} for each |
| * operation in the operations compartment. |
| */ |
| private void fetchAllOperations() { |
| for (Object child : operationCompartment.getChildren()) { |
| if (child instanceof OperationForClassEditPart) { |
| fetchOperation(OperationForClassEditPart.class.cast(child)); |
| } |
| } |
| } |
| |
| /** |
| * This method gets real property and its associated element (edit part and the |
| * notation element) and stores them in the corresponding maps. |
| * |
| * @param child |
| * the property edit part |
| */ |
| private void fetchAttribute(PropertyForClassEditPart propertyEditPart) { |
| if (propertyEditPart.getModel() instanceof View) { |
| View visualStuff = View.class.cast(propertyEditPart.getModel()); |
| if (visualStuff.getElement() instanceof Property) { |
| Property property = Property.class.cast(visualStuff.getElement()); |
| |
| this.propertyEditParts.put(property.getName(), propertyEditPart); |
| this.properties.put(property.getName(), property); |
| } else { |
| LOGGER.logCastProblem("visualStuff.getElement()", Property.class); //$NON-NLS-1$ |
| } |
| } else { |
| LOGGER.logCastProblem("propertyEditPart.getModel()", View.class); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * This method gets real operation and its associated element (edit part and the |
| * notation element) and stores them in the corresponding maps. |
| * |
| * @param child |
| * the operation edit part |
| */ |
| private void fetchOperation(OperationForClassEditPart operationEditPart) { |
| if (operationEditPart.getModel() instanceof View) { |
| View visualStuff = View.class.cast(operationEditPart.getModel()); |
| if (visualStuff.getElement() instanceof Operation) { |
| Operation operation = (Operation) visualStuff.getElement(); |
| |
| this.operationEditParts.put(operation.getName(), operationEditPart); |
| this.operations.put(operation.getName(), operation); |
| } else { |
| LOGGER.logCastProblem("visualStuff.getElement()", Operation.class); //$NON-NLS-1$ |
| } |
| } else { |
| LOGGER.logCastProblem("operationEditPart.getModel()", View.class); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Get the list of the real properties found in the class edit part. |
| * |
| * @return list of the real properties |
| */ |
| private Property[] getAllAttributes() { |
| return this.properties.values().toArray(new Property[0]); |
| } |
| |
| /** |
| * Get the list of the real operations found in the class edit part. |
| * |
| * @return list of the real operations |
| */ |
| private Operation[] getAllOperations() { |
| return this.operations.values().toArray(new Operation[0]); |
| } |
| |
| /** |
| * This method updates the properties.<BR> |
| * First, for each property in the textual definition of the class, it looks if |
| * a property in the papyrus class exists with the same name. If it is, it |
| * updates it and removes it from the list of properties to actually remove. If |
| * not, it creates a new property.<BR> |
| * Second, all the existing properties that have not been "met" are removed. |
| * |
| * @param globalCommand |
| * the global command on which all the properties edition |
| * commands will be chained with. |
| * @return the new global command. |
| */ |
| private Command processProperties(Command globalCommand) { |
| try { |
| |
| for (JsonUmlProperty property : theClass.getProperties()) { |
| Property papyrusProperty = properties.get(property.getName()); |
| if (papyrusProperty != null) { |
| globalCommand = globalCommand |
| .chain(ToEditPartFactory.getInstance().createJsonUmlPropertyToEditPart(editingDomain, editPart, attributeCompartment) |
| .commandForUpdatingProperty(property, papyrusProperty)); |
| |
| properties.remove(property.getName(), papyrusProperty); |
| } else { |
| globalCommand = globalCommand |
| .chain(ToEditPartFactory.getInstance().createJsonUmlPropertyToEditPart(editingDomain, editPart, attributeCompartment) |
| .commandForAddingProperty(property)); |
| } |
| } |
| for (Property papyrusProperty : getAllAttributes()) { |
| globalCommand = globalCommand |
| .chain(ToEditPartFactory.getInstance().createJsonUmlPropertyToEditPart(editingDomain, editPart, attributeCompartment) |
| .commandForRemovingProperty(propertyEditParts, papyrusProperty)); |
| } |
| } catch (Exception ex) { |
| LOGGER.logError(ex.toString(), ex); |
| } |
| return globalCommand; |
| } |
| |
| /** |
| * This method updates the operations.<BR> |
| * First, for each operation in the textual definition of the class, it looks if |
| * an operation in the papyrus class exists with the same name. If it is, it |
| * updates it and removes it from the list of properties to actually remove. If |
| * not, it creates a new operation.<BR> |
| * Second, all the existing operations that have not been "met" are removed. |
| * |
| * @param globalCommand |
| * the global command on which all the operations edition |
| * commands will be chained with. |
| * @return the new global command. |
| */ |
| private Command processOperations(Command globalCommand) { |
| try { |
| for (JsonUmlOperation operation : theClass.getOperations()) { |
| Operation papyrusOperation = operations.get(operation.getName()); |
| if (papyrusOperation != null) { |
| globalCommand = globalCommand |
| .chain(ToEditPartFactory.getInstance().createJsonUmlOperationToEditPart(editingDomain, editPart, operationCompartment) |
| .commandForUpdatingOperation(operation, papyrusOperation)); |
| operations.remove(operation.getName(), papyrusOperation); |
| } else { |
| globalCommand = globalCommand |
| .chain(ToEditPartFactory.getInstance().createJsonUmlOperationToEditPart(editingDomain, editPart, operationCompartment) |
| .commandForAddingOperation(operation)); |
| } |
| } |
| for (Operation papyrusOperation : getAllOperations()) { |
| globalCommand = globalCommand |
| .chain(ToEditPartFactory.getInstance().createJsonUmlOperationToEditPart(editingDomain, editPart, operationCompartment) |
| .commandForRemovingOperation(operationEditParts, papyrusOperation)); |
| } |
| } catch (Exception ex) { |
| LOGGER.logError(ex.toString(), ex); |
| } |
| return globalCommand; |
| } |
| |
| } |