View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jxpath.ri.compiler;
18  
19  import org.apache.commons.jxpath.ri.EvalContext;
20  
21  /**
22   * The common subclass for tree elements representing core operations like "+",
23   * "- ", "*" etc.
24   *
25   * @author Dmitri Plotnikov
26   * @version $Revision: 652845 $ $Date: 2008-05-02 19:46:46 +0200 (Fr, 02 Mai 2008) $
27   */
28  public abstract class CoreOperation extends Operation {
29  
30      /** or precedence */
31      protected static final int OR_PRECEDENCE = 0;
32      /** and precedence */
33      protected static final int AND_PRECEDENCE = 1;
34      /** compare precedence */
35      protected static final int COMPARE_PRECEDENCE = 2;
36      /** relational expression precedence */
37      protected static final int RELATIONAL_EXPR_PRECEDENCE = 3;
38      /** add/subtract precedence */
39      protected static final int ADD_PRECEDENCE = 4;
40      /** multiply/divide/mod precedence */
41      protected static final int MULTIPLY_PRECEDENCE = 5;
42      /** negate precedence */
43      protected static final int NEGATE_PRECEDENCE = 6;
44      /** union precedence */
45      protected static final int UNION_PRECEDENCE = 7;
46  
47      /**
48       * Create a new CoreOperation.
49       * @param args Expression[]
50       */
51      public CoreOperation(Expression[] args) {
52          super(args);
53      }
54  
55      public Object compute(EvalContext context) {
56          return computeValue(context);
57      }
58  
59      public abstract Object computeValue(EvalContext context);
60  
61      /**
62       * Returns the XPath symbol for this operation, e.g. "+", "div", etc.
63       * @return String symbol
64       */
65      public abstract String getSymbol();
66  
67      /**
68       * Returns true if the operation is not sensitive to the order of arguments,
69       * e.g. "=", "and" etc, and false if it is, e.g. "<=", "div".
70       * @return boolean
71       */
72      protected abstract boolean isSymmetric();
73  
74      /**
75       * Computes the precedence of the operation.
76       * @return int precedence
77       */
78      protected abstract int getPrecedence();
79  
80      public String toString() {
81          if (args.length == 1) {
82              return getSymbol() + parenthesize(args[0], false);
83          }
84          StringBuffer buffer = new StringBuffer();
85          for (int i = 0; i < args.length; i++) {
86              if (i > 0) {
87                  buffer.append(' ');
88                  buffer.append(getSymbol());
89                  buffer.append(' ');
90              }
91              buffer.append(parenthesize(args[i], i == 0));
92          }
93          return buffer.toString();
94      }
95  
96      /**
97       * Wrap an expression in parens if necessary.
98       * @param expression other Expression
99       * @param left whether <code>expression</code> is left of this one.
100      * @return String
101      */
102     private String parenthesize(Expression expression, boolean left) {
103         String s = expression.toString();
104         if (!(expression instanceof CoreOperation)) {
105             return s;
106         }
107         int compared = getPrecedence() - ((CoreOperation) expression).getPrecedence();
108 
109         if (compared < 0) {
110             return s;
111         }
112         if (compared == 0 && (isSymmetric() || left)) {
113             return s;
114         }
115         return '(' + s + ')';
116     }
117 }