com.github.simy4.xpath.expr.AxisStepExpr Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xpath-to-xml-core Show documentation
Show all versions of xpath-to-xml-core Show documentation
Convenient utility to build XML models by evaluating XPath expressions
package com.github.simy4.xpath.expr;
import com.github.simy4.xpath.XmlBuilderException;
import com.github.simy4.xpath.expr.axis.AxisResolver;
import com.github.simy4.xpath.navigator.Node;
import com.github.simy4.xpath.util.FilteringIterator;
import com.github.simy4.xpath.util.Function;
import com.github.simy4.xpath.util.Predicate;
import com.github.simy4.xpath.util.TransformingIterator;
import com.github.simy4.xpath.view.IterableNodeView;
import com.github.simy4.xpath.view.NodeSetView;
import com.github.simy4.xpath.view.NodeView;
import com.github.simy4.xpath.view.View;
import com.github.simy4.xpath.view.ViewContext;
import java.util.Iterator;
public class AxisStepExpr implements StepExpr {
private final AxisResolver axisResolver;
private final Iterable predicates;
public AxisStepExpr(AxisResolver axisResolver, Iterable predicates) {
this.axisResolver = axisResolver;
this.predicates = predicates;
}
@Override
public final IterableNodeView resolve(ViewContext context) throws XmlBuilderException {
IterableNodeView result = axisResolver.resolveAxis(context);
for (Expr predicate : predicates) {
result = resolvePredicate(context, result, predicate);
}
return result;
}
private IterableNodeView resolvePredicate(final ViewContext context,
final IterableNodeView filtered,
final Expr predicate) throws XmlBuilderException {
final PredicateContext predicateContext = new PredicateContext();
IterableNodeView result = new NodeSetView(new Iterable>() {
@Override
public Iterator> iterator() {
final Iterator> iterator = filtered.iterator();
return new FilteringIterator>(
new TransformingIterator, NodeView>(iterator, predicateContext),
new PredicateResolver(context, iterator, predicate));
}
});
if (context.isGreedy() && !context.hasNext() && !result.toBoolean()) {
final NodeView last = predicateContext.last;
final int position = predicateContext.position;
final NodeView newNode;
final ViewContext newContext;
if (null != last && last.isNew()) {
newNode = last;
newContext = new ViewContext(context.getNavigator(), last, true, false, position);
} else {
newNode = axisResolver.createAxisNode(context);
newContext = new ViewContext(context.getNavigator(), newNode, true, false, position + 1);
}
final View resolve = predicate.resolve(newContext);
if (!resolve.toBoolean()) {
throw new XmlBuilderException("Unable to satisfy expression predicate: " + predicate);
}
result = newNode;
}
return result;
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder(axisResolver.toString());
for (Expr predicate : predicates) {
stringBuilder.append(predicate);
}
return stringBuilder.toString();
}
private static final class PredicateResolver implements Predicate> {
private final ViewContext parentContext;
private final Iterator> iterator;
private final Expr predicate;
private int position = 1;
private PredicateResolver(ViewContext parentContext, Iterator> iterator, Expr predicate) {
this.parentContext = parentContext;
this.iterator = iterator;
this.predicate = predicate;
}
@Override
public boolean test(NodeView view) {
final ViewContext context = new ViewContext(parentContext.getNavigator(), view, false,
iterator.hasNext(), position++);
return predicate.resolve(context).toBoolean();
}
}
private static final class PredicateContext implements Function, NodeView> {
private NodeView last;
private int position;
@Override
public NodeView apply(NodeView view) {
if (null == last || !last.isNew()) {
last = view;
position++;
}
return view;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy