From 40b9929b81f9439cc1a0c235d20ddbd5c4a4b9ed Mon Sep 17 00:00:00 2001 From: Fanch BONNABESSE Date: Thu, 22 Oct 2015 10:50:02 +0200 Subject: Bug 478288: [BDD] Bad restore Association/DirectedAssociation https://bugs.eclipse.org/bugs/show_bug.cgi?id=478288 Comparison of Association to add. Change-Id: Iad6036d4a768f7ccaa5858d578115a324f721b7d Signed-off-by: Fanch BONNABESSE --- .../SysMLCreateOrShowExistingElementHelper.java | 445 ++++++++++++--------- .../service/types/utils/AssociationUtils.java | 101 +++++ 2 files changed, 356 insertions(+), 190 deletions(-) create mode 100644 plugins/sysml/org.eclipse.papyrus.sysml.service.types/src/org/eclipse/papyrus/sysml/service/types/utils/AssociationUtils.java (limited to 'plugins') diff --git a/plugins/sysml/diagram/org.eclipse.papyrus.sysml.diagram.common/src/org/eclipse/papyrus/sysml/diagram/common/utils/SysMLCreateOrShowExistingElementHelper.java b/plugins/sysml/diagram/org.eclipse.papyrus.sysml.diagram.common/src/org/eclipse/papyrus/sysml/diagram/common/utils/SysMLCreateOrShowExistingElementHelper.java index 1af6e4da783..9bcf5501c7d 100644 --- a/plugins/sysml/diagram/org.eclipse.papyrus.sysml.diagram.common/src/org/eclipse/papyrus/sysml/diagram/common/utils/SysMLCreateOrShowExistingElementHelper.java +++ b/plugins/sysml/diagram/org.eclipse.papyrus.sysml.diagram.common/src/org/eclipse/papyrus/sysml/diagram/common/utils/SysMLCreateOrShowExistingElementHelper.java @@ -1,190 +1,255 @@ -/***************************************************************************** - * Copyright (c) 2011 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: - * - * CEA LIST - Initial API and implementation - * - *****************************************************************************/ -package org.eclipse.papyrus.sysml.diagram.common.utils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.eclipse.emf.ecore.EObject; -import org.eclipse.gmf.runtime.emf.type.core.IElementType; -import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest; -import org.eclipse.gmf.runtime.notation.View; -import org.eclipse.papyrus.infra.services.edit.utils.RequestParameterConstants; -import org.eclipse.papyrus.sysml.service.types.element.SysMLElementTypes; -import org.eclipse.papyrus.sysml.service.types.utils.ConnectorUtils; -import org.eclipse.papyrus.uml.diagram.common.helper.CreateOrShowExistingElementHelper; -import org.eclipse.papyrus.uml.diagram.common.helper.ILinkMappingHelper; -import org.eclipse.papyrus.uml.diagram.common.util.LinkEndsMapper; -import org.eclipse.uml2.uml.AggregationKind; -import org.eclipse.uml2.uml.Association; -import org.eclipse.uml2.uml.Connector; -import org.eclipse.uml2.uml.Element; -import org.eclipse.uml2.uml.Property; -import org.eclipse.uml2.uml.UMLPackage; - -/** - * Show Existing Link Helper for SysML. This class provides specific management for SysML Association. - * - * @author VL222926 - * - */ -public class SysMLCreateOrShowExistingElementHelper extends CreateOrShowExistingElementHelper { - - /** - * the sysml connector util - */ - private ConnectorUtils sysmlConnectorUtils = new ConnectorUtils(); - - /** - * - * Constructor. - * - */ - public SysMLCreateOrShowExistingElementHelper() { - super(); - } - - /** - * - * Constructor. - * - * @param linkHelper - */ - public SysMLCreateOrShowExistingElementHelper(final ILinkMappingHelper linkHelper) { - super(linkHelper); - } - - /** - * - * @see org.eclipse.papyrus.uml.diagram.common.helper.CreateOrShowExistingElementHelper#getIElementTypeNameToDisplay(org.eclipse.gmf.runtime.emf.type.core.IElementType) - * - * @param elementType - * @return - */ - @Override - protected String getIElementTypeNameToDisplay(final IElementType elementType) { - if (SysMLElementTypes.ASSOCIATION_NONE.equals(elementType) || SysMLElementTypes.ASSOCIATION_NONE_DIRECTED.equals(elementType)) { - return "Association/DirectAssociation"; //$NON-NLS-1$ - } else if (SysMLElementTypes.ASSOCIATION_COMPOSITE.equals(elementType) || SysMLElementTypes.ASSOCIATION_COMPOSITE_DIRECTED.equals(elementType)) { - return "Composition/DirectComposition"; //$NON-NLS-1$ - } else if (SysMLElementTypes.ASSOCIATION_SHARED.equals(elementType) || SysMLElementTypes.ASSOCIATION_SHARED_DIRECTED.equals(elementType)) { - return "Aggregation/DirectAggregation"; //$NON-NLS-1$ - } - return super.getIElementTypeNameToDisplay(elementType); - } - - /** - * - * @see org.eclipse.papyrus.uml.diagram.common.helper.CreateOrShowExistingElementHelper#hasWantedType(org.eclipse.emf.ecore.EObject, org.eclipse.gmf.runtime.emf.type.core.IElementType) - * - * @param eobject - * an eobject - * @param wantedType - * the wanted element type - * @return - * true if the eobject is an instance of the wanted element type. - * - * Add test for SysML Association - */ - @Override - protected boolean hasWantedType(final EObject eobject, final IElementType wantedType) { - boolean result = super.hasWantedType(eobject, wantedType); - if (result) { - if (eobject instanceof Association) { - Association association = (Association) eobject; - // Skip incomplete associations: it can't be a duplicate of the current link (Which has a source and a target) - if (association.getMemberEnds().size() < 2) { - return false; - } - - final AggregationKind current = getAssociationAggregationKind((Association) eobject); - if (current == AggregationKind.NONE_LITERAL) { - if (SysMLElementTypes.ASSOCIATION_NONE.equals(current) || SysMLElementTypes.ASSOCIATION_NONE_DIRECTED.equals(wantedType)) { - result = true; - } - } else if (current == AggregationKind.COMPOSITE_LITERAL) { - if (SysMLElementTypes.ASSOCIATION_COMPOSITE.equals(current) || SysMLElementTypes.ASSOCIATION_COMPOSITE_DIRECTED.equals(wantedType)) { - result = true; - } - } else if (current == AggregationKind.SHARED_LITERAL) { - if (SysMLElementTypes.ASSOCIATION_SHARED.equals(current) || SysMLElementTypes.ASSOCIATION_SHARED_DIRECTED.equals(wantedType)) { - result = true; - } - } else { - result = false; - } - } - } - return result; - } - - /** - * - * @param association - * an association - * @return - * the association kind for the association - */ - private static final AggregationKind getAssociationAggregationKind(final Association association) { - // Incomplete associations - if (association.getMemberEnds().size() < 2) { - return AggregationKind.NONE_LITERAL; - } - - final Property source = association.getMemberEnds().get(0); - final Property target = association.getMemberEnds().get(1); - - if (source.getAggregation() == AggregationKind.NONE_LITERAL && target.getAggregation() == AggregationKind.NONE_LITERAL) { - return AggregationKind.NONE_LITERAL; - } else if ((source.getAggregation() == AggregationKind.COMPOSITE_LITERAL) || (target.getAggregation() == AggregationKind.COMPOSITE_LITERAL)) { - return AggregationKind.COMPOSITE_LITERAL; - } else { - return AggregationKind.SHARED_LITERAL; - } - - } - - /** - * @param request - * the request for the creation - * @param wantedEClass - * @return - * a list of {@link EdgeEndsMapper} referencing the existing links between the source and the target - */ - @Override - protected List getExistingLinksBetweenSourceAndTarget(final CreateRelationshipRequest request, final IElementType wantedElementType) { - if (wantedElementType.getEClass() == UMLPackage.eINSTANCE.getConnector()) { - final List existingElement = new ArrayList(); - for (final Element current : ((Element) request.getContainer()).getOwnedElements()) { - if (hasWantedType(current, wantedElementType)) { - final Collection sources = this.linkMappingHelper.getSource(current); - final Collection targets = this.linkMappingHelper.getTarget(current); - - if (sources.contains(request.getSource()) && targets.contains(request.getTarget())) { - // we verify the nestedPath before to propose to restore a connector - View sourceView = (View) request.getParameter(RequestParameterConstants.EDGE_CREATE_REQUEST_SOURCE_VIEW); - View targetView = (View) request.getParameter(RequestParameterConstants.EDGE_CREATE_REQUEST_TARGET_VIEW); - boolean canBeDisplayed = ConnectorUtils.canDisplayExistingConnectorBetweenViewsAccordingToNestedPaths((Connector) current, sourceView, targetView); - if (canBeDisplayed) { - existingElement.add(new LinkEndsMapper(current, sources, null, null)); - } - } - } - } - return existingElement; - } - return super.getExistingLinksBetweenSourceAndTarget(request, wantedElementType); - } -} +/***************************************************************************** + * Copyright (c) 2011 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: + * + * CEA LIST - Initial API and implementation + * Bonnabesse Fanch (ALL4TEC) fanch.bonnabesse@alltec.net - Bug 478288 + * + *****************************************************************************/ +package org.eclipse.papyrus.sysml.diagram.common.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gmf.runtime.emf.type.core.IElementType; +import org.eclipse.gmf.runtime.emf.type.core.requests.CreateRelationshipRequest; +import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.papyrus.infra.services.edit.utils.RequestParameterConstants; +import org.eclipse.papyrus.sysml.service.types.element.SysMLElementTypes; +import org.eclipse.papyrus.sysml.service.types.utils.AssociationUtils; +import org.eclipse.papyrus.sysml.service.types.utils.ConnectorUtils; +import org.eclipse.papyrus.uml.diagram.common.helper.CreateOrShowExistingElementHelper; +import org.eclipse.papyrus.uml.diagram.common.helper.ILinkMappingHelper; +import org.eclipse.papyrus.uml.diagram.common.util.LinkEndsMapper; +import org.eclipse.uml2.uml.AggregationKind; +import org.eclipse.uml2.uml.Association; +import org.eclipse.uml2.uml.Connector; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Property; +import org.eclipse.uml2.uml.UMLPackage; + +/** + * Show Existing Link Helper for SysML. This class provides specific management for SysML Association. + * + * @author VL222926 + * + */ +public class SysMLCreateOrShowExistingElementHelper extends CreateOrShowExistingElementHelper { + + /** + * + * Constructor. + * + */ + public SysMLCreateOrShowExistingElementHelper() { + super(); + } + + /** + * + * Constructor. + * + * @param linkHelper + */ + public SysMLCreateOrShowExistingElementHelper(final ILinkMappingHelper linkHelper) { + super(linkHelper); + } + + /** + * + * @see org.eclipse.papyrus.uml.diagram.common.helper.CreateOrShowExistingElementHelper#getIElementTypeNameToDisplay(org.eclipse.gmf.runtime.emf.type.core.IElementType) + * + * @param elementType + * @return + */ + @Override + protected String getIElementTypeNameToDisplay(final IElementType elementType) { + if (SysMLElementTypes.ASSOCIATION_NONE.equals(elementType) || SysMLElementTypes.ASSOCIATION_NONE_DIRECTED.equals(elementType)) { + return "Association/DirectAssociation"; //$NON-NLS-1$ + } else if (SysMLElementTypes.ASSOCIATION_COMPOSITE.equals(elementType) || SysMLElementTypes.ASSOCIATION_COMPOSITE_DIRECTED.equals(elementType)) { + return "Composition/DirectComposition"; //$NON-NLS-1$ + } else if (SysMLElementTypes.ASSOCIATION_SHARED.equals(elementType) || SysMLElementTypes.ASSOCIATION_SHARED_DIRECTED.equals(elementType)) { + return "Aggregation/DirectAggregation"; //$NON-NLS-1$ + } + return super.getIElementTypeNameToDisplay(elementType); + } + + /** + * + * @see org.eclipse.papyrus.uml.diagram.common.helper.CreateOrShowExistingElementHelper#hasWantedType(org.eclipse.emf.ecore.EObject, org.eclipse.gmf.runtime.emf.type.core.IElementType) + * + * @param eobject + * an eobject + * @param wantedType + * the wanted element type + * @return + * true if the eobject is an instance of the wanted element type. + * + * Add test for SysML Association + */ + @Override + protected boolean hasWantedType(final EObject eobject, final IElementType wantedType) { + boolean result = super.hasWantedType(eobject, wantedType); + if (result) { + if (eobject instanceof Association) { + Association association = (Association) eobject; + // Skip incomplete associations: it can't be a duplicate of the current link (Which has a source and a target) + if (association.getMemberEnds().size() < 2) { + return false; + } + + final AggregationKind current = getAssociationAggregationKind((Association) eobject); + if (current == AggregationKind.NONE_LITERAL) { + if (SysMLElementTypes.ASSOCIATION_NONE.equals(current) || SysMLElementTypes.ASSOCIATION_NONE_DIRECTED.equals(wantedType)) { + result = true; + } + } else if (current == AggregationKind.COMPOSITE_LITERAL) { + if (SysMLElementTypes.ASSOCIATION_COMPOSITE.equals(current) || SysMLElementTypes.ASSOCIATION_COMPOSITE_DIRECTED.equals(wantedType)) { + result = true; + } + } else if (current == AggregationKind.SHARED_LITERAL) { + if (SysMLElementTypes.ASSOCIATION_SHARED.equals(current) || SysMLElementTypes.ASSOCIATION_SHARED_DIRECTED.equals(wantedType)) { + result = true; + } + } else { + result = false; + } + } + } + return result; + } + + /** + * + * @param association + * an association + * @return + * the association kind for the association + */ + private static final AggregationKind getAssociationAggregationKind(final Association association) { + // Incomplete associations + if (association.getMemberEnds().size() < 2) { + return AggregationKind.NONE_LITERAL; + } + + final Property source = association.getMemberEnds().get(0); + final Property target = association.getMemberEnds().get(1); + + if (source.getAggregation() == AggregationKind.NONE_LITERAL && target.getAggregation() == AggregationKind.NONE_LITERAL) { + return AggregationKind.NONE_LITERAL; + } else if ((source.getAggregation() == AggregationKind.COMPOSITE_LITERAL) || (target.getAggregation() == AggregationKind.COMPOSITE_LITERAL)) { + return AggregationKind.COMPOSITE_LITERAL; + } else { + return AggregationKind.SHARED_LITERAL; + } + + } + + /** + * @param request + * the request for the creation + * @param wantedEClass + * @return + * a list of {@link EdgeEndsMapper} referencing the existing links between the source and the target + */ + @Override + protected List getExistingLinksBetweenSourceAndTarget(final CreateRelationshipRequest request, final IElementType wantedElementType) { + List existingElement = null; + + final EClass wantedEClass = wantedElementType.getEClass(); + + if (UMLPackage.eINSTANCE.getConnector().equals(wantedEClass)) { + EList ownedElements = ((Element) request.getContainer()).getOwnedElements(); + + existingElement = new ArrayList(); + + for (final Element current : ownedElements) { + if (hasWantedType(current, wantedElementType)) { + final Collection sources = this.linkMappingHelper.getSource(current); + final Collection targets = this.linkMappingHelper.getTarget(current); + + if (sources.contains(request.getSource()) && targets.contains(request.getTarget())) { + // we verify the nestedPath before to propose to restore a connector + View sourceView = (View) request.getParameter(RequestParameterConstants.EDGE_CREATE_REQUEST_SOURCE_VIEW); + View targetView = (View) request.getParameter(RequestParameterConstants.EDGE_CREATE_REQUEST_TARGET_VIEW); + boolean canBeDisplayed = ConnectorUtils.canDisplayExistingConnectorBetweenViewsAccordingToNestedPaths((Connector) current, sourceView, targetView); + if (canBeDisplayed) { + existingElement.add(new LinkEndsMapper(current, sources, null, null)); + } + } + } + } + + } else if (UMLPackage.eINSTANCE.getAssociation().equals(wantedEClass)) { + final EList ownedElements = ((Element) request.getContainer()).getOwnedElements(); + + existingElement = new ArrayList(); + + for (final Element current : ownedElements) { + if (hasWantedType(current, wantedElementType)) { + final Collection sources = this.linkMappingHelper.getSource(current); + final Collection targets = this.linkMappingHelper.getTarget(current); + + if (sources.contains(request.getSource()) && targets.contains(request.getTarget()) && (current instanceof Association)) { + boolean identicalAssociation = true; + + final Iterator iterator = ((Association) current).getMemberEnds().iterator(); + + while (iterator.hasNext() && identicalAssociation) { + final Property property = iterator.next(); + + final boolean source = request.getSource().equals(property.getType()); + + // Handle of all types of Association in SysML + if (SysMLElementTypes.ASSOCIATION_NONE_DIRECTED.equals(wantedElementType)) { + if (!AssociationUtils.isIdenticalProperties(false, AggregationKind.NONE_LITERAL, source, property)) { + identicalAssociation = false; + } + } else if (SysMLElementTypes.ASSOCIATION_NONE.equals(wantedElementType)) { + if (!AssociationUtils.isIdenticalProperties(true, AggregationKind.NONE_LITERAL, source, property)) { + identicalAssociation = false; + } + } else if (SysMLElementTypes.ASSOCIATION_COMPOSITE_DIRECTED.equals(wantedElementType)) { + if (!AssociationUtils.isIdenticalProperties(false, AggregationKind.COMPOSITE_LITERAL, source, property)) { + identicalAssociation = false; + } + } else if (SysMLElementTypes.ASSOCIATION_COMPOSITE.equals(wantedElementType)) { + if (!AssociationUtils.isIdenticalProperties(true, AggregationKind.COMPOSITE_LITERAL, source, property)) { + identicalAssociation = false; + } + } else if (SysMLElementTypes.ASSOCIATION_SHARED_DIRECTED.equals(wantedElementType)) { + if (!AssociationUtils.isIdenticalProperties(false, AggregationKind.SHARED_LITERAL, source, property)) { + identicalAssociation = false; + } + } else if (SysMLElementTypes.ASSOCIATION_SHARED.equals(wantedElementType)) { + if (!AssociationUtils.isIdenticalProperties(true, AggregationKind.SHARED_LITERAL, source, property)) { + identicalAssociation = false; + } + } + } + + if (identicalAssociation) { + existingElement.add(new LinkEndsMapper(current, sources, null, null)); + } + } + } + } + } else { + existingElement = super.getExistingLinksBetweenSourceAndTarget(request, wantedElementType); + } + + return existingElement; + } + +} diff --git a/plugins/sysml/org.eclipse.papyrus.sysml.service.types/src/org/eclipse/papyrus/sysml/service/types/utils/AssociationUtils.java b/plugins/sysml/org.eclipse.papyrus.sysml.service.types/src/org/eclipse/papyrus/sysml/service/types/utils/AssociationUtils.java new file mode 100644 index 00000000000..5b3f5e07576 --- /dev/null +++ b/plugins/sysml/org.eclipse.papyrus.sysml.service.types/src/org/eclipse/papyrus/sysml/service/types/utils/AssociationUtils.java @@ -0,0 +1,101 @@ +/***************************************************************************** + * Copyright (c) 2015 CEA LIST and others. + * + * 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: + * Bonnabesse Fanch (ALL4TEC) fanch.bonnabesse@alltec.net - Bug 478288 + * + *****************************************************************************/ + +package org.eclipse.papyrus.sysml.service.types.utils; + +import org.eclipse.uml2.uml.AggregationKind; +import org.eclipse.uml2.uml.Property; + +/** + * Utility class for Association edit helpers. + */ +public class AssociationUtils { + + /** + * This compares the Property of an Association with expected informations. + * + * @param expectedNavigable + * The expected navigable information. + * @param expectedAggregation + * The expected kind of aggregation. + * @param source + * To specify if the member in treatment is a source. + * @param property + * The property containing the aggregation to compare. + * @return The result of the comparison. + */ + public static boolean isIdenticalProperties(final boolean expectedNavigable, final AggregationKind expectedAggregation, final boolean source, final Property property) { + return (isIdenticalAggregations(expectedAggregation, source, property) && isIdenticalNavigables(expectedNavigable, source, property)); + } + + /** + * This compares the aggregation information of a Property with an expected kind of aggregation. + * + * @param expectedAggregation + * The expected kind of aggregation. + * @param source + * To specify if the member in treatment is a source. + * @param property + * The property containing the aggregation to compare. + * @return The result of the comparison. + */ + public static boolean isIdenticalAggregations(final AggregationKind expectedAggregation, final boolean source, final Property property) { + boolean identicalAggregation = false; + + final AggregationKind aggregation = property.getAggregation(); + + if (source) { + // If the member is the source member, the aggregation must be NONE + if (AggregationKind.NONE_LITERAL.equals(aggregation)) { + identicalAggregation = true; + } + + // If the member is the target member, the aggregation must be the same than the expected aggregation + } else if (expectedAggregation.equals(aggregation)) { + identicalAggregation = true; + } + + return identicalAggregation; + } + + /** + * This compares the navigable information of a Property with an expected navigable. + * + * @param expectedNavigable + * The expected navigable information. + * @param source + * To specify if the member in treatment is a source. + * @param property + * The property containing the navigable information to compare. + * @return The result of the comparison. + */ + public static boolean isIdenticalNavigables(final boolean expectedNavigable, final boolean source, final Property property) { + boolean identicalNavigable = false; + + final boolean navigable = property.isNavigable(); + + if (source) { + // If the member is the source member, the navigable value must be the same than the expected navigable + if (expectedNavigable == navigable) { + identicalNavigable = true; + } + + // If the member is the source member, the navigable value must be the same than the expected navigable + } else if (navigable) { + identicalNavigable = true; + } + + return identicalNavigable; + } + +} -- cgit v1.2.3