blob: d583eb4c436eb49448f62cf02ea930e9786589d9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2012 E.D.Willink 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.examples.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.examples.pivot.NamedElement;
import org.eclipse.ocl.examples.pivot.utilities.PathElement;
import org.eclipse.ocl.examples.xtext.base.basecs.PathElementCS;
import org.eclipse.ocl.examples.xtext.base.basecs.RootPackageCS;
import org.eclipse.ocl.examples.xtext.base.pivot2cs.AliasAnalysis;
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).getElement();
}
else {
firstElement = pathElements.get(0).getElement();
}
if (firstElement instanceof org.eclipse.ocl.examples.pivot.Package) {
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();
}
}