[578981] Avoid redundant path qualifiers
diff --git a/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/as2cs/AS2CSConversion.java b/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/as2cs/AS2CSConversion.java
index ea31409..2d5ff93 100644
--- a/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/as2cs/AS2CSConversion.java
+++ b/plugins/org.eclipse.ocl.xtext.base/src/org/eclipse/ocl/xtext/base/as2cs/AS2CSConversion.java
@@ -30,12 +30,14 @@
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.ocl.pivot.CollectionType;
+import org.eclipse.ocl.pivot.CompleteClass;
 import org.eclipse.ocl.pivot.CompletePackage;
 import org.eclipse.ocl.pivot.Element;
 import org.eclipse.ocl.pivot.MapType;
 import org.eclipse.ocl.pivot.Model;
 import org.eclipse.ocl.pivot.NamedElement;
 import org.eclipse.ocl.pivot.Namespace;
+import org.eclipse.ocl.pivot.Operation;
 import org.eclipse.ocl.pivot.Package;
 import org.eclipse.ocl.pivot.PivotPackage;
 import org.eclipse.ocl.pivot.Property;
@@ -84,6 +86,8 @@
 import org.eclipse.ocl.xtext.basecs.TypedRefCS;
 import org.eclipse.ocl.xtext.basecs.TypedTypeRefCS;
 
+import com.google.common.collect.Iterables;
+
 public class AS2CSConversion extends AbstractConversion implements PivotConstantsInternal
 {
 	private static final Logger logger = Logger.getLogger(AS2CSConversion.class);
@@ -324,6 +328,29 @@
 		}
 	}
 
+	/**
+	 * Return the qualifying NamedElement path from global to element (inclusive if a NamedElement).
+	 */
+	private @NonNull List<@NonNull NamedElement> getPath(@NonNull Element element) {
+		List<@NonNull NamedElement> path = new ArrayList<>();
+		for (EObject eContainer = element/*.eContainer()*/; eContainer instanceof Element; eContainer = eContainer.eContainer()) {
+			eContainer = metamodelManager.getPrimaryElement(eContainer);
+			if (eContainer instanceof Model) {
+				break;				// Skip root Model
+			}
+			if ((eContainer instanceof org.eclipse.ocl.pivot.Package) && Orphanage.isTypeOrphanage((org.eclipse.ocl.pivot.Package)eContainer)) {
+				break;				// Skip orphan package
+			}
+			if (eContainer instanceof TemplateSignature) {
+				continue;			// Skip signature
+			}
+			if (eContainer instanceof NamedElement) {
+				path.add(0, (NamedElement)eContainer);
+			}
+		}
+		return path;
+	}
+
 	public @NonNull PrecedenceManager getPrecedenceManager() {
 		return metamodelManager.getPrecedenceManager();
 	}
@@ -450,56 +477,89 @@
 	 * that the result is C::D::E.
 	 */
 	public void refreshPathName(@NonNull PathNameCS csPathName, @NonNull Element element, @Nullable Namespace scope) {//, @Nullable Resource csResource) {
-		Namespace safeScope = scope;
+		boolean hasFinalTarget = false;
+		List<PathElementCS> csPath = csPathName.getOwnedPathElements();
+		csPath.clear();		// FIXME re-use
 		Element primaryElement = metamodelManager.getPrimaryElement(element);
-		if ((safeScope != null) && (primaryElement instanceof Type)) {
-			String name = ((Type)primaryElement).getName();
-			for (EObject eObject = safeScope; eObject != null; eObject = eObject.eContainer()) {
-				if (eObject instanceof Namespace) {
-					safeScope = (Namespace) eObject;
-				}
-				if (eObject instanceof org.eclipse.ocl.pivot.Package) {
-					CompletePackage completePackage = metamodelManager.getCompletePackage((org.eclipse.ocl.pivot.Package)eObject);
-					org.eclipse.ocl.pivot.Class memberType = completePackage.getMemberType(name);
-					if (memberType == primaryElement) {
-						if ((eObject != scope) && (eObject != PivotUtil.getContainingPackage(scope))) {
-							eObject = eObject.eContainer(); // If eObject is needed in path, optional scope is its container
-						}
-						if (eObject instanceof Namespace) {
-							safeScope = (Namespace) eObject;
-						}
+		BaseCSResource csResource2 = this.csResource;
+		if ((csResource2 != null) && (csResource2.isPathable(primaryElement) != null)) {
+			List<@NonNull NamedElement> targetPath = getPath(element);
+			int iTargetStart = 0;
+			int iTargetSize = targetPath.size();
+			if ((scope != null) && (0 < iTargetSize)) {
+				List<@NonNull NamedElement> scopePath = getPath(scope);
+				int iScopeSize = scopePath.size();
+				int iMax = Math.min(iTargetSize, iScopeSize);
+				//
+				//	Necessary outer qualification, keep the common element of target and scope Path
+				//
+				for ( ; iTargetStart < iMax; iTargetStart++) {
+					NamedElement targetChildElement = targetPath.get(iTargetStart);
+					NamedElement scopeChildElement = scopePath.get(iTargetStart);
+					if (targetChildElement != scopeChildElement) {
 						break;
 					}
 				}
-			}
-		}
-		List<PathElementCS> csPath = csPathName.getOwnedPathElements();
-		csPath.clear();		// FIXME re-use
-		PathElementCS csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementCS();
-		csPath.add(csSimpleRef);
-		csSimpleRef.setReferredElement(primaryElement);
-		BaseCSResource csResource2 = this.csResource;
-		if ((csResource2 == null) || (csResource2.isPathable(primaryElement) == null)) {
-			return;
-		}
-		for (EObject eContainer = primaryElement.eContainer(); eContainer instanceof Element; eContainer = eContainer.eContainer()) {
-			if (eContainer instanceof Model) {
-				return;				// Skip root package
-			}
-			if ((eContainer instanceof org.eclipse.ocl.pivot.Package) && Orphanage.isTypeOrphanage((org.eclipse.ocl.pivot.Package)eContainer)) {
-				return;				// Skip orphan package
-			}
-			if (eContainer instanceof TemplateSignature) {
-				continue;			// Skip signature
-			}
-			for (EObject aScope = safeScope; aScope != null; aScope = aScope.eContainer()) {
-				if (metamodelManager.getPrimaryElement(aScope) == metamodelManager.getPrimaryElement(eContainer)) { 		// If element ancestor is scope or an ancestor
-					return;							// no need for further qualification
+				//
+				//	Redundant inner qualification no alternative resolutions for first qualifier.
+				//
+				if ((0 < iTargetStart) && (iTargetStart < iTargetSize)) {
+					String targetName = targetPath.get(iTargetStart).getName(); //((NamedElement)primaryElement).getName();
+					boolean noAlternatives = true;
+					for (int i = iTargetStart; i < iScopeSize-1; i++) {
+						NamedElement intermediateScopeElement = scopePath.get(i);
+						if (intermediateScopeElement instanceof org.eclipse.ocl.pivot.Package) {
+							CompletePackage completePackage = metamodelManager.getCompletePackage((org.eclipse.ocl.pivot.Package)intermediateScopeElement);
+							CompletePackage memberPackage = completePackage.getOwnedCompletePackage(targetName);
+							if (memberPackage != null) {
+								noAlternatives = false;
+								break;
+							}
+							org.eclipse.ocl.pivot.Class memberClass = completePackage.getMemberType(targetName);
+							if (memberClass  != null) {
+								noAlternatives = false;
+								break;
+							}
+						}
+						else if (intermediateScopeElement instanceof org.eclipse.ocl.pivot.Class) {
+							CompleteClass completeClass = metamodelManager.getCompleteClass((org.eclipse.ocl.pivot.Class)intermediateScopeElement);
+							Iterable<@NonNull Property> memberProperties = completeClass.getProperties((Property)primaryElement);
+							if ((memberProperties != null) && !Iterables.isEmpty(memberProperties)) {
+								noAlternatives = false;
+								break;
+							}
+							Iterable<@NonNull Operation> memberOperations = completeClass.getOperations(null, targetName);
+							assert memberOperations != null;
+							if (!Iterables.isEmpty(memberOperations)) {
+								noAlternatives = false;
+								break;
+							}
+						}
+					}
+					if (!noAlternatives) {
+						iTargetStart = iTargetStart-1;
+					}
 				}
 			}
-			csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementCS();
-			csPath.add(0, csSimpleRef);
-			csSimpleRef.setReferredElement((Element) eContainer);
+			//
+			//	Refresh with targetPath[iTargetStart...iTargetSize]
+			//
+			for (int i = iTargetStart; i < iTargetSize; i++) {
+				PathElementCS csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementCS();
+				NamedElement pathElement = targetPath.get(i);
+				csSimpleRef.setReferredElement(pathElement);
+				csPath.add(csSimpleRef);
+				if (pathElement == primaryElement) {
+					hasFinalTarget = true;
+					assert (i+1) == iTargetSize;
+					break;
+				}
+			}
+		}
+		if (!hasFinalTarget) {
+			PathElementCS csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementCS();
+			csSimpleRef.setReferredElement(primaryElement);
+			csPath.add(csSimpleRef);
 		}
 	}