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    }