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 */ 017 018package org.apache.commons.jxpath.ri.compiler; 019 020import org.apache.commons.jxpath.ri.Compiler; 021 022/** 023 * A step. 024 */ 025public class Step { 026 027 /** 028 * Decode an axis code to its name. 029 * 030 * @param axis int code 031 * @return String name. 032 * @see Compiler 033 * @see "http://www.w3.org/TR/xpath#axes" 034 */ 035 public static String axisToString(final int axis) { 036 switch (axis) { 037 case Compiler.AXIS_SELF: 038 return "self"; 039 case Compiler.AXIS_CHILD: 040 return "child"; 041 case Compiler.AXIS_PARENT: 042 return "parent"; 043 case Compiler.AXIS_ANCESTOR: 044 return "ancestor"; 045 case Compiler.AXIS_ATTRIBUTE: 046 return "attribute"; 047 case Compiler.AXIS_NAMESPACE: 048 return "namespace"; 049 case Compiler.AXIS_PRECEDING: 050 return "preceding"; 051 case Compiler.AXIS_FOLLOWING: 052 return "following"; 053 case Compiler.AXIS_DESCENDANT: 054 return "descendant"; 055 case Compiler.AXIS_ANCESTOR_OR_SELF: 056 return "ancestor-or-self"; 057 case Compiler.AXIS_FOLLOWING_SIBLING: 058 return "following-sibling"; 059 case Compiler.AXIS_PRECEDING_SIBLING: 060 return "preceding-sibling"; 061 case Compiler.AXIS_DESCENDANT_OR_SELF: 062 return "descendant-or-self"; 063 default: 064 return "UNKNOWN"; 065 } 066 } 067 068 private final int axis; 069 private final NodeTest nodeTest; 070 private final Expression[] predicates; 071 072 /** 073 * Constructs a new Step. 074 * 075 * @param axis axis code 076 * @param nodeTest step test 077 * @param predicates predicate expressions 078 */ 079 protected Step(final int axis, final NodeTest nodeTest, final Expression[] predicates) { 080 this.axis = axis; 081 this.nodeTest = nodeTest; 082 this.predicates = predicates; 083 } 084 085 /** 086 * Gets the axis code. 087 * 088 * @return int 089 */ 090 public int getAxis() { 091 return axis; 092 } 093 094 /** 095 * Gets the step test. 096 * 097 * @return NodeTest 098 */ 099 public NodeTest getNodeTest() { 100 return nodeTest; 101 } 102 103 /** 104 * Gets the predicates. 105 * 106 * @return Expression[] 107 */ 108 public Expression[] getPredicates() { 109 return predicates; 110 } 111 112 /** 113 * Tests whether this step contains any predicate that is context dependent. 114 * 115 * @return boolean 116 */ 117 public boolean isContextDependent() { 118 if (predicates != null) { 119 for (final Expression predicate : predicates) { 120 if (predicate.isContextDependent()) { 121 return true; 122 } 123 } 124 } 125 return false; 126 } 127 128 @Override 129 public String toString() { 130 final StringBuilder buffer = new StringBuilder(); 131 final int axis = getAxis(); 132 if (axis == Compiler.AXIS_CHILD) { 133 buffer.append(nodeTest); 134 } else if (axis == Compiler.AXIS_ATTRIBUTE) { 135 buffer.append('@'); 136 buffer.append(nodeTest); 137 } else if (axis == Compiler.AXIS_SELF && nodeTest instanceof NodeTypeTest && ((NodeTypeTest) nodeTest).getNodeType() == Compiler.NODE_TYPE_NODE) { 138 buffer.append("."); 139 } else if (axis == Compiler.AXIS_PARENT && nodeTest instanceof NodeTypeTest && ((NodeTypeTest) nodeTest).getNodeType() == Compiler.NODE_TYPE_NODE) { 140 buffer.append(".."); 141 } else if (axis == Compiler.AXIS_DESCENDANT_OR_SELF && nodeTest instanceof NodeTypeTest 142 && ((NodeTypeTest) nodeTest).getNodeType() == Compiler.NODE_TYPE_NODE && (predicates == null || predicates.length == 0)) { 143 buffer.append(""); 144 } else { 145 buffer.append(axisToString(axis)); 146 buffer.append("::"); 147 buffer.append(nodeTest); 148 } 149 final Expression[] predicates = getPredicates(); 150 if (predicates != null) { 151 for (final Expression predicate : predicates) { 152 buffer.append('['); 153 buffer.append(predicate); 154 buffer.append(']'); 155 } 156 } 157 return buffer.toString(); 158 } 159}