org.eclipse.xtext.naming.QualifiedName Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2010 itemis AG (http://www.itemis.eu) 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
*******************************************************************************/
package org.eclipse.xtext.naming;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream;
import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectOutputStream;
import org.eclipse.xtext.util.Strings;
import com.google.common.base.Function;
/**
* A datatype for dealing with qualified names.
* Instances are usually provided by a {@link IQualifiedNameProvider}.
*
* @author Jan Koehnlein - Initial contribution and API
* @author Sebastian Zarnekow
*/
public class QualifiedName implements Comparable {
private final int hash;
private final String[] segments;
private QualifiedName lowerCase;
public static final QualifiedName EMPTY = new QualifiedName() {
@Override
public QualifiedName append(QualifiedName relativeQualifiedName) {
return relativeQualifiedName;
}
@Override
public QualifiedName append(String segment) {
return QualifiedName.create(segment);
}
@Override
public QualifiedName toLowerCase() {
return this;
}
@Override
public QualifiedName toUpperCase() {
return this;
}
};
/**
* Low-level factory method. Consider using a {@link IQualifiedNameConverter} instead.
*
* @param segments the segments of the to-be-created qualified name.
* May be null
, but may not contain null
entries.
* @return a {@link QualifiedName}. Never null
.
* @exception IllegalArgumentException
* if any of the segments is null
*/
public static QualifiedName create(String... segments) {
if (segments == null || segments.length == 0) {
return EMPTY;
}
if (segments.length == 1) {
return create(segments[0]);
}
for (int i = 0; i < segments.length; i++) {
if (segments[i] == null) {
throw new IllegalArgumentException("Segment cannot be null");
}
}
return new QualifiedName(segments.clone());
}
/**
* Internal low level factory method.
* @noreference This method is not intended to be referenced by clients.
* @since 2.4
*/
public static QualifiedName createFromStream(EObjectInputStream eObjectInputStream) throws IOException{
int segmentCount = eObjectInputStream.readCompressedInt();
if (segmentCount == 0) {
return QualifiedName.EMPTY;
}
String[] segments = new String[segmentCount];
for (int i = 0; i < segmentCount; ++i) {
segments[i] = eObjectInputStream.readSegmentedString();
}
return new QualifiedName(segments);
}
/**
* Internal low level serialization of QualifiedNames.
* @since 2.4
*/
public void writeToStream(EObjectOutputStream eObjectOutputStream) throws IOException {
int segmentCount = getSegmentCount();
eObjectOutputStream.writeCompressedInt(segmentCount);
for (int i = 0; i < segmentCount; ++i) {
eObjectOutputStream.writeSegmentedString(getSegment(i));
}
}
/**
* Low-level factory method. Consider using a {@link IQualifiedNameConverter} instead.
*
* @param segments
* the segments of the to-be-created qualified name. May be null
, but may not contain
* null
entries.
* @return a {@link QualifiedName}. Never null
.
* @exception IllegalArgumentException
* if any of the segments is null
* @since 2.3
*/
public static QualifiedName create(List segments) {
if (segments == null || segments.isEmpty())
return QualifiedName.EMPTY;
if (segments.size() == 1) {
String singleSegment = segments.get(0);
return QualifiedName.create(singleSegment);
}
String[] segmentArray = segments.toArray(new String[segments.size()]);
for (int i = 0; i < segmentArray.length; i++) {
if (segmentArray[i] == null) {
throw new IllegalArgumentException("Segment cannot be null");
}
}
return new QualifiedName(segmentArray);
}
/**
* Low-level factory method. Consider using a {@link IQualifiedNameConverter} instead.
*
* @param singleSegment
* the single segment of the newly created qualified name
* @exception IllegalArgumentException
* if the singleSegment is null
* @since 2.3
*/
public static QualifiedName create(String singleSegment) {
if (singleSegment == null) {
throw new IllegalArgumentException("Segment cannot be null");
}
return new QualifiedName(singleSegment);
}
/**
* Wraps a name function to return a qualified name. Returns null if the name function returns null.
*/
public static Function wrapper(final Function nameFunction) {
return new Function() {
public QualifiedName apply(F from) {
String name = nameFunction.apply(from);
if (name == null)
return null;
return QualifiedName.create(name);
}
};
}
protected QualifiedName(String... segments) {
if (segments == null || segments.length == 0)
this.segments = Strings.EMPTY_ARRAY;
else
this.segments = segments;
hash = Arrays.hashCode(this.segments);
}
public boolean isEmpty() {
return segments.length == 0;
}
public List getSegments() {
return Collections.unmodifiableList(Arrays.asList(segments));
}
public int getSegmentCount() {
return segments.length;
}
public String getSegment(int index) {
return segments[index];
}
public String getLastSegment() {
return segments[segments.length - 1];
}
public String getFirstSegment() {
return segments[0];
}
public QualifiedName append(String segment) {
if (segment == null) {
throw new IllegalArgumentException("Segment cannot be null");
}
String[] newSegments = new String[getSegmentCount() + 1];
System.arraycopy(segments, 0, newSegments, 0, segments.length);
newSegments[segments.length] = segment;
return new QualifiedName(newSegments);
}
public QualifiedName append(QualifiedName relativeQualifiedName) {
String[] newSegments = new String[getSegmentCount() + relativeQualifiedName.getSegmentCount()];
for (int i = 0; i < getSegmentCount(); ++i)
newSegments[i] = getSegment(i);
for (int i = 0; i < relativeQualifiedName.getSegmentCount(); ++i)
newSegments[i + getSegmentCount()] = relativeQualifiedName.getSegment(i);
return new QualifiedName(newSegments);
}
public QualifiedName skipFirst(int skipCount) {
if (skipCount == getSegmentCount()) {
return EMPTY;
}
if (skipCount > getSegmentCount() || skipCount < 0) {
throw new IllegalArgumentException("Cannot skip " + skipCount + " fragments from QualifiedName with "
+ getSegmentCount() + " segments");
}
String[] newSegments = new String[segments.length - skipCount];
System.arraycopy(segments, skipCount, newSegments, 0, newSegments.length);
return new QualifiedName(newSegments);
}
public QualifiedName skipLast(int skipCount) {
if (skipCount == getSegmentCount()) {
return EMPTY;
}
if (skipCount > getSegmentCount() || skipCount < 0) {
throw new IllegalArgumentException("Cannot skip " + skipCount + " fragments from QualifiedName with "
+ getSegmentCount() + " segments");
}
String[] newSegments = new String[segments.length - skipCount];
System.arraycopy(segments, 0, newSegments, 0, newSegments.length);
return new QualifiedName(newSegments);
}
public QualifiedName toLowerCase() {
if (lowerCase != null)
return lowerCase;
String[] newSegments = new String[segments.length];
for (int i = 0; i < getSegmentCount(); ++i)
newSegments[i] = segments[i].toLowerCase();
lowerCase = new QualifiedName(newSegments) {
@Override
public QualifiedName toLowerCase() {
return this;
}
};
return lowerCase;
}
public QualifiedName toUpperCase() {
String[] newSegments = new String[getSegmentCount()];
for (int i = 0; i < getSegmentCount(); ++i)
newSegments[i] = segments[i].toUpperCase();
return new QualifiedName(newSegments);
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj==this)
return true;
if (obj instanceof QualifiedName) {
QualifiedName other = (QualifiedName) obj;
if (hash != other.hash)
return false;
return Arrays.equals(segments, other.segments);
}
return false;
}
public boolean equalsIgnoreCase(Object obj) {
return obj instanceof QualifiedName && ((QualifiedName) obj).getSegmentCount() == getSegmentCount()
&& startsWith((QualifiedName) obj, true);
}
public int compareTo(QualifiedName qualifiedName) {
return compareTo(qualifiedName, false);
}
public int compareToIgnoreCase(QualifiedName qualifiedName) {
return compareTo(qualifiedName, true);
}
protected int compareTo(QualifiedName qualifiedName, boolean ignoreCase) {
for (int i = 0; i < Math.min(getSegmentCount(), qualifiedName.getSegmentCount()); ++i) {
int result = (ignoreCase) ? getSegment(i).compareToIgnoreCase(qualifiedName.getSegment(i)) : getSegment(i)
.compareTo(qualifiedName.getSegment(i));
if (result != 0)
return result;
}
return getSegmentCount() - qualifiedName.getSegmentCount();
}
public boolean startsWith(QualifiedName prefix) {
return startsWith(prefix, false);
}
public boolean startsWithIgnoreCase(QualifiedName prefix) {
return startsWith(prefix, true);
}
protected boolean startsWith(QualifiedName prefix, boolean ignoreCase) {
if (prefix.getSegmentCount() > getSegmentCount())
return false;
for (int i = 0; i < prefix.getSegmentCount(); ++i) {
if ((ignoreCase && !this.getSegment(i).equalsIgnoreCase(prefix.getSegment(i)))
|| (!ignoreCase && !this.getSegment(i).equals(prefix.getSegment(i))))
return false;
}
return true;
}
/**
* Returns a canonical String representation of this using '.' as namespace delimiter. For language specific
* conversion taking the concrete syntax into account see {@link IQualifiedNameConverter#toString(QualifiedName)}.
*/
@Override
public String toString() {
return toString(".");
}
/**
* Returns a String representation of this using {@code delimiter} as namespace delimiter.
* @param delimiter the delimiter to use. null
will be represented as the String "null
".
* @return the concatenated segments joined with the given {@code delimiter}
* @since 2.3
*/
public String toString(String delimiter) {
int segmentCount = getSegmentCount();
switch (segmentCount) {
case 0: return "";
case 1: return getFirstSegment();
default:
StringBuilder builder = new StringBuilder();
for (int i = 0; i < segmentCount; i++) {
if (i > 0)
builder.append(delimiter);
builder.append(segments[i]);
}
return builder.toString();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy