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;
020import org.apache.commons.jxpath.ri.QName;
021
022/**
023 * @author Dmitri Plotnikov
024 * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $
025 */
026public 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}