    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    }