package cn.liutils.ripple;
/**
* Path for script objects (functions and values).
* @author acaly
*
*/
public final class Path {
public static final String pathRegex = "\\w+(.\\w+)*";
/**
* The string value of this path.
* Allows null. When path is null, it represents the root namespace.
*/
public final String path;
public Path(String path) {
this.path = path;
if (!isValid(this.path))
throw new RippleException("Invalid path");
}
public Path(Path parent, String sub) {
if (parent.path == null) {
this.path = sub;
} else {
this.path = parent.path + '.' + sub;
}
if (!isValid(this.path))
throw new RippleException("Invalid path");
}
public Path(Path parent, Path sub) {
if (parent.path == null) {
this.path = sub.path;
} else {
this.path = parent.path + '.' + sub.path;
}
if (!isValid(this.path))
throw new RippleException("Invalid path");
}
public boolean hasParent() {
return path != null;
}
public Path getParent() {
if (!hasParent()) {
throw new RuntimeException("Try to get parent of the root namespace");
}
int id = path.lastIndexOf('.');
if (id == -1) {
return new Path(null);
}
return new Path(path.substring(0, id));
}
public static boolean isValid(String path) {
return path == null || path.matches(pathRegex);
}
public static Path concatenate(Path a, Path b) {
if (b.path == null) {
throw new RuntimeException("Try to concatenate null paths");
}
if (a.path == null) {
return b;
}
String matchA = '.' + a.path + '.';
int indexInB = b.path.indexOf('.');
if (indexInB == -1) {
return b;
}
String matchB = b.path.substring(0, indexInB);
int matching = matchA.indexOf('.' + matchB + '.');
if (matching == -1) {
return b;
}
return new Path(a.path.substring(0, matching) + b.path);
}
@Override
public String toString() {
return path;
}
}