/******************************************************************************* * Copyright (c) 2011, 2015 Willink Transformations 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: * E.D.Willink - initial API and implementation *******************************************************************************/ package org.eclipse.ocl.xtext.base.scoping; import java.util.ArrayList; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.ocl.pivot.NamedElement; import org.eclipse.ocl.pivot.internal.utilities.PathElement; import org.eclipse.ocl.xtext.base.as2cs.AliasAnalysis; import org.eclipse.ocl.xtext.basecs.PathElementCS; import org.eclipse.ocl.xtext.basecs.RootPackageCS; import org.eclipse.xtext.naming.QualifiedName; /** * QualifiedPath refines QualifiedName to use {name,element} pairs for each segment and support deresolution * with respect to another path or an object context. */ public class QualifiedPath extends QualifiedName { // Since the underlying class is immutable, it can be safely extended with further immutable content. private static String[] getSegments(List<PathElement> pathElements) { String[] segments = new String[pathElements.size()]; for (int i = 0; i < segments.length; i++) { segments[i] = pathElements.get(i).getName(); } return segments; } private final List<PathElement> pathElements; private final boolean isAbsolute; public QualifiedPath(List<PathElement> pathElements) { this(pathElements, true); } protected QualifiedPath(List<PathElement> pathElements, boolean isAbsolute) { super(getSegments(pathElements)); this.pathElements = pathElements; this.isAbsolute = isAbsolute; } public QualifiedPath deresolve(QualifiedPath contextPath) { List<PathElement> thisPath = pathElements; List<PathElement> thatPath = contextPath.pathElements; int iSize = thisPath.size(); if (iSize <= 0) { return this; } int i = PathElement.getCommonLength(thisPath, thatPath); if (i <= 0) { return this; } if (i >= iSize) { return this; } final List<PathElement> newPath = new ArrayList<PathElement>(); for ( ; i < iSize-1; i++) { newPath.add(thisPath.get(i)); } newPath.add(thisPath.get(iSize-1)); // Last segment mandatory return new QualifiedPath(newPath, false); } @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof QualifiedPath) { QualifiedPath other = (QualifiedPath) obj; if (hashCode() != other.hashCode()) return false; if (isAbsolute != other.isAbsolute) return false; int iMax = pathElements.size(); if (iMax != other.pathElements.size()) { return false; } for (int i = 0; i < iMax; i++) { if (!pathElements.get(i).equals(other.pathElements.get(i))) { return false; } } return true; } return super.equals(obj); } /** * Return the segments of this path, deresolving the first segment of an absolute path to use the * aliases of the resource of csObject. */ public List<String> getSegments(EObject csObject) { List<String> segments = new ArrayList<String>(); int segmentCount = getSegmentCount(); if (segmentCount == 0) { return segments; } if (isAbsolute) { EObject root = EcoreUtil.getRootContainer(csObject); Resource csResource = root.eResource(); Resource asResource = null; if (root instanceof RootPackageCS) { EObject root2 = ((RootPackageCS)root).getPivot(); asResource = EcoreUtil.getRootContainer(root2).eResource(); } EObject firstElement = null; if (csObject instanceof PathElementCS) { firstElement = ((PathElementCS)csObject).getReferredElement(); } else { firstElement = pathElements.get(0).getElement(); } if ((firstElement instanceof org.eclipse.ocl.pivot.Package) && !firstElement.eIsProxy()) { Resource elementResource = firstElement.eResource(); if ((csResource != null) && (elementResource != csResource) && (elementResource != asResource)) { AliasAnalysis adapter = AliasAnalysis.getAdapter(csResource); if (segmentCount == 1) { String alias = adapter.getAlias(firstElement, null); if (alias != null) { segments.add(alias); segments.add(getFirstSegment()); } } else { for (int i = segmentCount - 2; i >= 0; i--) { EObject element = pathElements.get(i).getElement(); if (element != null) { String alias = adapter.getAlias(element, null); if (alias != null) { segments.add(alias); if (segmentCount == 1) { segments.add(((NamedElement)firstElement).getName()); } else { for (i++; i < segmentCount; i++) { segments.add(getSegment(i)); } } return segments; } } } } } } } if (segments.size() == 0) { segments.add(getFirstSegment()); } for (int i = 1; i < segmentCount; i++) { segments.add(getSegment(i)); } return segments; } @Override public String toString() { if (getSegmentCount() == 0) return ""; if (getSegmentCount() == 1) return getFirstSegment(); StringBuilder builder = new StringBuilder(); boolean isFirst = true; for (String segment : getSegments()) { if (!isFirst) builder.append("::"); isFirst = false; builder.append(segment); } return builder.toString(); } }