package lux.xpath; public class PathStep extends AbstractExpression { public static final int MSELF = 1; public static final int MCHILD = 2; public static final int MPARENT = 4; public static final int MDESCENDANT = 8; public static final int MANCESTOR = 16; public static final int MPRECEDING = 32; public static final int MFOLLOWING = 64; public static final int MPRECEDING_SIB = 128; public static final int MFOLLOWING_SIB = 256; public static final int MATTRIBUTE = 512; public enum Axis { DescendantSelf("descendant-or-self", false, MDESCENDANT | MCHILD | MSELF), Descendant("descendant", true, MDESCENDANT | MCHILD, DescendantSelf), AncestorSelf("ancestor-or-self", false, MANCESTOR | MPARENT | MSELF), Ancestor("ancestor", false, MANCESTOR | MPARENT, AncestorSelf), Self("self", true, MSELF, AncestorSelf, DescendantSelf), Child("child", true, MCHILD, Descendant), Parent("parent", false, MPARENT, Ancestor), Preceding("preceding", false, MPRECEDING | MPRECEDING_SIB), Following("following", true, MFOLLOWING | MFOLLOWING_SIB), PrecedingSibling("preceding-sibling", false, MPRECEDING_SIB, Preceding), FollowingSibling("following-sibling", true, MFOLLOWING_SIB, Following), Attribute("attribute", true, MATTRIBUTE); public final String name; public final boolean isForward; public final int rangeMask; public Axis [] extensions; Axis (String name, boolean forward, int rangeMask, Axis ... extensions) { this.name = name; this.isForward = forward; this.rangeMask = rangeMask; this.extensions = extensions; } @Override public String toString() { return name; } public boolean isAxisMask (int mask) { return (rangeMask & mask) != 0; } }; private final Axis axis; private final NodeTest nodeTest; public PathStep (Axis axis, NodeTest nodeTest) { super (Type.PATH_STEP); this.axis = axis; this.nodeTest = nodeTest; } public Axis getAxis () { return axis; } public NodeTest getNodeTest () { return nodeTest; } @Override public void toString (StringBuilder buf) { buf.append (axis).append("::"); nodeTest.toString (buf); } @Override public AbstractExpression accept(ExpressionVisitor visitor) { return visitor.visit(this); } /** * @return 0 */ @Override public int getPrecedence () { return 100; } @Override public boolean isDocumentOrdered () { return axis.isForward; } @Override public AbstractExpression getLastContextStep () { // If self::* or self::node(), return Dot instead if (axis == Axis.Self && nodeTest.isWild()) { return new Dot(); } return this; } @Override public boolean propEquals (AbstractExpression other) { return axis == ((PathStep) other).axis && nodeTest.equivalent(((PathStep) other).nodeTest); } @Override public boolean propGreaterEqual (AbstractExpression other) { PathStep otherStep = (PathStep) other; int oax = otherStep.axis.rangeMask; return (axis == otherStep.axis || ((axis.rangeMask & oax) == oax)) && nodeTest.propGreaterEqual(otherStep.nodeTest); } @Override public int equivHash () { return axis.ordinal() * nodeTest.equivHash(); } @Override public boolean isRestrictive () { return true; } } /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */