001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.jxpath.ri.compiler;
018
019import org.apache.commons.jxpath.ri.Compiler;
020
021/**
022 * @author Dmitri Plotnikov
023 * @version $Revision: 1523200 $ $Date: 2013-09-14 11:48:25 +0200 (Sa, 14 Sep 2013) $
024 */
025public class Step {
026    private int axis;
027    private NodeTest nodeTest;
028    private Expression[] predicates;
029
030    /**
031     * Create a new Step.
032     * @param axis axis code
033     * @param nodeTest step test
034     * @param predicates predicate expressions
035     */
036    protected Step(int axis, NodeTest nodeTest, Expression[] predicates) {
037        this.axis = axis;
038        this.nodeTest = nodeTest;
039        this.predicates = predicates;
040    }
041
042    /**
043     * Get the axis code.
044     * @return int
045     */
046    public int getAxis() {
047        return axis;
048    }
049
050    /**
051     * Get the step test.
052     * @return NodeTest
053     */
054    public NodeTest getNodeTest() {
055        return nodeTest;
056    }
057
058    /**
059     * Get the predicates.
060     * @return Expression[]
061     */
062    public Expression[] getPredicates() {
063        return predicates;
064    }
065
066    /**
067     * Learn whether this step contains any predicate that is context dependent.
068     * @return boolean
069     */
070    public boolean isContextDependent() {
071        if (predicates != null) {
072            for (int i = 0; i < predicates.length; i++) {
073                if (predicates[i].isContextDependent()) {
074                    return true;
075                }
076            }
077        }
078        return false;
079    }
080
081    public String toString() {
082        StringBuffer buffer = new StringBuffer();
083        int axis = getAxis();
084        if (axis == Compiler.AXIS_CHILD) {
085            buffer.append(nodeTest);
086        }
087        else if (axis == Compiler.AXIS_ATTRIBUTE) {
088            buffer.append('@');
089            buffer.append(nodeTest);
090        }
091        else if (axis == Compiler.AXIS_SELF
092                && nodeTest instanceof NodeTypeTest
093                && ((NodeTypeTest) nodeTest).getNodeType()
094                    == Compiler.NODE_TYPE_NODE) {
095            buffer.append(".");
096        }
097        else if (axis == Compiler.AXIS_PARENT
098                && nodeTest instanceof NodeTypeTest
099                && ((NodeTypeTest) nodeTest).getNodeType()
100                    == Compiler.NODE_TYPE_NODE) {
101            buffer.append("..");
102        }
103        else if (axis == Compiler.AXIS_DESCENDANT_OR_SELF
104                && nodeTest instanceof NodeTypeTest
105                && ((NodeTypeTest) nodeTest).getNodeType()
106                    == Compiler.NODE_TYPE_NODE
107                && (predicates == null || predicates.length == 0)) {
108            buffer.append("");
109        }
110        else {
111            buffer.append(axisToString(axis));
112            buffer.append("::");
113            buffer.append(nodeTest);
114        }
115        Expression[] predicates = getPredicates();
116        if (predicates != null) {
117            for (int i = 0; i < predicates.length; i++) {
118                buffer.append('[');
119                buffer.append(predicates[i]);
120                buffer.append(']');
121            }
122        }
123        return buffer.toString();
124    }
125
126    /**
127     * Decode an axis code to its name.
128     * @param axis int code
129     * @return String name.
130     * @see Compiler
131     * @see "http://www.w3.org/TR/xpath#axes"
132     */
133    public static String axisToString(int axis) {
134        switch (axis) {
135            case Compiler.AXIS_SELF :
136                return "self";
137            case Compiler.AXIS_CHILD :
138                return "child";
139            case Compiler.AXIS_PARENT :
140                return "parent";
141            case Compiler.AXIS_ANCESTOR :
142                return "ancestor";
143            case Compiler.AXIS_ATTRIBUTE :
144                return "attribute";
145            case Compiler.AXIS_NAMESPACE :
146                return "namespace";
147            case Compiler.AXIS_PRECEDING :
148                return "preceding";
149            case Compiler.AXIS_FOLLOWING :
150                return "following";
151            case Compiler.AXIS_DESCENDANT :
152                return "descendant";
153            case Compiler.AXIS_ANCESTOR_OR_SELF :
154                return "ancestor-or-self";
155            case Compiler.AXIS_FOLLOWING_SIBLING :
156                return "following-sibling";
157            case Compiler.AXIS_PRECEDING_SIBLING :
158                return "preceding-sibling";
159            case Compiler.AXIS_DESCENDANT_OR_SELF :
160                return "descendant-or-self";
161            default:
162                return "UNKNOWN";
163        }
164    }
165}