package com.googlecode.totallylazy.xml.streaming;
import com.googlecode.totallylazy.functions.Function1;
import com.googlecode.totallylazy.Option;
import com.googlecode.totallylazy.predicates.Predicate;
import com.googlecode.totallylazy.predicates.Predicates;
import com.googlecode.totallylazy.collections.PersistentList;
import com.googlecode.totallylazy.predicates.LogicalPredicate;
import static com.googlecode.totallylazy.Option.none;
import static com.googlecode.totallylazy.Option.some;
import static com.googlecode.totallylazy.predicates.Predicates.is;
import static com.googlecode.totallylazy.Sequences.sequence;
import static com.googlecode.totallylazy.functions.Compose.compose;
import static com.googlecode.totallylazy.predicates.LogicalPredicate.logicalPredicate;
public class XPath {
public static LogicalPredicate<Node> name(String value) {
return name(value.equals("*") ? Predicates.any() : is(value));
}
public static LogicalPredicate<Node> name(Predicate<? super String> predicate) {
return logicalPredicate((Node element) -> element.isElement() && predicate.matches(element.name()));
}
public static LogicalPredicate<Node> attribute(String name, Predicate<? super String> predicate) {
return logicalPredicate((Node node) -> predicate.matches(node.attributes().get(name)));
}
public static Function1<PersistentList<Node>, Option<PersistentList<Node>>> descendant(String name) {
return descendant(name(name));
}
public static Function1<PersistentList<Node>, Option<PersistentList<Node>>> descendant(Predicate<? super Node> predicate) {
return steps -> descendant(predicate, steps);
}
private static Option<PersistentList<Node>> descendant(Predicate<? super Node> predicate, PersistentList<Node> steps) {
return steps.tails().toSequence().
filter(tail -> predicate.matches(tail.head())).
lastOption().
map(PersistentList::tail);
}
public static Function1<PersistentList<Node>, Option<PersistentList<Node>>> child(String name) {
return child(name(name));
}
public static Function1<PersistentList<Node>, Option<PersistentList<Node>>> child(Predicate<? super Node> predicate) {
return steps -> {
if (steps.headOption().is(predicate)) return some(steps.tail());
return none();
};
}
public static LogicalPredicate<Node> text() {
return logicalPredicate(Node::isText);
}
@SafeVarargs
public static Predicate<Context> xpath(Function1<? super PersistentList<Node>, ? extends Option<PersistentList<Node>>>... steps) {
return context -> sequence(steps).
fold(some(context.path()), Option::flatMap).
contains(PersistentList.constructors.empty());
}
public static Predicate<Node> node() {
return Predicates.any();
}
}