| /***************************************************************************** |
| * Copyright (c) 2019 CEA LIST, and others. |
| * |
| * 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: |
| * Nicolas FAUVERGUE (CEA LIST) nicolas.fauvergue@cea.fr - Initial API and implementation |
| * |
| *****************************************************************************/ |
| |
| package org.eclipse.papyrus.interoperability.sysml16.sysml14.xmi.helper; |
| |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import org.eclipse.emf.ecore.EAnnotation; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl; |
| import org.eclipse.emf.ecore.xmi.XMIResource; |
| import org.eclipse.gmf.runtime.notation.Bendpoints; |
| import org.eclipse.gmf.runtime.notation.Bounds; |
| import org.eclipse.gmf.runtime.notation.Connector; |
| import org.eclipse.gmf.runtime.notation.DecorationNode; |
| import org.eclipse.gmf.runtime.notation.Diagram; |
| import org.eclipse.gmf.runtime.notation.IdentityAnchor; |
| import org.eclipse.gmf.runtime.notation.Location; |
| import org.eclipse.gmf.runtime.notation.Shape; |
| import org.eclipse.gmf.runtime.notation.StringValueStyle; |
| import org.eclipse.gmf.runtime.notation.Style; |
| import org.eclipse.papyrus.infra.viewpoints.style.PapyrusViewStyle; |
| |
| /** |
| * This class defines the needed methods to preserve or create the Notation XMI identifiers. |
| */ |
| @SuppressWarnings("deprecation") |
| public class NotationXMIIDHelper { |
| |
| /** |
| * The diagram compatibility version identifier. |
| */ |
| private static final String DIAGRAM_COMPATIBILITY_VERSION = "diagram_compatibility_version"; //$NON-NLS-1$ |
| |
| /** |
| * The Bendpoints identifier. |
| */ |
| private static final String BENDPOINTS = "bendpoints"; //$NON-NLS-1$ |
| |
| /** |
| * The Bounds identifier. |
| */ |
| private static final String BOUNDS = "bounds"; //$NON-NLS-1$ |
| |
| /** |
| * The Connector identifier. |
| */ |
| private static final String CONNECTOR = "connector"; //$NON-NLS-1$ |
| |
| /** |
| * The IdentityAnchor identifier. |
| */ |
| private static final String IDENTITY_ANCHOR = "identityAnchor"; //$NON-NLS-1$ |
| |
| /** |
| * The Location identifier. |
| */ |
| private static final String LOCATION = "location"; //$NON-NLS-1$ |
| |
| /** |
| * The PapyrusViewStyle identifier. |
| */ |
| private static final String PAPYRUS_VIEW_STYLE = "papyrusViewStyle"; //$NON-NLS-1$ |
| |
| /** |
| * The Shape identifier. |
| */ |
| private static final String SHAPE = "shape"; //$NON-NLS-1$ |
| |
| /** |
| * The 'from' separator in identifier. |
| */ |
| private static final String FROM = "_from_"; //$NON-NLS-1$ |
| |
| /** |
| * The 'Of' separator in identifier. |
| */ |
| private static final String OF = "_Of_"; //$NON-NLS-1$ |
| |
| /** |
| * The 'to' separator in identifier. |
| */ |
| private static final String TO = "_to_"; //$NON-NLS-1$ |
| |
| /** |
| * The underscore separator. |
| */ |
| private static final String UNDERSCORE = "_"; //$NON-NLS-1$ |
| |
| /** |
| * This allows to calculate the identifiers of created Notation elements. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param current |
| * The object to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateNeededId(final XMIResource res, final Object current, final Map<EObject, String> oldIds) { |
| if (current instanceof DecorationNode) { |
| calculateDecorationNode(res, (DecorationNode) current, oldIds); |
| } else if (current instanceof Diagram) { |
| calculateDiagram(res, (Diagram) current, oldIds); |
| } else if (current instanceof Style) { |
| calculateStyle(res, (Style) current, oldIds); |
| } else if (current instanceof Bounds) { |
| calculateBounds(res, (Bounds) current, oldIds); |
| } else if (current instanceof Location) { |
| calculateLocation(res, (Location) current, oldIds); |
| } else if (current instanceof EAnnotation) { |
| calculateEAnnotation(res, (EAnnotation) current, oldIds); |
| } else if (current instanceof Bendpoints) { |
| calculateBendpoints(res, (Bendpoints) current, oldIds); |
| } else if (current instanceof IdentityAnchor) { |
| calculateIdentityAnchor(res, (IdentityAnchor) current, oldIds); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created DecorationNode. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param decorationNode |
| * The DecorationNode to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateDecorationNode(final XMIResource res, final DecorationNode decorationNode, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(decorationNode)) { |
| final String containerID = ((XMIResource) decorationNode.eContainer().eResource()).getID(decorationNode.eContainer()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(decorationNode.getType()); |
| stringBuilder.append(OF); |
| stringBuilder.append(containerID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(decorationNode, stringBuilder.toString()); |
| oldIds.put(decorationNode, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of converted Diagram. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param diagram |
| * The Diagram to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateDiagram(final XMIResource res, final Diagram diagram, final Map<EObject, String> oldIds) { |
| StringValueStyle compatibilityVersion = null; |
| Set<PapyrusViewStyle> papyrusViewStyles = new HashSet<>(); |
| |
| @SuppressWarnings("unchecked") |
| final Iterator<EObject> styles = diagram.getStyles().iterator(); |
| while (styles.hasNext()) { |
| final EObject style = styles.next(); |
| if (style instanceof PapyrusViewStyle) { |
| papyrusViewStyles.add((PapyrusViewStyle) style); |
| } else if (style instanceof StringValueStyle && ((StringValueStyle) style).getName().equals("diagram_compatibility_version")) { |
| compatibilityVersion = (StringValueStyle) style; |
| } |
| } |
| final String diagramID = ((XMIResource) diagram.eResource()).getID(diagram); |
| |
| if (null != compatibilityVersion && !oldIds.containsKey(compatibilityVersion)) { |
| final StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(DIAGRAM_COMPATIBILITY_VERSION); |
| stringBuilder.append(OF); |
| stringBuilder.append(diagramID); |
| res.setID(compatibilityVersion, stringBuilder.toString()); |
| oldIds.put(compatibilityVersion, stringBuilder.toString()); |
| } |
| |
| for (final PapyrusViewStyle papyrusViewStyle : papyrusViewStyles) { |
| if (!oldIds.containsKey(papyrusViewStyle)) { |
| final StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(PAPYRUS_VIEW_STYLE); |
| stringBuilder.append(((XMIResource) papyrusViewStyle.getOwner().eResource()).getID(papyrusViewStyle.getOwner())); |
| stringBuilder.append(OF); |
| stringBuilder.append(diagramID); |
| res.setID(papyrusViewStyle, stringBuilder.toString()); |
| oldIds.put(papyrusViewStyle, stringBuilder.toString()); |
| } |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created Style. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param style |
| * The Style to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateStyle(final XMIResource res, final Style style, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(style)) { |
| final String containerID = ((XMIResource) style.eContainer().eResource()).getID(style.eContainer()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(style.eClass().getName()); |
| stringBuilder.append(OF); |
| stringBuilder.append(containerID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(style, stringBuilder.toString()); |
| oldIds.put(style, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created Bounds. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param bounds |
| * The Bounds to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateBounds(final XMIResource res, final Bounds bounds, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(bounds)) { |
| final String containerID = ((XMIResource) bounds.eContainer().eResource()).getID(bounds.eContainer()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(BOUNDS); |
| stringBuilder.append(OF); |
| stringBuilder.append(containerID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(bounds, stringBuilder.toString()); |
| oldIds.put(bounds, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created Location. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param location |
| * The Location to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateLocation(final XMIResource res, final Location location, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(location)) { |
| final String containerID = ((XMIResource) location.eContainer().eResource()).getID(location.eContainer()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(LOCATION); |
| stringBuilder.append(OF); |
| stringBuilder.append(containerID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(location, stringBuilder.toString()); |
| oldIds.put(location, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created EAnnotation and details. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param eAnnotation |
| * The EAnnotation to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateEAnnotation(final XMIResource res, final EAnnotation eAnnotation, final Map<EObject, String> oldIds) { |
| final String containerID = ((XMIResource) eAnnotation.eContainer().eResource()).getID(eAnnotation.eContainer()); |
| |
| String eAnnotationID = null; |
| if (!oldIds.containsKey(eAnnotation)) { |
| final StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(eAnnotation.getSource()); |
| stringBuilder.append(OF); |
| stringBuilder.append(containerID); |
| eAnnotationID = stringBuilder.toString(); |
| res.setID(eAnnotation, eAnnotationID); |
| oldIds.put(eAnnotation, eAnnotationID); |
| } else { |
| eAnnotationID = oldIds.get(eAnnotation); |
| } |
| |
| for (final Entry<String, String> detail : eAnnotation.getDetails()) { |
| if (detail instanceof EStringToStringMapEntryImpl && !oldIds.containsKey((EStringToStringMapEntryImpl) detail)) { |
| final StringBuilder eAnnotationStringBuilder = new StringBuilder(); |
| eAnnotationStringBuilder.append(detail.getKey()); |
| eAnnotationStringBuilder.append(OF); |
| eAnnotationStringBuilder.append(eAnnotationID); |
| res.setID((EStringToStringMapEntryImpl) detail, eAnnotationStringBuilder.toString()); |
| oldIds.put((EStringToStringMapEntryImpl) detail, eAnnotationStringBuilder.toString()); |
| } |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created Shape. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param shape |
| * The Shape to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateShape(final XMIResource res, final Shape shape, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(shape)) { |
| final String elementID = ((XMIResource) shape.getElement().eResource()).getID(shape.getElement()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(SHAPE); |
| stringBuilder.append(OF); |
| stringBuilder.append(elementID); |
| |
| // Manage the existing shape id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(shape, stringBuilder.toString()); |
| oldIds.put(shape, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created Connector. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param connector |
| * The Connector to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateConnector(final XMIResource res, final Connector connector, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(connector)) { |
| final String sourceID = ((XMIResource) connector.getSource().eResource()).getID(connector.getSource()); |
| final String targetID = ((XMIResource) connector.getTarget().eResource()).getID(connector.getTarget()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(CONNECTOR); |
| stringBuilder.append(FROM); |
| stringBuilder.append(sourceID); |
| stringBuilder.append(TO); |
| stringBuilder.append(targetID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(connector, stringBuilder.toString()); |
| oldIds.put(connector, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created Bendpoints. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param bendpoints |
| * The Bendpoints to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateBendpoints(final XMIResource res, final Bendpoints bendpoints, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(bendpoints)) { |
| final String elementID = ((XMIResource) bendpoints.eContainer().eResource()).getID(bendpoints.eContainer()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(BENDPOINTS); |
| stringBuilder.append(OF); |
| stringBuilder.append(elementID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(bendpoints, stringBuilder.toString()); |
| oldIds.put(bendpoints, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to calculate the identifiers of created IdentityAnchor. |
| * |
| * @param res |
| * The Notation Resource. |
| * @param identityAnchor |
| * The IdentityAnchor to manage its identifier. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| */ |
| public static void calculateIdentityAnchor(final XMIResource res, final IdentityAnchor identityAnchor, final Map<EObject, String> oldIds) { |
| if (!oldIds.containsKey(identityAnchor)) { |
| final String elementID = ((XMIResource) identityAnchor.eContainer().eResource()).getID(identityAnchor.eContainer()); |
| |
| StringBuilder stringBuilder = new StringBuilder(); |
| stringBuilder.append(IDENTITY_ANCHOR); |
| stringBuilder.append(OF); |
| stringBuilder.append(elementID); |
| |
| // Manage the existing connector id with incremental suffix item if needed |
| stringBuilder = incrementStringBuilder(stringBuilder.toString(), oldIds); |
| |
| res.setID(identityAnchor, stringBuilder.toString()); |
| oldIds.put(identityAnchor, stringBuilder.toString()); |
| } |
| } |
| |
| /** |
| * This allows to suffix the initial string builder if the id already exist. |
| * |
| * @param initialString |
| * The initial string builder. |
| * @param oldIds |
| * The existing objects and their identifiers. |
| * @return The string builder incremented if needed. |
| */ |
| protected static StringBuilder incrementStringBuilder(final String initialString, final Map<EObject, String> oldIds) { |
| StringBuilder subStringBuilder = new StringBuilder(initialString); |
| |
| boolean idAlreadyExist = oldIds.containsValue(initialString); |
| int incremental = 2; |
| while (idAlreadyExist) { |
| subStringBuilder = new StringBuilder(initialString); |
| subStringBuilder.append(UNDERSCORE); |
| subStringBuilder.append(incremental); |
| if (!oldIds.containsValue(subStringBuilder.toString())) { |
| idAlreadyExist = false; |
| } |
| incremental++; |
| } |
| |
| return subStringBuilder; |
| } |
| } |