![JAR search and dependency download from the Maven repository](/logo.png)
io.nextop.Path Maven / Gradle / Ivy
package io.nextop;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import rx.functions.Func1;
import javax.annotation.Nullable;
import java.net.URISyntaxException;
import java.util.*;
import java.util.regex.Pattern;
// paths can use "$var" segments
// optionally starts with a '/', see Urls.parseSegments
public class Path {
public static Path valueOf(String s) {
final int n = s.length();
int j;
if (0 < n && '/' == s.charAt(0)) {
j = 1;
} else {
j = 0;
}
LinkedList segments = new LinkedList();
for (int i = j; i < n; ++i) {
char c = s.charAt(i);
if ('?' == c || '#' == c) {
segments.add(Segment.valueOf(s.substring(j, i)));
j = n;
break;
}
if ('/' == c) {
segments.add(Segment.valueOf(s.substring(j, i)));
j = i + 1;
}
}
if (j < n) {
segments.add(Segment.valueOf(s.substring(j, n)));
}
return new Path(ImmutableList.copyOf(segments));
}
public static Path empty() {
return new Path(Collections.emptyList());
}
public final List segments;
private Path(List segments) {
this.segments = segments;
}
public Path append(String s) {
return append(valueOf(s));
}
public Path append(Path suffix) {
return new Path(ImmutableList.copyOf(Iterables.concat(segments, suffix.segments)));
}
public boolean startsWith(Path prefix) {
int n = prefix.segments.size();
int m = segments.size();
if (m < n) {
return false;
}
for (int i = 0; i < n; ++i) {
if (!segments.get(i).equals(prefix.segments.get(i))) {
return false;
}
}
return true;
}
public boolean endsWidth(Path suffix) {
int n = suffix.segments.size();
int m = segments.size();
if (m < n) {
return false;
}
for (int i = 0; i < n; ++i) {
if (!segments.get(m - 1 - i).equals(suffix.segments.get(n - 1 - i))) {
return false;
}
}
return true;
}
////// FIXED ///////
/* fixed means all segments are FIXED. To be fixed,
* VARIABLE need to be replaced with the variable values. */
public boolean isFixed() {
for (Segment segment : segments) {
if (!Segment.Type.FIXED.equals(segment.type)) {
return false;
}
}
return true;
}
public Path fix(Func1 subs) throws URISyntaxException {
int n = segments.size();
List fixedSegments = new ArrayList(n);
for (int i = 0; i < n; ++i) {
Segment segment = segments.get(i);
switch (segment.type) {
case FIXED:
fixedSegments.add(segment);
break;
case VARIABLE:
Segment subSegment;
@Nullable Object subValue = subs.call(segment.value);
if (null == subValue) {
throw new URISyntaxException(segment.toString(), "No substitution found.", i);
}
try {
subSegment = Segment.valueOf(subValue.toString());
} catch (IllegalArgumentException e) {
throw new URISyntaxException(segment.toString(), String.format("Substitution not a valid segment: %s", subValue), i);
}
if (!Segment.Type.FIXED.equals(subSegment.type)) {
throw new URISyntaxException(segment.toString(), String.format("Substitution not a fixed segment: %s", subSegment), i);
}
fixedSegments.add(subSegment);
break;
}
}
return new Path(fixedSegments);
}
@Override
public String toString() {
return "/" + Joiner.on("/").join(segments);
}
@Override
public int hashCode() {
return segments.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Path)) {
return false;
}
Path b = (Path) obj;
return segments.equals(b.segments);
}
public static final class Segment {
public static enum Type {
FIXED,
VARIABLE
}
private static Segment valueOf(String s) {
int n = s.length();
if (n <= 0) {
throw new IllegalArgumentException();
}
if ('$' == s.charAt(0)) {
String value = s.substring(1, n);
if (!M_VARIABLE.matcher(value).matches()) {
throw new IllegalArgumentException();
}
return new Segment(Type.VARIABLE, value);
} else {
String value = s;
if (!M_FIXED.matcher(value).matches()) {
throw new IllegalArgumentException();
}
return new Segment(Type.FIXED, value);
}
}
public final Type type;
public final String value;
private Segment(Type type, String value) {
this.type = type;
this.value = value;
}
@Override
public String toString() {
switch (type) {
case FIXED:
return value;
case VARIABLE:
return "$" + value;
default:
throw new IllegalStateException();
}
}
@Override
public int hashCode() {
int c = type.hashCode();
c = 31 * c + value.hashCode();
return c;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Segment)) {
return false;
}
Segment b = (Segment) obj;
return type.equals(b.type) && value.equals(b.value);
}
// FIXME ref spec
private static final Pattern M_FIXED = Pattern.compile("[a-z0-9-_;\\.]+");
private static final Pattern M_VARIABLE = Pattern.compile("[a-z0-9-\\.]+");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy