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 package org.apache.commons.jxpath.ri.compiler;
018
019 import org.apache.commons.jxpath.ri.Compiler;
020 import org.apache.commons.jxpath.ri.QName;
021
022 /**
023 * @author Dmitri Plotnikov
024 * @version $Revision: 652845 $ $Date: 2008-05-02 12:46:46 -0500 (Fri, 02 May 2008) $
025 */
026 public class TreeCompiler implements Compiler {
027
028 private static final QName QNAME_NAME = new QName(null, "name");
029
030 public Object number(String value) {
031 return new Constant(new Double(value));
032 }
033
034 public Object literal(String value) {
035 return new Constant(value);
036 }
037
038 public Object qname(String prefix, String name) {
039 return new QName(prefix, name);
040 }
041
042 public Object sum(Object[] arguments) {
043 return new CoreOperationAdd(toExpressionArray(arguments));
044 }
045
046 public Object minus(Object left, Object right) {
047 return new CoreOperationSubtract(
048 (Expression) left,
049 (Expression) right);
050 }
051
052 public Object multiply(Object left, Object right) {
053 return new CoreOperationMultiply((Expression) left, (Expression) right);
054 }
055
056 public Object divide(Object left, Object right) {
057 return new CoreOperationDivide((Expression) left, (Expression) right);
058 }
059
060 public Object mod(Object left, Object right) {
061 return new CoreOperationMod((Expression) left, (Expression) right);
062 }
063
064 public Object lessThan(Object left, Object right) {
065 return new CoreOperationLessThan((Expression) left, (Expression) right);
066 }
067
068 public Object lessThanOrEqual(Object left, Object right) {
069 return new CoreOperationLessThanOrEqual(
070 (Expression) left,
071 (Expression) right);
072 }
073
074 public Object greaterThan(Object left, Object right) {
075 return new CoreOperationGreaterThan(
076 (Expression) left,
077 (Expression) right);
078 }
079
080 public Object greaterThanOrEqual(Object left, Object right) {
081 return new CoreOperationGreaterThanOrEqual(
082 (Expression) left,
083 (Expression) right);
084 }
085
086 public Object equal(Object left, Object right) {
087 return isNameAttributeTest((Expression) left)
088 ? new NameAttributeTest((Expression) left, (Expression) right)
089 : new CoreOperationEqual((Expression) left, (Expression) right);
090 }
091
092 public Object notEqual(Object left, Object right) {
093 return new CoreOperationNotEqual((Expression) left, (Expression) right);
094 }
095
096 public Object minus(Object argument) {
097 return new CoreOperationNegate((Expression) argument);
098 }
099
100 public Object variableReference(Object qName) {
101 return new VariableReference((QName) qName);
102 }
103
104 public Object function(int code, Object[] args) {
105 return new CoreFunction(code, toExpressionArray(args));
106 }
107
108 public Object function(Object name, Object[] args) {
109 return new ExtensionFunction((QName) name, toExpressionArray(args));
110 }
111
112 public Object and(Object[] arguments) {
113 return new CoreOperationAnd(toExpressionArray(arguments));
114 }
115
116 public Object or(Object[] arguments) {
117 return new CoreOperationOr(toExpressionArray(arguments));
118 }
119
120 public Object union(Object[] arguments) {
121 return new CoreOperationUnion(toExpressionArray(arguments));
122 }
123
124 public Object locationPath(boolean absolute, Object[] steps) {
125 return new LocationPath(absolute, toStepArray(steps));
126 }
127
128 public Object expressionPath(Object expression, Object[] predicates,
129 Object[] steps) {
130 return new ExpressionPath(
131 (Expression) expression,
132 toExpressionArray(predicates),
133 toStepArray(steps));
134 }
135
136 public Object nodeNameTest(Object qname) {
137 return new NodeNameTest((QName) qname);
138 }
139
140 public Object nodeTypeTest(int nodeType) {
141 return new NodeTypeTest(nodeType);
142 }
143
144 public Object processingInstructionTest(String instruction) {
145 return new ProcessingInstructionTest(instruction);
146 }
147
148 public Object step(int axis, Object nodeTest, Object[] predicates) {
149 return new Step(
150 axis,
151 (NodeTest) nodeTest,
152 toExpressionArray(predicates));
153 }
154
155 /**
156 * Get an Object[] as an Expression[].
157 * @param array Object[]
158 * @return Expression[]
159 */
160 private Expression[] toExpressionArray(Object[] array) {
161 Expression[] expArray = null;
162 if (array != null) {
163 expArray = new Expression[array.length];
164 for (int i = 0; i < expArray.length; i++) {
165 expArray[i] = (Expression) array[i];
166 }
167 }
168 return expArray;
169 }
170
171 /**
172 * Get an Object[] as a Step[].
173 * @param array Object[]
174 * @return Step[]
175 */
176 private Step[] toStepArray(Object[] array) {
177 Step[] stepArray = null;
178 if (array != null) {
179 stepArray = new Step[array.length];
180 for (int i = 0; i < stepArray.length; i++) {
181 stepArray[i] = (Step) array[i];
182 }
183 }
184 return stepArray;
185 }
186
187 /**
188 * Learn whether arg is a name attribute test.
189 * @param arg Expression to test
190 * @return boolean
191 */
192 private boolean isNameAttributeTest(Expression arg) {
193 if (!(arg instanceof LocationPath)) {
194 return false;
195 }
196
197 Step[] steps = ((LocationPath) arg).getSteps();
198 if (steps.length != 1) {
199 return false;
200 }
201 if (steps[0].getAxis() != Compiler.AXIS_ATTRIBUTE) {
202 return false;
203 }
204 NodeTest test = steps[0].getNodeTest();
205 if (!(test instanceof NodeNameTest)) {
206 return false;
207 }
208 if (!((NodeNameTest) test).getNodeName().equals(QNAME_NAME)) {
209 return false;
210 }
211 return true;
212 }
213 }