    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.jxpath.ri.compiler;
    17
    18  import org.apache.commons.jxpath.ri.EvalContext;
    19
    20  /***
    21   * The common subclass for tree elements representing core operations like "+",
    22   * "- ", "*" etc.
    23   *
    24   * @author Dmitri Plotnikov
    25   * @version $Revision: 1.14 $ $Date: 2004/02/29 14:17:39 $
    26   */
    27  public abstract class CoreOperation extends Operation {
    28
    29      public CoreOperation(Expression args[]) {
    30          super(args);
    31      }
    32
    33      public Object compute(EvalContext context) {
    34          return computeValue(context);
    35      }
    36
    37      public abstract Object computeValue(EvalContext context);
    38
    39      /***
    40       * Returns the XPath symbol for this operation, e.g. "+", "div", etc.
    41       */
    42      public abstract String getSymbol();
    43
    44      /***
    45       * Returns true if the operation is not sensitive to the order of arguments,
    46       * e.g. "=", "and" etc, and false if it is, e.g. "&lt;=", "div".
    47       */
    48      protected abstract boolean isSymmetric();
    49
    50      /***
    51       * Computes the precedence of the operation.
    52       */
    53      protected abstract int getPrecedence();
    54
    55      public String toString() {
    56          if (args.length == 1) {
    57              return getSymbol() + parenthesize(args[0], false);
    58          }
    59          else {
    60              StringBuffer buffer = new StringBuffer();
    61              for (int i = 0; i < args.length; i++) {
    62                  if (i > 0) {
    63                      buffer.append(' ');
    64                      buffer.append(getSymbol());
    65                      buffer.append(' ');
    66                  }
    67                  buffer.append(parenthesize(args[i], i == 0));
    68              }
    69              return buffer.toString();
    70          }
    71      }
    72
    73      private String parenthesize(Expression expression, boolean left) {
    74          if (!(expression instanceof CoreOperation)) {
    75              return expression.toString();
    76          }
    77          CoreOperation op = (CoreOperation) expression;
    78          int myPrecedence = getPrecedence();
    79          int thePrecedence = op.getPrecedence();
    80
    81          boolean needParens = true;
    82          if (myPrecedence < thePrecedence) {
    83              needParens = false;
    84          }
    85          else if (myPrecedence == thePrecedence) {
    86              if (isSymmetric()) {
    87                  needParens = false;
    88              }
    89              else {
    90                  needParens = !left;
    91              }
    92          }
    93
    94          if (needParens) {
    95              return "(" + expression.toString() + ")";
    96          }
    97          else {
    98              return expression.toString();
    99          }
    100     }
    101 }