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
/*
* Copyright 2017-2021 Alex Simkin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.Navigator;
import com.github.simy4.xpath.navigator.Node;
import com.github.simy4.xpath.util.Function;
import com.github.simy4.xpath.view.IterableNodeView;
import com.github.simy4.xpath.view.NodeSetView;
import com.github.simy4.xpath.view.NodeView;
import java.io.Serializable;
import java.util.Collection;
public class AxisStepExpr implements StepExpr, Serializable {
private static final long serialVersionUID = 1L;
private final AxisResolver axisResolver;
private final Collection predicates;
public AxisStepExpr(AxisResolver axisResolver, Collection predicates) {
this.axisResolver = axisResolver;
this.predicates = predicates;
}
@Override
public final IterableNodeView resolve(
Navigator navigator, NodeView view, boolean greedy) throws XmlBuilderException {
final boolean newGreedy = !view.hasNext() && greedy;
final IterableNodeView result = axisResolver.resolveAxis(navigator, view, newGreedy);
return resolvePredicates(navigator, view, result, newGreedy);
}
private IterableNodeView resolvePredicates(
Navigator navigator, NodeView view, IterableNodeView axis, boolean greedy)
throws XmlBuilderException {
IterableNodeView result = axis;
if (!predicates.isEmpty()) {
NodeSupplier nodeSupplier = new AxisNodeSupplier(navigator, axisResolver, view);
for (Expr predicate : predicates) {
final PredicateExpr predicateExpr = new PredicateExpr(predicate);
final PredicateResolver predicateResolver =
new PredicateResolver(navigator, nodeSupplier, predicateExpr, greedy);
result = result.flatMap(predicateResolver);
nodeSupplier = predicateResolver;
}
}
return result;
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder(axisResolver.toString());
for (Expr predicate : predicates) {
stringBuilder.append(predicate);
}
return stringBuilder.toString();
}
private interface NodeSupplier {
NodeView apply(int position) throws XmlBuilderException;
}
private static final class AxisNodeSupplier implements NodeSupplier {
private final Navigator navigator;
private final AxisResolver axisResolver;
private final NodeView parent;
private AxisNodeSupplier(
Navigator navigator, AxisResolver axisResolver, NodeView parent) {
this.navigator = navigator;
this.axisResolver = axisResolver;
this.parent = parent;
}
@Override
public NodeView apply(int position) throws XmlBuilderException {
return axisResolver.createAxisNode(navigator, parent, position);
}
}
private static final class PredicateResolver
implements NodeSupplier, Function, IterableNodeView> {
private final Navigator navigator;
private final NodeSupplier parentNodeSupplier;
private final Expr predicate;
private final boolean greedy;
private boolean resolved;
private PredicateResolver(
Navigator navigator,
NodeSupplier parentNodeSupplier,
Expr predicate,
boolean greedy) {
this.navigator = navigator;
this.parentNodeSupplier = parentNodeSupplier;
this.predicate = predicate;
this.greedy = greedy;
}
@Override
public NodeView apply(int position) throws XmlBuilderException {
final NodeView newNode = parentNodeSupplier.apply(position);
if (!predicate.resolve(navigator, newNode, true).toBoolean()) {
throw new XmlBuilderException("Unable to satisfy expression predicate: " + predicate);
}
return newNode;
}
@Override
public IterableNodeView apply(NodeView view) {
final IterableNodeView result;
final boolean check = predicate.resolve(navigator, view, false).toBoolean();
if (check) {
result = view;
} else if ((view.isNew() || view.isMarked()) && greedy) {
if (!predicate.resolve(navigator, view, true).toBoolean()) {
throw new XmlBuilderException("Unable to satisfy expression predicate: " + predicate);
}
result = view;
} else if (!view.hasNext() && !resolved && greedy) {
result = apply(view.getPosition() + 1);
} else {
result = NodeSetView.empty();
}
resolved |= check;
return result;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy