Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas FAUVERGUE2016-02-11 15:08:36 +0000
committerGerrit Code Review @ Eclipse.org2016-02-24 15:31:08 +0000
commit2f0dd86c51f8543f56a99cd4371965a01287fcaa (patch)
tree8255f00b8202347c0f0fbb64a09df5b27668c352 /plugins
parent3dec4967ac2a6fcfb71f059bf7e347091b81df89 (diff)
downloadorg.eclipse.papyrus-2f0dd86c51f8543f56a99cd4371965a01287fcaa.tar.gz
org.eclipse.papyrus-2f0dd86c51f8543f56a99cd4371965a01287fcaa.tar.xz
org.eclipse.papyrus-2f0dd86c51f8543f56a99cd4371965a01287fcaa.zip
Bug 481835: [Table] java.lang.IndexOutOfBoundsException: Index: 0, Size:
0 with UMLReferenceTextWithCompletionCellEditor https://bugs.eclipse.org/bugs/show_bug.cgi?id=481835 If the object to edit has a same namespace and shortest qualified name, use the simple reference selection dialog instead of text completion. It is possible to choose class with same name by the xtext (and the completion (which displayed all objects names)) and the element choose is the first. Change-Id: I35e31fc6612cef5e7827638315d33d23da5e2763 Signed-off-by: Nicolas FAUVERGUE <nicolas.fauvergue@all4tec.net>
Diffstat (limited to 'plugins')
-rwxr-xr-xplugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/converter/StringResolutionProblemPapyrusConverter.java21
-rw-r--r--plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java10
-rw-r--r--plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java28
-rwxr-xr-xplugins/uml/nattable/org.eclipse.papyrus.uml.nattable/src/org/eclipse/papyrus/uml/nattable/manager/cell/editor/UMLReferenceTextWithCompletionCellEditor.java30
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionHelper.java46
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionUtils.java831
-rw-r--r--plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/util/UMLReferenceConverter.java49
7 files changed, 587 insertions, 428 deletions
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/converter/StringResolutionProblemPapyrusConverter.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/converter/StringResolutionProblemPapyrusConverter.java
index fbd4d18250f..48d9347a015 100755
--- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/converter/StringResolutionProblemPapyrusConverter.java
+++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/converter/StringResolutionProblemPapyrusConverter.java
@@ -63,13 +63,24 @@ public class StringResolutionProblemPapyrusConverter implements IPapyrusConverte
}
/**
+ * {@inheritDoc}
+ *
* @see org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper#getShortestQualifiedNames(java.lang.Object)
- *
- * @param element
- * @return
+ * @deprecated since 1.2.0
+ */
+ @Override
+ public List<String> getShortestQualifiedNames(final Object element) {
+ return getShortestQualifiedNames(element, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper#getShortestQualifiedNames(java.lang.Object, boolean)
*/
- public List<String> getShortestQualifiedNames(Object element) {
- return wrappedDisplayConverter.getShortestQualifiedNames(element);
+ @Override
+ public List<String> getShortestQualifiedNames(final Object element, final boolean manageDuplicate) {
+ return wrappedDisplayConverter.getShortestQualifiedNames(element, manageDuplicate);
}
/**
diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java
index 7de49d963cc..98d34d0acd5 100644
--- a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java
+++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/editors/StringEditorWithCompletionWrapper.java
@@ -20,6 +20,7 @@ import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ContentAssistant;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposalSorter;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.papyrus.infra.widgets.util.IPapyrusConverter;
import org.eclipse.papyrus.infra.widgets.util.ISetPapyrusConverter;
@@ -144,6 +145,15 @@ public class StringEditorWithCompletionWrapper implements ISetPapyrusConverter{
assistant.setContentAssistProcessor(this.processor, IDocument.DEFAULT_CONTENT_TYPE);
}
+ // Manage the sorter for the completion proposal
+ assistant.setSorter(new ICompletionProposalSorter() {
+
+ @Override
+ public int compare(final ICompletionProposal p1, final ICompletionProposal p2) {
+ return p1.getDisplayString().compareTo(p2.getDisplayString());
+ }
+ });
+
assistant.install(textViewer);
assistant.addCompletionListener(new ICompletionListener() {
diff --git a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java
index 727c9c6b46e..cadecebe16f 100644
--- a/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java
+++ b/plugins/infra/ui/org.eclipse.papyrus.infra.widgets/src/org/eclipse/papyrus/infra/widgets/util/INameResolutionHelper.java
@@ -20,13 +20,13 @@ import java.util.List;
*
*/
public interface INameResolutionHelper {
-
+
/**
*
* @param aString
* a string
* @return
- * all elements whose the name starts with this string, or all found element if the string is <code>null</code> or empty
+ * all elements whose the name starts with this string, or all found element if the string is <code>null</code> or empty
*/
public List<?> getMatchingElements(final String aString);
@@ -35,16 +35,32 @@ public interface INameResolutionHelper {
* @param aString
* a string
* @return
- * all elements which have the wanted string as (qualified) name
+ * all elements which have the wanted string as (qualified) name
*/
public List<?> getElementsByName(final String aString);
/**
- * @param namedElement
+ * Get the shortest qualified name.
+ *
+ * @param element
+ * The element to get the shortest qualified name.
* @return
- * the shortest qualified to use for the element
+ * the shortest qualified to use for the element
+ * @deprecated since 1.2.0
+ */
+ @Deprecated
+ public List<String> getShortestQualifiedNames(final Object element);
+
+ /**
+ * Get the shortest qualified name.
+ *
+ * @param element
+ * The element to get the shortest qualified name.
+ * @param manageDuplicate
+ * Boolean to determinate if the duplicated shortest qualified names must be remove from the returned list.
+ * @return the shortest qualified to use for the element
*/
- public List<String> getShortestQualifiedNames(Object element);
+ public List<String> getShortestQualifiedNames(final Object element, final boolean manageDuplicate);
}
diff --git a/plugins/uml/nattable/org.eclipse.papyrus.uml.nattable/src/org/eclipse/papyrus/uml/nattable/manager/cell/editor/UMLReferenceTextWithCompletionCellEditor.java b/plugins/uml/nattable/org.eclipse.papyrus.uml.nattable/src/org/eclipse/papyrus/uml/nattable/manager/cell/editor/UMLReferenceTextWithCompletionCellEditor.java
index b80a7fd3b7c..58b4d10fe12 100755
--- a/plugins/uml/nattable/org.eclipse.papyrus.uml.nattable/src/org/eclipse/papyrus/uml/nattable/manager/cell/editor/UMLReferenceTextWithCompletionCellEditor.java
+++ b/plugins/uml/nattable/org.eclipse.papyrus.uml.nattable/src/org/eclipse/papyrus/uml/nattable/manager/cell/editor/UMLReferenceTextWithCompletionCellEditor.java
@@ -7,7 +7,7 @@
*
* Contributors:
* Vincent Lorenzo (CEA-LIST) - duplicated and adapted code from nattable project.
- * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue - Bug 482790
+ * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue - Bug 482790, 481835
*
******************************************************************************/
package org.eclipse.papyrus.uml.nattable.manager.cell.editor;
@@ -142,6 +142,8 @@ public class UMLReferenceTextWithCompletionCellEditor extends AbstractPapyrusSty
final CrossAxisWrapper<EObject, EStructuralFeature> editedElement = UMLTableUtils.getRealEditedObject(layerCell, elementProvider);
final EObject element = editedElement.getFirstAxis();
+ boolean useSimpleDialog = true;
+
Control control = null;
// Bug 482790: Check if this is not an object with a null namespace
@@ -149,8 +151,28 @@ public class UMLReferenceTextWithCompletionCellEditor extends AbstractPapyrusSty
this.helper = createNameResolutionHelper();
parser = new StringResolutionProblemPapyrusConverter(new UMLReferenceConverter(this.helper, isMultiValued));
setPapyrusConverter(parser);
- control = super.activateCell(parent, originalCanonicalValue);
- }else{
+
+ // Get the display value
+ Object displayValue = null;
+ if (this.displayConverter != null) {
+ displayValue = this.displayConverter.canonicalToDisplayValue(this.layerCell, this.configRegistry, originalCanonicalValue);
+ } else {
+ displayValue = originalCanonicalValue;
+ }
+
+ // Bug 481835 : If the display value is empty and the data value is not null,
+ // this means the namespace of the object to edit cannot be resolved (same Objects name? other?).
+ // In this case, use the simple reference dialog.
+ if(displayValue.toString().isEmpty() && null != layerCell.getDataValue()){
+ helper = null;
+ parser = null;
+ setPapyrusConverter(parser);
+ }else{
+ useSimpleDialog = false;
+ }
+ }
+
+ if(useSimpleDialog){
// Bug 482790: The parse can't be used because no name resolution helper can't be created
// So re-initialize the display converter to null
this.displayConverter = null;
@@ -201,6 +223,8 @@ public class UMLReferenceTextWithCompletionCellEditor extends AbstractPapyrusSty
} else {
singleReferenceValueCellEditor.close();
}
+ }else{
+ control = super.activateCell(parent, originalCanonicalValue);
}
return control;
}
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionHelper.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionHelper.java
index d42c44d4ce9..c7a3fc7745c 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionHelper.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionHelper.java
@@ -63,7 +63,7 @@ public class NameResolutionHelper implements INameResolutionHelper {
/**
* the empty string
*/
- private static final String EMPTY_STRING = ""; //$NON-NLS-N1
+ private static final String EMPTY_STRING = ""; // $NON-NLS-N1
/**
*
@@ -120,7 +120,7 @@ public class NameResolutionHelper implements INameResolutionHelper {
* @param name
* a name
* @return
- * all named element matching this name
+ * all named element matching this name
*
* @deprecated you should use {@link #getElementsByName(String)}
*/
@@ -258,12 +258,30 @@ public class NameResolutionHelper implements INameResolutionHelper {
}
/**
+ * This allows to get the shortest qualified name for a named element in parameter.
+ *
* @param namedElement
+ * The named element.
* @return
- * the shortest qualified to use for the element
+ * the shortest qualified to use for the element
*/
+ @Deprecated
public List<String> getShortestQualifiedNames(NamedElement namedElement) {
- return NameResolutionUtils.getShortestQualifiedNames(namedElement, this.scope);
+ return getShortestQualifiedNames(namedElement, true);
+ }
+
+ /**
+ * This allows to get the shortest qualified name for a named element in parameter.
+ *
+ * @param namedElement
+ * The named element.
+ * @param manageDuplicate
+ * Boolean to determinate if the duplicated shortest qualified names must be remove from the returned list.
+ * @return
+ * the shortest qualified to use for the element
+ */
+ public List<String> getShortestQualifiedNames(NamedElement namedElement, final boolean manageDusplicate) {
+ return NameResolutionUtils.getShortestQualifiedNames(namedElement, this.scope, manageDusplicate);
}
/**
@@ -310,16 +328,24 @@ public class NameResolutionHelper implements INameResolutionHelper {
return returnedValues != null ? returnedValues : Collections.emptyList();
}
-
/**
+ * {@inheritDoc}
+ *
* @see org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper#getShortestQualifiedNames(java.lang.Object)
- *
- * @param element
- * @return
+ * @deprecated since 1.2.0
+ */
+ public List<String> getShortestQualifiedNames(final Object element) {
+ return getShortestQualifiedNames(element, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper#getShortestQualifiedNames(java.lang.Object, boolean)
*/
- public List<String> getShortestQualifiedNames(Object element) {
+ public List<String> getShortestQualifiedNames(final Object element, final boolean manageDuplicate) {
if (element instanceof NamedElement) {
- return getShortestQualifiedNames((NamedElement) element);
+ return getShortestQualifiedNames((NamedElement) element, manageDuplicate);
}
return null;
}
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionUtils.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionUtils.java
index bb06ad6d34a..b3e0aa07a1a 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionUtils.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools.utils/src/org/eclipse/papyrus/uml/tools/utils/NameResolutionUtils.java
@@ -1,386 +1,445 @@
-/*****************************************************************************
- * 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:
- * Arnaud Cuccuru (CEA LIST) - Initial API and implementation
- * Vincent Lorenzo (CEA LIST)
- *****************************************************************************/
-
-package org.eclipse.papyrus.uml.tools.utils;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.uml2.uml.Element;
-import org.eclipse.uml2.uml.Model;
-import org.eclipse.uml2.uml.NamedElement;
-import org.eclipse.uml2.uml.Namespace;
-import org.eclipse.uml2.uml.resource.UMLResource;
-
-public class NameResolutionUtils {
-
-
- private NameResolutionUtils() {
- // to prevent instanciation
- }
-
- /**
- * From a given (potentially qualified) name and a scope, retrieves a list of NamedElement, filter by the filter metaclass (which can be null).
- * If there are more than one element in the returned list, the name is ambiguous
- * If the list is empty, the name does not correspond to any available named element in the context of the model resource set
- *
- * @param name
- * , the potentially/partially qualified name of the NamedElement to be resolved
- * @param scope
- * , the namespace defining the scope for the name resolution
- * @param filter
- * , the potential "filter" metaclass (can be null)
- * @return the list of NamedElement found by applying the resolution process
- */
- public static final List<NamedElement> getNamedElements(final String name, final Element scope, final EClass filter) {
- final List<NamedElement> resolvedNamedElements = new ArrayList<NamedElement>();
- // In practice, a scope can only be a Namespace
- if (!(scope instanceof Namespace)) {
- return resolvedNamedElements;
- }
- return NameResolutionUtils.getNamedElements(name, (Namespace) scope, filter);
- }
-
- /**
- * From a given (potentially qualified) name and a scope, retrieves a list of NamedElement, filter by the filter metaclass (which can be null).
- * If there are more than one element in the returned list, the name is ambiguous
- * If the list is empty, the name does not correspond to any available named element in the context of the model resource set
- *
- * @param name
- * , the potentially/partially qualified name of the NamedElement to be resolved
- * @param scope
- * , the namespace defining the scope for the name resolution
- * @param filter
- * , the potential "filter" metaclass (can be null)
- * @return the list of NamedElement found by applying the resolution process
- */
- public static final List<NamedElement> getNamedElements(final String name, final Namespace scope, final EClass filter) {
- final List<NamedElement> resolvedNamedElements = new ArrayList<NamedElement>();
-
- // extracts name fragments for the given (potentially qualified) name
- final List<String> nameFragments = NameResolutionUtils.computeNameFragments(name);
- // tries to resolve the name
- resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(nameFragments, scope, filter));
-
- // If no named elements have been found, tries to restart the process on the enclosing namespace of the scope, if any
- if (resolvedNamedElements.isEmpty()) {
- Namespace enclosingNamespace = scope.getNamespace();
- while (resolvedNamedElements.isEmpty() && (enclosingNamespace != null)) {
- resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(nameFragments, enclosingNamespace, filter));
- enclosingNamespace = enclosingNamespace.getNamespace();
- }
- }
-
- // If no named elements have been found, tries to evaluate the name using the root context model has a root of the qualified name
- if (resolvedNamedElements.isEmpty()) {
- Namespace model = scope.getModel();
- if (model == null) {
- model = scope;
- }
- if (model.getName().equals(nameFragments.get(0))) {
- if (nameFragments.size() == 1) {
- if (filter != null) {
- if (filter.isSuperTypeOf(model.eClass())) {
- resolvedNamedElements.add(model);
- }
- } else {
- resolvedNamedElements.add(model);
- }
- } else {
- final List<String> remainingNameFragments = nameFragments.subList(1, nameFragments.size());
- resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(remainingNameFragments, model, filter));
- }
- }
- }
-
- // If no named elements have been found, tries to evaluate the name as a fully qualified name
- // This requires analysis of available UML resources in the context of scope resource set
- if (resolvedNamedElements.isEmpty()) {
- final List<Resource> resources = scope.eResource().getResourceSet().getResources();
- for (final Resource resource : resources) {
- if ((resource != scope.eResource()) && (resource instanceof UMLResource)) {
- final UMLResource umlResource = (UMLResource) resource;
- Model root = null;
- for (final Iterator<EObject> i = umlResource.getAllContents(); i.hasNext() && (root == null);) {
- final EObject next = i.next();
- if (next instanceof Model) {
- root = (Model) next;
- }
- }
- if (root != null) {
- if (root.getName().equals(nameFragments.get(0))) {
- if (nameFragments.size() == 1) {
- if (filter != null) {
- if (filter.isSuperTypeOf(root.eClass())) {
- resolvedNamedElements.add(root);
- }
- } else {
- resolvedNamedElements.add(root);
- }
- } else {
- final List<String> remainingNameFragments = nameFragments.subList(1, nameFragments.size());
- resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(remainingNameFragments, root, filter));
- }
- }
- }
- }
- }
- }
-
- return resolvedNamedElements;
- }
-
- /**
- * From a given list of name fragments representing a (potentially qualified name),
- * retrieves a list of NamedElement.
- * The basic principle of the algorithm is to try to match the first element of nameFragments with
- * members of the scope.
- * When a match is found, this method is called a recursively on a sublist of a nameFragments
- * (i.e., the first element is omitted) and on the matched member.
- * The stop condition for recursivity is that the size of nameFragments is 1.
- *
- * @param nameFragments
- * , the potentially/partially qualified name of the NamedElement to be resolved
- * @param scope
- * , the namespace defining the scope for the name resolution
- * @param clazz
- * , the potential "filter" metaclass (can be null)
- * @return the list of NamedElement found by applying the resolution process
- */
- private static final List<NamedElement> getNamedElements(final List<String> nameFragments, final Namespace scope, final EClass clazz) {
- final List<NamedElement> resolvedNamedElements = new ArrayList<NamedElement>();
- // Tries to match the first name fragment with members of the scope
- for (final NamedElement member : scope.getMembers()) {
- final List<String> memberNames = scope.getNamesOfMember(member);
- final String firstNameFragment = nameFragments.get(0);
- // iterates other names given to the current member in the context of this scope
- for (final String memberName : memberNames) {
- if (memberName.equals(firstNameFragment)) {
- // the first fragment matches with this member
- if (nameFragments.size() == 1) { // Stop condition for recursivity
- if (clazz != null) {
- if (clazz.isSuperTypeOf(member.eClass())) {
- resolvedNamedElements.add(member);
- }
- } else {
- resolvedNamedElements.add(member);
- }
- } else {
- if (member instanceof Namespace) { // Recursive call on the sublist and the matching member
- final List<String> remainingNameFragments = nameFragments.subList(1, nameFragments.size());
- resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(remainingNameFragments, (Namespace) member, clazz));
- }
- }
- }
- }
- }
- return resolvedNamedElements;
- }
-
- /**
- * Computes a List<String> containing the various "name fragments" of parameter "name".
- * The string "name" is simply splitted according to qualifiedNameSeparator ("::").
- *
- * @param name
- * The name to be "fragmented"
- * @return The list of name fragments
- */
- private static final List<String> computeNameFragments(final String name) {
- final String[] nameFragmentsArray = name.split(NamedElementUtil.QUALIFIED_NAME_SEPARATOR);
- final List<String> nameFragments = new ArrayList<String>();
- for (final String element : nameFragmentsArray) {
- nameFragments.add(element);
- }
- return nameFragments;
- }
-
- /**
- * Computes the shortest qualified names for a named element, in the context of a scope.
- * The shortest qualified names are the shortest name in terms of qualification depth which unambiguously
- * resolve to the researched element.
- * In the case where the returned list is empty, there is no unambiguous name that could be found,
- * including the fully qualified name of the element. This typically means that there are problems in the
- * context model in terms of organization of element imports and package imports and named element
- * definitions, or conflict in loaded UML resources.
- * In the case where the list contains more than one name, all these names are all valid, all have the same
- * qualification depth, and can be used indifferently.
- *
- * @param element
- * , the named element for which we try to determine the shortest qualified name
- * @param scope
- * , the scope in which we try to determine the shortest qualified name for element
- * @return the shortest qualified names for element
- */
- public static final List<String> getShortestQualifiedNames(final NamedElement element, final Element scope) {
- final List<String> shortestNames = new ArrayList<String>();
- // In practice, a scope can only be a Namespace
- if (!(scope instanceof Namespace)) {
- return shortestNames;
- }
- return NameResolutionUtils.getShortestQualifiedNames(element, (Namespace) scope);
- }
-
- /**
- * Computes the shortest qualified names for a named element, in the context of a scope.
- * The shortest qualified names are the shortest name in terms of qualification depth which unambiguously
- * resolve to the researched element.
- * In the case where the returned list is empty, there is no unambiguous name that could be found,
- * including the fully qualified name of the element. This typically means that there are problems in the
- * context model in terms of organization of element imports and package imports and named element
- * definitions, or conflict in loaded UML resources.
- * In the case where the list contains more than one name, all these names are all valid, all have the same
- * qualification depth, and can be used indifferently.
- *
- * @param element
- * , the named element for which we try to determine the shortest qualified name
- * @param scope
- * , the scope in which we try to determine the shortest qualified name for element
- * @return the shortest qualified names for element
- */
- public static final List<String> getShortestQualifiedNames(final NamedElement element, final Namespace scope) {
- final List<String> shortestNames = new ArrayList<String>();
-
- // Tries to compute
- shortestNames.addAll(NameResolutionUtils.getShortestQualifiedNamesOmittingFullyQualifiedName(element, scope));
-
- // if no short name have been found, returns the fully qualified name, if it is itself unambiguous
- if (shortestNames.isEmpty()) {
- final String fullyQualifiedNameOfElement = element.getQualifiedName();
- if ((fullyQualifiedNameOfElement != null) && !(fullyQualifiedNameOfElement.length() == 0)) {
- shortestNames.add(fullyQualifiedNameOfElement);
- shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
- }
- }
- return shortestNames;
- }
-
- /**
- * Computes the shortest qualified names for a named element in the context of a scope, omitting
- * fully qualified name of the named element (The fully qualified name is handled as a special case of
- * getShortestQualifiedName, in the case where this method was not able to produce a non-ambiguous qualified
- * name).
- * The basic principle is the following (each step is applied if the previous one did not succeed.
- * "Evaluates" means assuring that computed names are not ambiguous):
- * 1. if element and scope are the same, directly evaluates the name of the element.
- * 2. if element is a member of scope, evaluates member names for this element,
- * 3. Iterate over enclosing namespaces of scope, and if element is a member of an enclosing namespace,
- * evaluate member names for element in the context of this enclosing namespace
- * 4. Recursively call this method using the enclosing namespace of element as the reasearched named element,
- * build partially qualified names from the obtained list, and evaluate the computed names
- *
- * @param element
- * , the named element for which we try to determine the shortest qualified name
- * @param scope
- * , the scope in which we try to determine the shortest qualified name for element
- * @return the shortest qualified names for element (omitting the fully qualified name element)
- */
- private static final List<String> getShortestQualifiedNamesOmittingFullyQualifiedName(final NamedElement element, final Namespace scope) {
- boolean continueResearch = true;
- final List<String> shortestNames = new ArrayList<String>();
- // if element and scope are the same, the shortest name is the name of the element
- if (element == scope) {
- shortestNames.add(element.getName());
- shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
- if (!shortestNames.isEmpty()) {
- continueResearch = false;
- }
- }
- // if element is part of the scope members, the shortest names are the names given to this member in the context of this scope
- if (continueResearch && scope.getMembers().contains(element)) {
- shortestNames.addAll(scope.getNamesOfMember(element));
- shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
- if (!shortestNames.isEmpty()) {
- continueResearch = false;
- }
- }
- if (continueResearch) {
- // tries to find element in the enclosing namespaces of scope
- Namespace enclosingNamespaceOfScope = scope.getNamespace();
- while ((enclosingNamespaceOfScope != null) && shortestNames.isEmpty()) {
- if (enclosingNamespaceOfScope.getMembers().contains(element)) {
- shortestNames.addAll(enclosingNamespaceOfScope.getNamesOfMember(element));
- shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
- }
- enclosingNamespaceOfScope = enclosingNamespaceOfScope.getNamespace();
- }
- if (shortestNames.isEmpty()) {
- // tries to find the shortest name for the enclosing namespace in the context of scope
- final Namespace enclosingNamespaceOfElement = element.getNamespace();
- if (enclosingNamespaceOfElement != null) {
- final List<String> shortestNamesForEnclosingNamespace = new ArrayList<String>();
- shortestNamesForEnclosingNamespace.addAll(NameResolutionUtils.getShortestQualifiedNames(enclosingNamespaceOfElement, scope));
- // creates the list of shortest name from the list of shortest names for the enclosing namespace
- for (final String shortestNameForEnclosing : shortestNamesForEnclosingNamespace) {
- final List<String> memberNames = enclosingNamespaceOfElement.getNamesOfMember(element);
- for (final String memberName : memberNames) {
- shortestNames.add(shortestNameForEnclosing + NamedElementUtil.QUALIFIED_NAME_SEPARATOR + memberName);
- }
- }
- shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
- }
- }
- }
- return shortestNames;
- }
-
- /**
- * From a list of names, select the names which do not unambiguously resolve to researchedElement,
- * in the context of scope
- *
- * @param names
- * , the list of names to evaluate
- * @param researchedElement
- * , the element that must be resolved from the names
- * @param scope
- * , the scope in which evaluation happens
- * @return the list of names which are ambiguous
- */
- private static final List<String> findAmbiguousNames(final List<String> names, final NamedElement researchedElement, final Namespace scope) {
- final List<String> ambiguousNames = new ArrayList<String>();
- for (final String name : names) {
- if (NameResolutionUtils.isQualifiedNameAmbiguous(name, researchedElement, scope)) {
- ambiguousNames.add("" + name);
- }
- }
- return ambiguousNames;
- }
-
-
- /**
- * Determines if a given name is ambiguous. From a given scope where evaluation of the name happens,
- * a name is ambiguous if:
- * - The given name resolves to multiple elements,
- * - Or the name resolves to one element which is not the researched element.
- * This method relies on getNamedElements(String, Element, EClass), using researchedElement.eClass() as a filter.
- *
- * @param name
- * @param researchedElement
- * @param scope
- * @return
- */
- private static final boolean isQualifiedNameAmbiguous(final String name, final NamedElement researchedElement, final Namespace scope) {
- final List<NamedElement> resolvedElements = NameResolutionUtils.getNamedElements(name, scope, researchedElement.eClass());
- if (resolvedElements.size() > 1) {
- return true;
- }
- if (resolvedElements.get(0) != researchedElement) {
- return true;
- }
- return false;
- }
-}
+/*****************************************************************************
+ * 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:
+ * Arnaud Cuccuru (CEA LIST) - Initial API and implementation
+ * Vincent Lorenzo (CEA LIST)
+ *****************************************************************************/
+
+package org.eclipse.papyrus.uml.tools.utils;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.Model;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Namespace;
+import org.eclipse.uml2.uml.resource.UMLResource;
+
+public class NameResolutionUtils {
+
+
+ private NameResolutionUtils() {
+ // to prevent instanciation
+ }
+
+ /**
+ * From a given (potentially qualified) name and a scope, retrieves a list of NamedElement, filter by the filter metaclass (which can be null).
+ * If there are more than one element in the returned list, the name is ambiguous
+ * If the list is empty, the name does not correspond to any available named element in the context of the model resource set
+ *
+ * @param name
+ * , the potentially/partially qualified name of the NamedElement to be resolved
+ * @param scope
+ * , the namespace defining the scope for the name resolution
+ * @param filter
+ * , the potential "filter" metaclass (can be null)
+ * @return the list of NamedElement found by applying the resolution process
+ */
+ public static final List<NamedElement> getNamedElements(final String name, final Element scope, final EClass filter) {
+ final List<NamedElement> resolvedNamedElements = new ArrayList<NamedElement>();
+ // In practice, a scope can only be a Namespace
+ if (!(scope instanceof Namespace)) {
+ return resolvedNamedElements;
+ }
+ return NameResolutionUtils.getNamedElements(name, (Namespace) scope, filter);
+ }
+
+ /**
+ * From a given (potentially qualified) name and a scope, retrieves a list of NamedElement, filter by the filter metaclass (which can be null).
+ * If there are more than one element in the returned list, the name is ambiguous
+ * If the list is empty, the name does not correspond to any available named element in the context of the model resource set
+ *
+ * @param name
+ * , the potentially/partially qualified name of the NamedElement to be resolved
+ * @param scope
+ * , the namespace defining the scope for the name resolution
+ * @param filter
+ * , the potential "filter" metaclass (can be null)
+ * @return the list of NamedElement found by applying the resolution process
+ */
+ public static final List<NamedElement> getNamedElements(final String name, final Namespace scope, final EClass filter) {
+ final List<NamedElement> resolvedNamedElements = new ArrayList<NamedElement>();
+
+ // extracts name fragments for the given (potentially qualified) name
+ final List<String> nameFragments = NameResolutionUtils.computeNameFragments(name);
+ // tries to resolve the name
+ resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(nameFragments, scope, filter));
+
+ // If no named elements have been found, tries to restart the process on the enclosing namespace of the scope, if any
+ if (resolvedNamedElements.isEmpty()) {
+ Namespace enclosingNamespace = scope.getNamespace();
+ while (resolvedNamedElements.isEmpty() && (enclosingNamespace != null)) {
+ resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(nameFragments, enclosingNamespace, filter));
+ enclosingNamespace = enclosingNamespace.getNamespace();
+ }
+ }
+
+ // If no named elements have been found, tries to evaluate the name using the root context model has a root of the qualified name
+ if (resolvedNamedElements.isEmpty()) {
+ Namespace model = scope.getModel();
+ if (model == null) {
+ model = scope;
+ }
+ if (model.getName().equals(nameFragments.get(0))) {
+ if (nameFragments.size() == 1) {
+ if (filter != null) {
+ if (filter.isSuperTypeOf(model.eClass())) {
+ resolvedNamedElements.add(model);
+ }
+ } else {
+ resolvedNamedElements.add(model);
+ }
+ } else {
+ final List<String> remainingNameFragments = nameFragments.subList(1, nameFragments.size());
+ resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(remainingNameFragments, model, filter));
+ }
+ }
+ }
+
+ // If no named elements have been found, tries to evaluate the name as a fully qualified name
+ // This requires analysis of available UML resources in the context of scope resource set
+ if (resolvedNamedElements.isEmpty()) {
+ final List<Resource> resources = scope.eResource().getResourceSet().getResources();
+ for (final Resource resource : resources) {
+ if ((resource != scope.eResource()) && (resource instanceof UMLResource)) {
+ final UMLResource umlResource = (UMLResource) resource;
+ Model root = null;
+ for (final Iterator<EObject> i = umlResource.getAllContents(); i.hasNext() && (root == null);) {
+ final EObject next = i.next();
+ if (next instanceof Model) {
+ root = (Model) next;
+ }
+ }
+ if (root != null) {
+ if (root.getName().equals(nameFragments.get(0))) {
+ if (nameFragments.size() == 1) {
+ if (filter != null) {
+ if (filter.isSuperTypeOf(root.eClass())) {
+ resolvedNamedElements.add(root);
+ }
+ } else {
+ resolvedNamedElements.add(root);
+ }
+ } else {
+ final List<String> remainingNameFragments = nameFragments.subList(1, nameFragments.size());
+ resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(remainingNameFragments, root, filter));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return resolvedNamedElements;
+ }
+
+ /**
+ * From a given list of name fragments representing a (potentially qualified name),
+ * retrieves a list of NamedElement.
+ * The basic principle of the algorithm is to try to match the first element of nameFragments with
+ * members of the scope.
+ * When a match is found, this method is called a recursively on a sublist of a nameFragments
+ * (i.e., the first element is omitted) and on the matched member.
+ * The stop condition for recursivity is that the size of nameFragments is 1.
+ *
+ * @param nameFragments
+ * , the potentially/partially qualified name of the NamedElement to be resolved
+ * @param scope
+ * , the namespace defining the scope for the name resolution
+ * @param clazz
+ * , the potential "filter" metaclass (can be null)
+ * @return the list of NamedElement found by applying the resolution process
+ */
+ private static final List<NamedElement> getNamedElements(final List<String> nameFragments, final Namespace scope, final EClass clazz) {
+ final List<NamedElement> resolvedNamedElements = new ArrayList<NamedElement>();
+ // Tries to match the first name fragment with members of the scope
+ for (final NamedElement member : scope.getMembers()) {
+ final List<String> memberNames = scope.getNamesOfMember(member);
+ final String firstNameFragment = nameFragments.get(0);
+ // iterates other names given to the current member in the context of this scope
+ for (final String memberName : memberNames) {
+ if (memberName.equals(firstNameFragment)) {
+ // the first fragment matches with this member
+ if (nameFragments.size() == 1) { // Stop condition for recursivity
+ if (clazz != null) {
+ if (clazz.isSuperTypeOf(member.eClass())) {
+ resolvedNamedElements.add(member);
+ }
+ } else {
+ resolvedNamedElements.add(member);
+ }
+ } else {
+ if (member instanceof Namespace) { // Recursive call on the sublist and the matching member
+ final List<String> remainingNameFragments = nameFragments.subList(1, nameFragments.size());
+ resolvedNamedElements.addAll(NameResolutionUtils.getNamedElements(remainingNameFragments, (Namespace) member, clazz));
+ }
+ }
+ }
+ }
+ }
+ return resolvedNamedElements;
+ }
+
+ /**
+ * Computes a List<String> containing the various "name fragments" of parameter "name".
+ * The string "name" is simply splitted according to qualifiedNameSeparator ("::").
+ *
+ * @param name
+ * The name to be "fragmented"
+ * @return The list of name fragments
+ */
+ private static final List<String> computeNameFragments(final String name) {
+ final String[] nameFragmentsArray = name.split(NamedElementUtil.QUALIFIED_NAME_SEPARATOR);
+ final List<String> nameFragments = new ArrayList<String>();
+ for (final String element : nameFragmentsArray) {
+ nameFragments.add(element);
+ }
+ return nameFragments;
+ }
+
+ /**
+ * Computes the shortest qualified names for a named element, in the context of a scope.
+ * The shortest qualified names are the shortest name in terms of qualification depth which unambiguously
+ * resolve to the researched element.
+ * In the case where the returned list is empty, there is no unambiguous name that could be found,
+ * including the fully qualified name of the element. This typically means that there are problems in the
+ * context model in terms of organization of element imports and package imports and named element
+ * definitions, or conflict in loaded UML resources.
+ * In the case where the list contains more than one name, all these names are all valid, all have the same
+ * qualification depth, and can be used indifferently.
+ *
+ * @param element
+ * , the named element for which we try to determine the shortest qualified name
+ * @param scope
+ * , the scope in which we try to determine the shortest qualified name for element
+ * @return the shortest qualified names for element
+ */
+ public static final List<String> getShortestQualifiedNames(final NamedElement element, final Element scope) {
+ final List<String> shortestNames = new ArrayList<String>();
+ // In practice, a scope can only be a Namespace
+ if (!(scope instanceof Namespace)) {
+ return shortestNames;
+ }
+ return NameResolutionUtils.getShortestQualifiedNames(element, (Namespace) scope, true);
+ }
+
+ /**
+ * Computes the shortest qualified names for a named element, in the context of a scope.
+ * The shortest qualified names are the shortest name in terms of qualification depth which unambiguously
+ * resolve to the researched element.
+ * In the case where the returned list is empty, there is no unambiguous name that could be found,
+ * including the fully qualified name of the element. This typically means that there are problems in the
+ * context model in terms of organization of element imports and package imports and named element
+ * definitions, or conflict in loaded UML resources.
+ * In the case where the list contains more than one name, all these names are all valid, all have the same
+ * qualification depth, and can be used indifferently.
+ *
+ * @param element
+ * , the named element for which we try to determine the shortest qualified name
+ * @param scope
+ * , the scope in which we try to determine the shortest qualified name for element
+ * @return the shortest qualified names for element
+ * @deprecated since 1.2.0
+ */
+ @Deprecated
+ public static final List<String> getShortestQualifiedNames(final NamedElement element, final Namespace scope) {
+ return getShortestQualifiedNames(element, scope, true);
+ }
+
+ /**
+ * Computes the shortest qualified names for a named element, in the context of a scope.
+ * The shortest qualified names are the shortest name in terms of qualification depth which unambiguously
+ * resolve to the researched element if specified in parameter
+ * In the case where the returned list is empty, there is no unambiguous name that could be found if specified in parameter,
+ * including the fully qualified name of the element. This typically means that there are problems in the
+ * context model in terms of organization of element imports and package imports and named element
+ * definitions, or conflict in loaded UML resources.
+ * In the case where the list contains more than one name, all these names are all valid, all have the same
+ * qualification depth, and can be used indifferently.
+ *
+ * @param element
+ * , the named element for which we try to determine the shortest qualified name
+ * @param scope
+ * , the scope in which we try to determine the shortest qualified name for element
+ * @param manageDuplicate
+ * Boolean to determinate if the duplicated shortest qualified names must be remove from the returned list.
+ * @return the shortest qualified names for element
+ */
+ public static final List<String> getShortestQualifiedNames(final NamedElement element, final Namespace scope, final boolean manageDuplicate) {
+ final List<String> shortestNames = new ArrayList<String>();
+
+ // Tries to compute
+ shortestNames.addAll(NameResolutionUtils.getShortestQualifiedNamesOmittingFullyQualifiedName(element, scope, manageDuplicate));
+
+ // if no short name have been found, returns the fully qualified name, if it is itself unambiguous
+ if (shortestNames.isEmpty()) {
+ final String fullyQualifiedNameOfElement = element.getQualifiedName();
+ if ((fullyQualifiedNameOfElement != null) && !(fullyQualifiedNameOfElement.length() == 0)) {
+ shortestNames.add(fullyQualifiedNameOfElement);
+ if (manageDuplicate) {
+ shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
+ }
+ }
+ }
+ return shortestNames;
+ }
+
+ /**
+ * Computes the shortest qualified names for a named element in the context of a scope, omitting
+ * fully qualified name of the named element (The fully qualified name is handled as a special case of
+ * getShortestQualifiedName, in the case where this method was not able to produce a non-ambiguous qualified
+ * name).
+ * The basic principle is the following (each step is applied if the previous one did not succeed.
+ * "Evaluates" means assuring that computed names are not ambiguous):
+ * 1. if element and scope are the same, directly evaluates the name of the element.
+ * 2. if element is a member of scope, evaluates member names for this element,
+ * 3. Iterate over enclosing namespaces of scope, and if element is a member of an enclosing namespace,
+ * evaluate member names for element in the context of this enclosing namespace
+ * 4. Recursively call this method using the enclosing namespace of element as the reasearched named element,
+ * build partially qualified names from the obtained list, and evaluate the computed names
+ *
+ * @param element
+ * , the named element for which we try to determine the shortest qualified name
+ * @param scope
+ * , the scope in which we try to determine the shortest qualified name for element
+ * @param manageDuplicate
+ * Boolean to determinate if the duplicated shortest qualified names must be remove from the returned list.
+ * @return the shortest qualified names for element (omitting the fully qualified name element)
+ * @deprecated since 1.2.0
+ */
+ @Deprecated
+ private static final List<String> getShortestQualifiedNamesOmittingFullyQualifiedName(final NamedElement element, final Namespace scope) {
+ return getShortestQualifiedNamesOmittingFullyQualifiedName(element, scope, true);
+ }
+
+ /**
+ * Computes the shortest qualified names for a named element in the context of a scope, omitting
+ * fully qualified name of the named element (The fully qualified name is handled as a special case of
+ * getShortestQualifiedName, in the case where this method was not able to produce a non-ambiguous qualified
+ * name if specified in parameter).
+ * The basic principle is the following (each step is applied if the previous one did not succeed.
+ * "Evaluates" means assuring that computed names are not ambiguous):
+ * 1. if element and scope are the same, directly evaluates the name of the element.
+ * 2. if element is a member of scope, evaluates member names for this element,
+ * 3. Iterate over enclosing namespaces of scope, and if element is a member of an enclosing namespace,
+ * evaluate member names for element in the context of this enclosing namespace
+ * 4. Recursively call this method using the enclosing namespace of element as the reasearched named element,
+ * build partially qualified names from the obtained list, and evaluate the computed names
+ *
+ * @param element
+ * , the named element for which we try to determine the shortest qualified name
+ * @param scope
+ * , the scope in which we try to determine the shortest qualified name for element
+ * @return the shortest qualified names for element (omitting the fully qualified name element)
+ */
+ private static final List<String> getShortestQualifiedNamesOmittingFullyQualifiedName(final NamedElement element, final Namespace scope, final boolean manageDuplicate) {
+ boolean continueResearch = true;
+ final List<String> shortestNames = new ArrayList<String>();
+ // if element and scope are the same, the shortest name is the name of the element
+ if (element == scope) {
+ shortestNames.add(element.getName());
+ shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
+ if (!shortestNames.isEmpty()) {
+ continueResearch = false;
+ }
+ }
+ // if element is part of the scope members, the shortest names are the names given to this member in the context of this scope
+ if (continueResearch && scope.getMembers().contains(element)) {
+ shortestNames.addAll(scope.getNamesOfMember(element));
+ shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
+ if (!shortestNames.isEmpty()) {
+ continueResearch = false;
+ }
+ }
+ if (continueResearch) {
+ // tries to find element in the enclosing namespaces of scope
+ Namespace enclosingNamespaceOfScope = scope.getNamespace();
+ while ((enclosingNamespaceOfScope != null) && shortestNames.isEmpty()) {
+ if (enclosingNamespaceOfScope.getMembers().contains(element)) {
+ shortestNames.addAll(enclosingNamespaceOfScope.getNamesOfMember(element));
+ if (manageDuplicate) {
+ shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
+ }
+ }
+ enclosingNamespaceOfScope = enclosingNamespaceOfScope.getNamespace();
+ }
+ if (shortestNames.isEmpty()) {
+ // tries to find the shortest name for the enclosing namespace in the context of scope
+ final Namespace enclosingNamespaceOfElement = element.getNamespace();
+ if (enclosingNamespaceOfElement != null) {
+ final List<String> shortestNamesForEnclosingNamespace = new ArrayList<String>();
+ shortestNamesForEnclosingNamespace.addAll(NameResolutionUtils.getShortestQualifiedNames(enclosingNamespaceOfElement, scope, manageDuplicate));
+ // creates the list of shortest name from the list of shortest names for the enclosing namespace
+ for (final String shortestNameForEnclosing : shortestNamesForEnclosingNamespace) {
+ final List<String> memberNames = enclosingNamespaceOfElement.getNamesOfMember(element);
+ for (final String memberName : memberNames) {
+ shortestNames.add(shortestNameForEnclosing + NamedElementUtil.QUALIFIED_NAME_SEPARATOR + memberName);
+ }
+ }
+ if (manageDuplicate) {
+ shortestNames.removeAll(NameResolutionUtils.findAmbiguousNames(shortestNames, element, scope));
+ }
+ }
+ }
+ }
+ return shortestNames;
+ }
+
+ /**
+ * From a list of names, select the names which do not unambiguously resolve to researchedElement,
+ * in the context of scope
+ *
+ * @param names
+ * , the list of names to evaluate
+ * @param researchedElement
+ * , the element that must be resolved from the names
+ * @param scope
+ * , the scope in which evaluation happens
+ * @return the list of names which are ambiguous
+ */
+ private static final List<String> findAmbiguousNames(final List<String> names, final NamedElement researchedElement, final Namespace scope) {
+ final List<String> ambiguousNames = new ArrayList<String>();
+ for (final String name : names) {
+ if (NameResolutionUtils.isQualifiedNameAmbiguous(name, researchedElement, scope)) {
+ ambiguousNames.add("" + name);
+ }
+ }
+ return ambiguousNames;
+ }
+
+
+ /**
+ * Determines if a given name is ambiguous. From a given scope where evaluation of the name happens,
+ * a name is ambiguous if:
+ * - The given name resolves to multiple elements,
+ * - Or the name resolves to one element which is not the researched element.
+ * This method relies on getNamedElements(String, Element, EClass), using researchedElement.eClass() as a filter.
+ *
+ * @param name
+ * @param researchedElement
+ * @param scope
+ * @return
+ */
+ private static final boolean isQualifiedNameAmbiguous(final String name, final NamedElement researchedElement, final Namespace scope) {
+ final List<NamedElement> resolvedElements = NameResolutionUtils.getNamedElements(name, scope, researchedElement.eClass());
+ if (resolvedElements.size() > 1) {
+ return true;
+ }
+ if (resolvedElements.get(0) != researchedElement) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/util/UMLReferenceConverter.java b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/util/UMLReferenceConverter.java
index 7c8b4feff0b..4a1f8d7d287 100644
--- a/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/util/UMLReferenceConverter.java
+++ b/plugins/uml/tools/org.eclipse.papyrus.uml.tools/src/org/eclipse/papyrus/uml/tools/util/UMLReferenceConverter.java
@@ -129,7 +129,6 @@ public class UMLReferenceConverter implements IPapyrusConverter {
for (String string2 : names) {
List<?> values = sharedResolutionHelper.getElementsByName(string2);
if (values.size() > 0) {
- Assert.isTrue(values.size() == 1);
elements.add((NamedElement) values.get(0));
}
}
@@ -167,16 +166,18 @@ public class UMLReferenceConverter implements IPapyrusConverter {
* @return
* the name of the named element, starting and ending with {@link #STRING_DELIMITER} if its name contains {@link #STRING_DELIMITER}
*/
- protected String getElementNameWithDelimiterIfRequired(NamedElement namedElement) {
- StringBuffer builder = new StringBuffer();
- List<String> names = sharedResolutionHelper.getShortestQualifiedNames(namedElement);
- String name = names.get(0);
- if (name.contains(STRING_SEPARATOR)) {
- builder.append(STRING_DELIMITER);
- builder.append(name);
- builder.append(STRING_DELIMITER);
- } else {
- builder.append(name);
+ protected String getElementNameWithDelimiterIfRequired(final NamedElement namedElement) {
+ final StringBuilder builder = new StringBuilder();
+ final List<String> names = sharedResolutionHelper.getShortestQualifiedNames(namedElement, true);
+ if(!names.isEmpty()){
+ String name = names.get(0);
+ if (name.contains(STRING_SEPARATOR)) {
+ builder.append(STRING_DELIMITER);
+ builder.append(name);
+ builder.append(STRING_DELIMITER);
+ } else {
+ builder.append(name);
+ }
}
return builder.toString();
}
@@ -237,12 +238,24 @@ public class UMLReferenceConverter implements IPapyrusConverter {
/**
- * @param namedElement
- * @return
- * the shortest qualified to use for the element
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper#getShortestQualifiedNames(java.lang.Object)
+ * @deprecated since 1.2.0
+ */
+ @Override
+ public List<String> getShortestQualifiedNames(final Object element) {
+ return this.sharedResolutionHelper.getShortestQualifiedNames(element, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.papyrus.infra.widgets.util.INameResolutionHelper#getShortestQualifiedNames(java.lang.Object, boolean)
*/
- public List<String> getShortestQualifiedNames(Object element) {
- return this.sharedResolutionHelper.getShortestQualifiedNames(element);
+ @Override
+ public List<String> getShortestQualifiedNames(final Object element, final boolean manageDuplicate) {
+ return this.sharedResolutionHelper.getShortestQualifiedNames(element, manageDuplicate);
}
/**
@@ -268,7 +281,7 @@ public class UMLReferenceConverter implements IPapyrusConverter {
while (iter.hasNext()) {
Object tmp = iter.next();
Assert.isTrue(tmp instanceof NamedElement);
- List<String> names = getShortestQualifiedNames(tmp);
+ List<String> names = getShortestQualifiedNames(tmp, false);
if (names.size() > 0) {
builder.append(names.get(0));
}
@@ -280,7 +293,7 @@ public class UMLReferenceConverter implements IPapyrusConverter {
} else if (object instanceof EObject) {
EObject eobject = (EObject) object;
Assert.isTrue(eobject instanceof NamedElement);
- List<String> names = getShortestQualifiedNames(eobject);
+ List<String> names = getShortestQualifiedNames(eobject, false);
if (names.size() > 0) {
return names.get(0);
}

Back to the top