package edu.uw.zookeeper.data;
/**
* Can be empty.
*/
public final class RelativeZNodePath extends ZNodeLabelVector {
/**
* @param path to be validated
* @return path
*/
public static String validate(String path) {
return validate(path, 0, path.length());
}
public static <T extends CharSequence> T validate(T path, int start, int end) {
if (start < end) {
int lastSlash = start-1;
for (int i=start; i<end; ++i) {
char c = path.charAt(i);
if ((c == SLASH) || (i == end - 1)) {
if (i > start) {
int labelEnd;
if (c == SLASH) {
if (i == end - 1) {
throw new IllegalArgumentException(String.format("Trailing slash at index %d in %s", i, path));
}
labelEnd = i;
} else {
labelEnd = i+1;
}
int labelStart = lastSlash + 1;
ZNodeLabel.validate(path, labelStart, labelEnd);
for (ZNodeLabel illegal: ILLEGAL_LABELS) {
int j;
for (j=0; (j<labelEnd-labelStart) && (j<illegal.length()) && (path.charAt(labelStart+j) == illegal.charAt(j)); j++) {
}
if (j == labelEnd-labelStart) {
throw new IllegalArgumentException(String.format("Illegal label at index %d in %s", labelStart, path));
}
}
}
if (c == SLASH) {
if (i == start) {
throw new IllegalArgumentException(String.format("Leading slash at index %d in %s", i, path));
}
lastSlash = i;
}
}
}
if (lastSlash < start) {
throw new IllegalArgumentException(String.format("No slash in index range [%d,%d) for %s", start, end, path));
}
} else {
throw new IllegalArgumentException(String.format("Empty index range [%d,%d) for %s", start, end, path));
}
return path;
}
@Serializes(from=String.class, to=RelativeZNodePath.class)
public static RelativeZNodePath validated(String path) {
return fromString(validate(path));
}
@Serializes(from=String.class, to=RelativeZNodePath.class)
public static RelativeZNodePath fromString(String path) {
return new RelativeZNodePath(path);
}
public static RelativeZNodePath empty() {
return new RelativeZNodePath("");
}
private static final ZNodeLabel[] ILLEGAL_LABELS = { ZNodeLabel.self(), ZNodeLabel.parent() };
private RelativeZNodePath(String label) {
super(label);
}
@Override
public boolean isAbsolute() {
return false;
}
@Override
public RelativeZNodePath join(ZNodeName other) {
String suffix = other.toString();
if (suffix.isEmpty()) {
return this;
} else if (suffix.charAt(0) == SLASH) {
throw new IllegalArgumentException(suffix);
}
return RelativeZNodePath.fromString(new StringBuilder(length() + suffix.length() + 1).append(toString()).append(SLASH).append(suffix).toString());
}
}