package ch.x42.terye;
import java.util.Arrays;
import javax.jcr.RepositoryException;
public class Path {
public static final String DELIMITER = "/";
// store path as a string for toString
private String path;
private String[] segments;
private boolean isAbsolute = false;
public Path(String path) {
// check if path is absolute
if (path.startsWith(Path.DELIMITER)) {
isAbsolute = true;
path = path.substring(1, path.length());
}
// remove trailing delimiter, if any
if (path.endsWith(Path.DELIMITER)) {
path = path.substring(0, path.length() - 1);
}
// split path into segments
if (path.isEmpty()) {
// split on empty string doesn't yield empty array
segments = new String[0];
} else {
segments = path.split(Path.DELIMITER);
}
}
private Path(String[] segments) {
isAbsolute = true;
this.segments = segments;
}
public static Path getCanonical(Path absBasePath, String relPath) throws RepositoryException {
Path relativePath = new Path(relPath);
if (!relativePath.isRelative()) {
throw new RepositoryException("Not a relative path: " + relPath);
}
return absBasePath.concat(relPath).getCanonical();
}
public boolean isAbsolute() {
return isAbsolute;
}
public boolean isRelative() {
return !isAbsolute();
}
public boolean isRoot() {
return isAbsolute() && segments.length == 0;
}
public Path concat(Path that) {
// make sure that lhs is absolute and rhs is relative
// -> yields an absolute path
if (isRelative()) {
throw new IllegalArgumentException("Concat cannot be called on a relative path");
} else if (that.isAbsolute()) {
throw new IllegalArgumentException("Specified path must be relative");
}
// concat segments and return new path
String[] segments = new String[this.segments.length + that.segments.length];
System.arraycopy(this.segments, 0, segments, 0, this.segments.length);
System.arraycopy(that.segments, 0, segments, this.segments.length, that.segments.length);
return new Path(segments);
}
public Path concat(String path) {
return concat(new Path(path));
}
public Path getCanonical() throws RepositoryException {
// XXX: implement
if (!isAbsolute()) {
throw new RepositoryException("Not an absolute path: " + toString());
}
return this;
}
public Path getParent() {
// should only be called on absolute paths
if (!isAbsolute()) {
throw new UnsupportedOperationException();
}
// return null for empty paths (root node or empty relative path)
if (segments.length == 0) {
return null;
}
return new Path(Arrays.copyOfRange(segments, 0, segments.length - 1));
}
public String getLastSegment() {
return segments.length > 0 ? segments[segments.length - 1] : "";
}
@Override
public String toString() {
if (path == null) {
path = isAbsolute ? Path.DELIMITER : "";
for (int i = 0; i < segments.length; i++) {
path += segments[i];
if (i < segments.length - 1) {
path += Path.DELIMITER;
}
}
}
return path;
}
}