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