content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   *
   * Contributors:
   *     Florent Guillaume, Nuxeo
   */
  package org.apache.chemistry.opencmis.server.support.query;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import org.antlr.runtime.tree.Tree;
  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
  
  /**
   * Basic implementation walking a predicate in lexical order.
   * <p>
   * The {@code walkXYZ} methods can be overridden to change the walking order.
   */
  public abstract class AbstractPredicateWalker implements PredicateWalker {
  
      @Override
      public Boolean walkPredicate(Tree node) {
          switch (node.getType()) {
          case CmisQlStrictLexer.NOT:
              return walkNot(node, node.getChild(0));
          case CmisQlStrictLexer.AND:
              return walkAnd(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.OR:
              return walkOr(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.EQ:
              return walkEquals(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.NEQ:
              return walkNotEquals(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.GT:
              return walkGreaterThan(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.GTEQ:
              return walkGreaterOrEquals(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.LT:
              return walkLessThan(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.LTEQ:
              return walkLessOrEquals(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.IN:
              return walkIn(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.NOT_IN:
              return walkNotIn(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.IN_ANY:
              return walkInAny(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.NOT_IN_ANY:
              return walkNotInAny(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.EQ_ANY:
              return walkEqAny(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.IS_NULL:
              return walkIsNull(node, node.getChild(0));
          case CmisQlStrictLexer.IS_NOT_NULL:
              return walkIsNotNull(node, node.getChild(0));
          case CmisQlStrictLexer.LIKE:
              return walkLike(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.NOT_LIKE:
              return walkNotLike(node, node.getChild(0), node.getChild(1));
          case CmisQlStrictLexer.CONTAINS:
              if (node.getChildCount() == 1) {
                  return walkContains(node, null, node.getChild(0));
              } else {
                  return walkContains(node, node.getChild(0), node.getChild(1));
              }
          case CmisQlStrictLexer.IN_FOLDER:
              if (node.getChildCount() == 1) {
                  return walkInFolder(node, null, node.getChild(0));
              } else {
                  return walkInFolder(node, node.getChild(0), node.getChild(1));
              }
          case CmisQlStrictLexer.IN_TREE:
              if (node.getChildCount() == 1) {
                  return walkInTree(node, null, node.getChild(0));
              } else {
                  return walkInTree(node, node.getChild(0), node.getChild(1));
              }
          case CmisQlStrictLexer.BOOL_LIT:
              walkBoolean(node);
              return false;
          case CmisQlStrictLexer.NUM_LIT:
              walkNumber(node);
              return false;
          case CmisQlStrictLexer.STRING_LIT:
              walkString(node);
              return false;
          case CmisQlStrictLexer.TIME_LIT:
              walkTimestamp(node);
              return false;
          case CmisQlStrictLexer.IN_LIST:
              walkList(node);
              return false;
          case CmisQlStrictLexer.COL:
              walkCol(node);
              return false;
          case CmisQlStrictLexer.ID:
              walkId(node);
              return false;
          case CmisQlStrictLexer.SCORE:
              return walkScore(node);
          default:
              return walkOtherPredicate(node);
          }
      }
  
  
      /** For extensibility. */
      protected Boolean walkOtherPredicate(Tree node) {
          throw new CmisRuntimeException("Unknown node type: " + node.getType() + " (" + node.getText() + ")");
      }
  
      @Override
      public Boolean walkNot(Tree opNode, Tree node) {
          walkPredicate(node);
          return false;
      }
  
      @Override
      public Boolean walkAnd(Tree opNode, Tree leftNode, Tree rightNode) {
          walkPredicate(leftNode);
          walkPredicate(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkOr(Tree opNode, Tree leftNode, Tree rightNode) {
          walkPredicate(leftNode);
          walkPredicate(rightNode);
          return false;
      }
  
      @Override
      public Object walkExpr(Tree node) {
          switch (node.getType()) {
          case CmisQlStrictLexer.BOOL_LIT:
              return walkBoolean(node);
          case CmisQlStrictLexer.NUM_LIT:
              return walkNumber(node);
          case CmisQlStrictLexer.STRING_LIT:
              return walkString(node);
          case CmisQlStrictLexer.TIME_LIT:
              return walkTimestamp(node);
          case CmisQlStrictLexer.IN_LIST:
              return walkList(node);
          case CmisQlStrictLexer.COL:
              return walkCol(node);
          case CmisQlStrictLexer.ID:
              return walkId(node);
          default:
              return walkOtherExpr(node);
          }
      }
  
      public Boolean walkSearchExpr(Tree node) {
          switch (node.getType()) {
          case TextSearchLexer.TEXT_AND:
              return walkTextAnd(node);
          case TextSearchLexer.TEXT_OR:
              return walkTextOr(node);
          case TextSearchLexer.TEXT_MINUS:
              return walkTextMinus(node);
          case TextSearchLexer.TEXT_SEARCH_WORD_LIT:
              return walkTextWord(node);
          case TextSearchLexer.TEXT_SEARCH_PHRASE_STRING_LIT:
              return walkTextPhrase(node);
          default:
              walkOtherExpr(node);
              return null;
          }
      }
  
      /** For extensibility. */
      protected Object walkOtherExpr(Tree node) {
          throw new CmisRuntimeException("Unknown node type: " + node.getType() + " (" + node.getText() + ")");
      }
  
      @Override
      public Boolean walkEquals(Tree opNode, Tree leftNode, Tree rightNode) {
          walkExpr(leftNode);
          walkExpr(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkNotEquals(Tree opNode, Tree leftNode, Tree rightNode) {
          walkExpr(leftNode);
          walkExpr(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkGreaterThan(Tree opNode, Tree leftNode, Tree rightNode) {
          walkExpr(leftNode);
          walkExpr(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkGreaterOrEquals(Tree opNode, Tree leftNode, Tree rightNode) {
          walkExpr(leftNode);
          walkExpr(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkLessThan(Tree opNode, Tree leftNode, Tree rightNode) {
          walkExpr(leftNode);
          walkExpr(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkLessOrEquals(Tree opNode, Tree leftNode, Tree rightNode) {
          walkExpr(leftNode);
          walkExpr(rightNode);
          return false;
      }
  
      @Override
      public Boolean walkIn(Tree opNode, Tree colNode, Tree listNode) {
          walkExpr(colNode);
          walkExpr(listNode);
          return false;
      }
  
      @Override
      public Boolean walkNotIn(Tree opNode, Tree colNode, Tree listNode) {
          walkExpr(colNode);
          walkExpr(listNode);
          return false;
      }
  
      @Override
      public Boolean walkInAny(Tree opNode, Tree colNode, Tree listNode) {
          walkExpr(colNode);
          walkExpr(listNode);
          return false;
      }
  
      @Override
      public Boolean walkNotInAny(Tree opNode, Tree colNode, Tree listNode) {
          walkExpr(colNode);
          walkExpr(listNode);
          return false;
      }
  
      @Override
      public Boolean walkEqAny(Tree opNode, Tree literalNode, Tree colNode) {
          walkExpr(literalNode);
          walkExpr(colNode);
          return false;
      }
  
      @Override
      public Boolean walkIsNull(Tree opNode, Tree colNode) {
          walkExpr(colNode);
          return false;
      }
  
      @Override
      public Boolean walkIsNotNull(Tree opNode, Tree colNode) {
          walkExpr(colNode);
          return false;
      }
  
      @Override
      public Boolean walkLike(Tree opNode, Tree colNode, Tree stringNode) {
          walkExpr(colNode);
          walkExpr(stringNode);
          return false;
      }
  
      @Override
      public Boolean walkNotLike(Tree opNode, Tree colNode, Tree stringNode) {
          walkExpr(colNode);
          walkExpr(stringNode);
          return false;
      }
  
      @Override
      public Boolean walkContains(Tree opNode, Tree qualNode, Tree queryNode) {
          if (qualNode != null) {
              return walkSearchExpr(qualNode);
          }
          return walkSearchExpr(queryNode);
      }
  
      @Override
      public Boolean walkInFolder(Tree opNode, Tree qualNode, Tree paramNode) {
          if (qualNode != null) {
              walkExpr(qualNode);
          }
          walkExpr(paramNode);
          return false;
      }
  
      @Override
      public Boolean walkInTree(Tree opNode, Tree qualNode, Tree paramNode) {
          if (qualNode != null) {
              walkExpr(qualNode);
          }
          walkExpr(paramNode);
          return false;
      }
  
      @Override
      public Object walkList(Tree node) {
          int n = node.getChildCount();
          List<Object> res = new ArrayList<Object>(n);
          for (int i = 0; i < n; i++) {
              res.add(walkExpr(node.getChild(i)));
          }
          return res;
      }
  
      @Override
      public Object walkBoolean(Tree node) {
          String s = node.getText();
          return Boolean.valueOf(s);
      }
  
      @Override
      public Object walkNumber(Tree node) {
          String s = node.getText();
          if (s.contains(".") || s.contains("e") || s.contains("E")) {
              return Double.valueOf(s);
          } else {
              return Long.valueOf(s);
          }
      }
  
      @Override
      public Object walkString(Tree node) {
          String s = node.getText();
          s = s.substring(1, s.length() - 1);
          s = s.replace("''", "'"); // unescape quotes
          return s;
      }
  
      @Override
      public Object walkTimestamp(Tree node) {
          String s = node.getText();
          s = s.substring(s.indexOf('\'') + 1, s.length() - 1);
          return CalendarHelper.fromString(s);
      }
  
      @Override
      public Object walkCol(Tree node) {
          return null;
      }
  
      @Override
      public Object walkId(Tree node) {
          return null;
      }
      
      protected Boolean walkTextAnd(Tree node) {
          return null;
      }
      
      protected Boolean walkTextOr(Tree node) {
          return null;
      }
      
      protected Boolean walkTextMinus(Tree node) {
          return null;
      }
      
      protected Boolean walkTextWord(Tree node) {
          return null;
      }
      
      protected Boolean walkTextPhrase(Tree node) {
          return null;
      }
      
      protected Boolean walkScore(Tree node) {
         return false;        
      }
  
  }
  