/* Generated By:JJTree&JavaCC: Do not edit this line. JCRSQLParser.java */
/*
 * 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.
 */
package org.apache.jackrabbit.spi.commons.query.sql;

import org.apache.jackrabbit.spi.commons.conversion.NameException;
import org.apache.jackrabbit.spi.commons.conversion.NameResolver;
import org.apache.jackrabbit.spi.commons.query.QueryConstants;
import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
import org.apache.jackrabbit.spi.Name;

import javax.jcr.NamespaceException;

public class JCRSQLParser/*@bgen(jjtree)*/implements JCRSQLParserTreeConstants, JCRSQLParserConstants {/*@bgen(jjtree)*/
  protected JJTJCRSQLParserState jjtree = new JJTJCRSQLParserState();
  private String statement;

  private NameResolver resolver;

  public static void main(String args[]) throws ParseException {
        JCRSQLParser parser = new JCRSQLParser(System.in);
        parser.Query().dump("");
  }

  public static ASTQuery parse(String statement, NameResolver resolver) throws ParseException {
        java.io.StringReader sReader = new java.io.StringReader(statement);
        JCRSQLParser parser = new JCRSQLParser(sReader);
        parser.setNameResolver(resolver);
        return parser.Query();
  }

  void setNameResolver(NameResolver resolver) {
        this.resolver = resolver;
  }

// QUERY EXPRESSIONS, 7
  final public ASTQuery Query() throws ParseException {
 /*@bgen(jjtree) Query */
  ASTQuery jjtn000 = new ASTQuery(JJTQUERY);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(SELECT);
      SelectList();
      TableExpression();
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ORDER:
        OrderByClause();
        break;
      default:
        jj_la1[0] = jj_gen;
        ;
      }
      jj_consume_token(0);
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    {if (true) return jjtn000;}
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
    throw new Error("Missing return statement in function");
  }

  final public void SelectList() throws ParseException {
 /*@bgen(jjtree) SelectList */
  ASTSelectList jjtn000 = new ASTSelectList(JJTSELECTLIST);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ASTERISK:
        jj_consume_token(ASTERISK);
        break;
      case BY:
      case IN:
      case OR:
      case IS:
      case AND:
      case LIKE:
      case NULL:
      case FROM:
      case ORDER:
      case WHERE:
      case SELECT:
      case BETWEEN:
      case EXCERPT:
      case REGULAR_IDENTIFIER:
      case DELIMITED_IDENTIFIER:
        SelectItem();
        label_1:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case COMMA:
            ;
            break;
          default:
            jj_la1[1] = jj_gen;
            break label_1;
          }
          jj_consume_token(COMMA);
          SelectItem();
        }
        break;
      default:
        jj_la1[2] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } catch (Throwable jjte000) {
      if (jjtc000) {
        jjtree.clearNodeScope(jjtn000);
        jjtc000 = false;
      } else {
        jjtree.popNode();
      }
      if (jjte000 instanceof RuntimeException) {
        {if (true) throw (RuntimeException)jjte000;}
      }
      if (jjte000 instanceof ParseException) {
        {if (true) throw (ParseException)jjte000;}
      }
      {if (true) throw (Error)jjte000;}
    } finally {
      if (jjtc000) {
        jjtree.closeNodeScope(jjtn000, true);
      }
    }
  }

  final public void SelectItem() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case EXCERPT:
      ExcerptFunction();
      break;
    case BY:
    case IN:
    case OR:
    case IS:
    case AND:
    case LIKE:
    case NULL:
    case FROM:
    case ORDER:
    case WHERE:
    case SELECT:
    case BETWEEN:
    case REGULAR_IDENTIFIER:
    case DELIMITED_IDENTIFIER:
      Identifier();
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case PERIOD:
        jj_consume_token(PERIOD);
        Identifier();
                                                             Node n = jjtree.popNode(); jjtree.popNode(); jjtree.pushNode(n);
        break;
      default:
        jj_la1[3] = jj_gen;
        ;
      }
      break;
    default:
      jj_la1[4] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void TableExpression() throws ParseException {
    FromClause();
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case WHERE:
      WhereClause();
      break;
    default:
      jj_la1[5] = jj_gen;
      ;
    }
  }

  final public void FromClause() throws ParseException {
 /*@bgen(jjtree) FromClause */
  ASTFromClause jjtn000 = new ASTFromClause(JJTFROMCLAUSE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(FROM);
      Identifier();
      label_2:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[6] = jj_gen;
          break label_2;
        }
        jj_consume_token(COMMA);
        Identifier();
      }
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public void WhereClause() throws ParseException {
 /*@bgen(jjtree) WhereClause */
  ASTWhereClause jjtn000 = new ASTWhereClause(JJTWHERECLAUSE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(WHERE);
      SearchCondition();
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

// PREDICATES 8.1
  final public void Predicate() throws ParseException {
 /*@bgen(jjtree) Predicate */
  ASTPredicate jjtn000 = new ASTPredicate(JJTPREDICATE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);int operationType;
  Name identifier;
  String value;
  String escapeString;
    try {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case BY:
      case IN:
      case OR:
      case IS:
      case AND:
      case LIKE:
      case NULL:
      case FROM:
      case LOWER:
      case ORDER:
      case UPPER:
      case WHERE:
      case SELECT:
      case BETWEEN:
      case REGULAR_IDENTIFIER:
      case DELIMITED_IDENTIFIER:
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case BY:
        case IN:
        case OR:
        case IS:
        case AND:
        case LIKE:
        case NULL:
        case FROM:
        case ORDER:
        case WHERE:
        case SELECT:
        case BETWEEN:
        case REGULAR_IDENTIFIER:
        case DELIMITED_IDENTIFIER:
          identifier = Identifier();
                                      jjtn000.setIdentifier(identifier);
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case PERIOD:
            jj_consume_token(PERIOD);
            identifier = Identifier();
                                                                                                                  Node n = jjtree.popNode(); jjtree.popNode(); jjtree.pushNode(n); jjtn000.setIdentifier(identifier);
            break;
          default:
            jj_la1[7] = jj_gen;
            ;
          }
          break;
        case LOWER:
        case UPPER:
          identifier = PropertyFunction();
                                            jjtn000.setIdentifier(identifier);
          break;
        default:
          jj_la1[8] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case LT_OPERATOR:
        case EQ_OPERATOR:
        case GT_OPERATOR:
        case NE_OPERATOR:
        case GE_OPERATOR:
        case LE_OPERATOR:
          operationType = ComparisonOperation();
                                                  jjtn000.setOperationType(operationType);
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case EXACT_NUMERIC_LITERAL:
          case APPROXIMATE_NUMERIC_LITERAL:
          case DATETIME_LITERAL:
          case CHAR_STRING_LITERAL:
            Literal();
            break;
          case BY:
          case IN:
          case OR:
          case IS:
          case AND:
          case LIKE:
          case NULL:
          case FROM:
          case ORDER:
          case WHERE:
          case SELECT:
          case BETWEEN:
          case REGULAR_IDENTIFIER:
          case DELIMITED_IDENTIFIER:
            identifier = Identifier();
                                                    jjtn000.setIdentifier(identifier);
            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
            case PERIOD:
              jj_consume_token(PERIOD);
              identifier = Identifier();
                                                                                                                                Node n = jjtree.popNode(); jjtree.popNode(); jjtree.pushNode(n); jjtn000.setIdentifier(identifier);
              break;
            default:
              jj_la1[9] = jj_gen;
              ;
            }
            break;
          default:
            jj_la1[10] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
          break;
        case NOT:
        case LIKE:
        case BETWEEN:
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case NOT:
            jj_consume_token(NOT);
                  jjtn000.setNegate(true);
            break;
          default:
            jj_la1[11] = jj_gen;
            ;
          }
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case BETWEEN:
            jj_consume_token(BETWEEN);
                         jjtn000.setOperationType(QueryConstants.OPERATION_BETWEEN);
            Literal();
            jj_consume_token(AND);
            Literal();
            break;
          case LIKE:
            jj_consume_token(LIKE);
                       jjtn000.setOperationType(QueryConstants.OPERATION_LIKE);
            value = CharStringLiteral();
                ASTLiteral s = new ASTLiteral(JJTLITERAL);
                s.setType(QueryConstants.TYPE_STRING);
                s.setValue(value);
                jjtree.pushNode(s);
            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
            case ESCAPE:
              jj_consume_token(ESCAPE);
              escapeString = CharStringLiteral();
                                                             jjtn000.setEscapeString(escapeString);
              break;
            default:
              jj_la1[12] = jj_gen;
              ;
            }
            break;
          default:
            jj_la1[13] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
          break;
        case IS:
          jj_consume_token(IS);
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case NOT:
            jj_consume_token(NOT);
                       jjtn000.setNegate(true);
            break;
          default:
            jj_la1[14] = jj_gen;
            ;
          }
          jj_consume_token(NULL);
            jjtree.closeNodeScope(jjtn000, true);
            jjtc000 = false;
            jjtn000.setOperationType(jjtn000.isNegate() ? QueryConstants.OPERATION_NOT_NULL : QueryConstants.OPERATION_NULL);
          break;
        default:
          jj_la1[15] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        break;
      case EXACT_NUMERIC_LITERAL:
      case APPROXIMATE_NUMERIC_LITERAL:
      case DATETIME_LITERAL:
      case CHAR_STRING_LITERAL:
        Literal();
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case NOT:
          jj_consume_token(NOT);
                         jjtn000.setNegate(true);
          break;
        default:
          jj_la1[16] = jj_gen;
          ;
        }
        jj_consume_token(IN);
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case BY:
        case IN:
        case OR:
        case IS:
        case AND:
        case LIKE:
        case NULL:
        case FROM:
        case ORDER:
        case WHERE:
        case SELECT:
        case BETWEEN:
        case REGULAR_IDENTIFIER:
        case DELIMITED_IDENTIFIER:
          identifier = Identifier();
          break;
        case LOWER:
        case UPPER:
          identifier = PropertyFunction();
          break;
        default:
          jj_la1[17] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
          jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
          jjtn000.setIdentifier(identifier);
          jjtn000.setOperationType(jjtn000.isNegate() ? QueryConstants.OPERATION_NE_GENERAL : QueryConstants.OPERATION_EQ_GENERAL);
        break;
      case SIMILAR:
        jj_consume_token(SIMILAR);
        jj_consume_token(LEFT_PAREN);
                      jjtn000.setOperationType(QueryConstants.OPERATION_SIMILAR);
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case PERIOD:
          jj_consume_token(PERIOD);
          break;
        case BY:
        case IN:
        case OR:
        case IS:
        case AND:
        case LIKE:
        case NULL:
        case FROM:
        case ORDER:
        case WHERE:
        case SELECT:
        case BETWEEN:
        case REGULAR_IDENTIFIER:
        case DELIMITED_IDENTIFIER:
          identifier = Identifier();
                                           jjtn000.setIdentifier(identifier);
          break;
        default:
          jj_la1[18] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        jj_consume_token(COMMA);
        value = CharStringLiteral();
            ASTLiteral s = new ASTLiteral(JJTLITERAL);
            s.setType(QueryConstants.TYPE_STRING);
            s.setValue(value);
            jjtree.pushNode(s);
        jj_consume_token(RIGHT_PAREN);
        break;
      case SPELLCHECK:
        jj_consume_token(SPELLCHECK);
        jj_consume_token(LEFT_PAREN);
                         jjtn000.setOperationType(QueryConstants.OPERATION_SPELLCHECK);
        value = CharStringLiteral();
            ASTLiteral stmt = new ASTLiteral(JJTLITERAL);
            stmt.setType(QueryConstants.TYPE_STRING);
            stmt.setValue(value);
            jjtree.pushNode(stmt);
        jj_consume_token(RIGHT_PAREN);
        break;
      default:
        jj_la1[19] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public Name PropertyFunction() throws ParseException {
  Name identifier;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case LOWER:
      identifier = LowerFunction();
      break;
    case UPPER:
      identifier = UpperFunction();
      break;
    default:
      jj_la1[20] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return identifier;}
    throw new Error("Missing return statement in function");
  }

  final public Name LowerFunction() throws ParseException {
 /*@bgen(jjtree) LowerFunction */
  ASTLowerFunction jjtn000 = new ASTLowerFunction(JJTLOWERFUNCTION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);Name identifier;
    try {
      jj_consume_token(LOWER);
      jj_consume_token(LEFT_PAREN);
      identifier = Identifier();
      jj_consume_token(RIGHT_PAREN);
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    {if (true) return identifier;}
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
    throw new Error("Missing return statement in function");
  }

  final public Name UpperFunction() throws ParseException {
 /*@bgen(jjtree) UpperFunction */
  ASTUpperFunction jjtn000 = new ASTUpperFunction(JJTUPPERFUNCTION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);Name identifier;
    try {
      jj_consume_token(UPPER);
      jj_consume_token(LEFT_PAREN);
      identifier = Identifier();
      jj_consume_token(RIGHT_PAREN);
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    {if (true) return identifier;}
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
    throw new Error("Missing return statement in function");
  }

  final public int ComparisonOperation() throws ParseException {
  int operationType;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case EQ_OPERATOR:
      jj_consume_token(EQ_OPERATOR);
                      operationType = QueryConstants.OPERATION_EQ_GENERAL;
      break;
    case NE_OPERATOR:
      jj_consume_token(NE_OPERATOR);
                      operationType = QueryConstants.OPERATION_NE_GENERAL;
      break;
    case LT_OPERATOR:
      jj_consume_token(LT_OPERATOR);
                      operationType = QueryConstants.OPERATION_LT_GENERAL;
      break;
    case GT_OPERATOR:
      jj_consume_token(GT_OPERATOR);
                      operationType = QueryConstants.OPERATION_GT_GENERAL;
      break;
    case LE_OPERATOR:
      jj_consume_token(LE_OPERATOR);
                      operationType = QueryConstants.OPERATION_LE_GENERAL;
      break;
    case GE_OPERATOR:
      jj_consume_token(GE_OPERATOR);
                      operationType = QueryConstants.OPERATION_GE_GENERAL;
      break;
    default:
      jj_la1[21] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return operationType;}
    throw new Error("Missing return statement in function");
  }

// SEARCH CONDITION 8.12
  final public void SearchCondition() throws ParseException {
    OrExpression();
  }

  final public void OrExpression() throws ParseException {
    ASTOrExpression jjtn001 = new ASTOrExpression(JJTOREXPRESSION);
    boolean jjtc001 = true;
    jjtree.openNodeScope(jjtn001);
    try {
      AndExpression();
      label_3:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case OR:
          ;
          break;
        default:
          jj_la1[22] = jj_gen;
          break label_3;
        }
        jj_consume_token(OR);
        AndExpression();
      }
    } catch (Throwable jjte001) {
    if (jjtc001) {
      jjtree.clearNodeScope(jjtn001);
      jjtc001 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte001 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte001;}
    }
    if (jjte001 instanceof ParseException) {
      {if (true) throw (ParseException)jjte001;}
    }
    {if (true) throw (Error)jjte001;}
    } finally {
    if (jjtc001) {
      jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1);
    }
    }
  }

  final public void AndExpression() throws ParseException {
    ASTAndExpression jjtn001 = new ASTAndExpression(JJTANDEXPRESSION);
    boolean jjtc001 = true;
    jjtree.openNodeScope(jjtn001);
    try {
      UnaryExpression();
      label_4:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case AND:
          ;
          break;
        default:
          jj_la1[23] = jj_gen;
          break label_4;
        }
        jj_consume_token(AND);
        UnaryExpression();
      }
    } catch (Throwable jjte001) {
    if (jjtc001) {
      jjtree.clearNodeScope(jjtn001);
      jjtc001 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte001 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte001;}
    }
    if (jjte001 instanceof ParseException) {
      {if (true) throw (ParseException)jjte001;}
    }
    {if (true) throw (Error)jjte001;}
    } finally {
    if (jjtc001) {
      jjtree.closeNodeScope(jjtn001, jjtree.nodeArity() > 1);
    }
    }
  }

  final public void UnaryExpression() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case NOT:
    ASTNotExpression jjtn001 = new ASTNotExpression(JJTNOTEXPRESSION);
    boolean jjtc001 = true;
    jjtree.openNodeScope(jjtn001);
      try {
        jj_consume_token(NOT);
        UnaryExpression();
      } catch (Throwable jjte001) {
    if (jjtc001) {
      jjtree.clearNodeScope(jjtn001);
      jjtc001 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte001 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte001;}
    }
    if (jjte001 instanceof ParseException) {
      {if (true) throw (ParseException)jjte001;}
    }
    {if (true) throw (Error)jjte001;}
      } finally {
    if (jjtc001) {
      jjtree.closeNodeScope(jjtn001, true);
    }
      }
      break;
    case BY:
    case IN:
    case OR:
    case IS:
    case AND:
    case LIKE:
    case NULL:
    case FROM:
    case LOWER:
    case ORDER:
    case UPPER:
    case WHERE:
    case SELECT:
    case BETWEEN:
    case SIMILAR:
    case CONTAINS:
    case SPELLCHECK:
    case LEFT_PAREN:
    case REGULAR_IDENTIFIER:
    case DELIMITED_IDENTIFIER:
    case EXACT_NUMERIC_LITERAL:
    case APPROXIMATE_NUMERIC_LITERAL:
    case DATETIME_LITERAL:
    case CHAR_STRING_LITERAL:
      PrimaryExpression();
      break;
    default:
      jj_la1[24] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void PrimaryExpression() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case BY:
    case IN:
    case OR:
    case IS:
    case AND:
    case LIKE:
    case NULL:
    case FROM:
    case LOWER:
    case ORDER:
    case UPPER:
    case WHERE:
    case SELECT:
    case BETWEEN:
    case SIMILAR:
    case SPELLCHECK:
    case REGULAR_IDENTIFIER:
    case DELIMITED_IDENTIFIER:
    case EXACT_NUMERIC_LITERAL:
    case APPROXIMATE_NUMERIC_LITERAL:
    case DATETIME_LITERAL:
    case CHAR_STRING_LITERAL:
      Predicate();
      break;
    case LEFT_PAREN:
      BracketExpression();
      break;
    case CONTAINS:
      ContainsExpression();
      break;
    default:
      jj_la1[25] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void BracketExpression() throws ParseException {
 /*@bgen(jjtree) BracketExpression */
  ASTBracketExpression jjtn000 = new ASTBracketExpression(JJTBRACKETEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(LEFT_PAREN);
      SearchCondition();
      jj_consume_token(RIGHT_PAREN);
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public void ContainsExpression() throws ParseException {
 /*@bgen(jjtree) ContainsExpression */
  ASTContainsExpression jjtn000 = new ASTContainsExpression(JJTCONTAINSEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);Token t = null;
  Name name = null;
    try {
      jj_consume_token(CONTAINS);
      jj_consume_token(LEFT_PAREN);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ASTERISK:
        jj_consume_token(ASTERISK);
        break;
      case PERIOD:
        jj_consume_token(PERIOD);
        break;
      case BY:
      case IN:
      case OR:
      case IS:
      case AND:
      case LIKE:
      case NULL:
      case FROM:
      case ORDER:
      case WHERE:
      case SELECT:
      case BETWEEN:
      case REGULAR_IDENTIFIER:
      case DELIMITED_IDENTIFIER:
        name = Identifier();
                                                   jjtn000.setPropertyName(name);
        break;
      default:
        jj_la1[26] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      jj_consume_token(COMMA);
      t = jj_consume_token(CHAR_STRING_LITERAL);
                              jjtn000.setQuery(t.image.substring(1, t.image.length() - 1).replaceAll("''", "'"));
      jj_consume_token(RIGHT_PAREN);
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public void Literal() throws ParseException {
 /*@bgen(jjtree) Literal */
  ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);Token t = null;
  String value;
    try {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case APPROXIMATE_NUMERIC_LITERAL:
        t = jj_consume_token(APPROXIMATE_NUMERIC_LITERAL);
                                        jjtree.closeNodeScope(jjtn000, true);
                                        jjtc000 = false;
                                        jjtn000.setType(QueryConstants.TYPE_DOUBLE); jjtn000.setValue(t.image);
        break;
      case EXACT_NUMERIC_LITERAL:
        // can contain a dot -> use double
            t = jj_consume_token(EXACT_NUMERIC_LITERAL);
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
      if (t.image.indexOf('.') > -1) {
        jjtn000.setType(QueryConstants.TYPE_DOUBLE);
      } else {
        jjtn000.setType(QueryConstants.TYPE_LONG);
      }
      jjtn000.setValue(t.image);
        break;
      case CHAR_STRING_LITERAL:
        value = CharStringLiteral();
                                  jjtree.closeNodeScope(jjtn000, true);
                                  jjtc000 = false;
                                  jjtn000.setType(QueryConstants.TYPE_STRING); jjtn000.setValue(value);
        break;
      case DATETIME_LITERAL:
        t = jj_consume_token(DATETIME_LITERAL);
      jjtree.closeNodeScope(jjtn000, true);
      jjtc000 = false;
      if (t.image.startsWith("TIMESTAMP")) {
        jjtn000.setValue(t.image.substring(t.image.indexOf('\'') + 1, t.image.length() - 1));
        if (jjtn000.getValue().indexOf(" ") == 10) {
          // replace SQL 92 timesamp string with ISO8601
          StringBuffer tmp = new StringBuffer();
          tmp.append(jjtn000.getValue().substring(0, 10));
          tmp.append("T").append(jjtn000.getValue().substring(11));
          jjtn000.setValue(tmp.toString());
        }
        jjtn000.setType(QueryConstants.TYPE_TIMESTAMP);
      /*
      } else if (t.image.startsWith("TIME")) {
        jjtThis.setValue(t.image.substring(t.image.indexOf('\'') + 1, t.image.length() - 1));
        jjtThis.setType(QueryConstants.TYPE_TIME);
      */
      } else {
        jjtn000.setValue(t.image.substring(t.image.indexOf('\'') + 1, t.image.length() - 1));
        jjtn000.setType(QueryConstants.TYPE_DATE);
      }
        break;
      default:
        jj_la1[27] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public String CharStringLiteral() throws ParseException {
  Token t;
  String value = "";
    t = jj_consume_token(CHAR_STRING_LITERAL);
                                value += t.image.substring(1, t.image.length() - 1);
    label_5:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case CHAR_STRING_LITERAL:
        ;
        break;
      default:
        jj_la1[28] = jj_gen;
        break label_5;
      }
      t = jj_consume_token(CHAR_STRING_LITERAL);
                                                                                                                     value += t.image.substring(1, t.image.length() - 1);
    }
    // strip any quote escapes
    {if (true) return value.replaceAll("''", "'");}
    throw new Error("Missing return statement in function");
  }

  final public Name Identifier() throws ParseException {
 /*@bgen(jjtree) Identifier */
  ASTIdentifier jjtn000 = new ASTIdentifier(JJTIDENTIFIER);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);Token t = null;
  Name name = null;
  boolean pseudoProperty = false;
    try {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case REGULAR_IDENTIFIER:
        t = jj_consume_token(REGULAR_IDENTIFIER);
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case LEFT_PAREN:
          jj_consume_token(LEFT_PAREN);
          jj_consume_token(RIGHT_PAREN);
                                                            pseudoProperty = true;
          break;
        default:
          jj_la1[29] = jj_gen;
          ;
        }
        try {
          String jcrName = t.image;
          if (pseudoProperty) {
            jcrName += "()";
          }
          jjtn000.setName(resolver.getQName(jcrName));
        } catch (NameException e) {
          {if (true) throw new ParseException(e.getMessage());}
        } catch (NamespaceException e) {
          {if (true) throw new ParseException(e.getMessage());}
        }
        break;
      case DELIMITED_IDENTIFIER:
        t = jj_consume_token(DELIMITED_IDENTIFIER);
        try {
          jjtn000.setName(resolver.getQName(t.image.substring(1, t.image.length()-1)));
        } catch (NameException e) {
          {if (true) throw new ParseException(e.getMessage());}
        } catch (NamespaceException e) {
          {if (true) throw new ParseException(e.getMessage());}
        }
        break;
      case BY:
      case IN:
      case OR:
      case IS:
      case AND:
      case LIKE:
      case NULL:
      case FROM:
      case ORDER:
      case WHERE:
      case SELECT:
      case BETWEEN:
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case BY:
          // or any keyword
                    t = jj_consume_token(BY);
          break;
        case IN:
          t = jj_consume_token(IN);
          break;
        case OR:
          t = jj_consume_token(OR);
          break;
        case IS:
          t = jj_consume_token(IS);
          break;
        case AND:
          t = jj_consume_token(AND);
          break;
        case LIKE:
          t = jj_consume_token(LIKE);
          break;
        case NULL:
          t = jj_consume_token(NULL);
          break;
        case FROM:
          t = jj_consume_token(FROM);
          break;
        case ORDER:
          t = jj_consume_token(ORDER);
          break;
        case WHERE:
          t = jj_consume_token(WHERE);
          break;
        case SELECT:
          t = jj_consume_token(SELECT);
          break;
        case BETWEEN:
          t = jj_consume_token(BETWEEN);
          break;
        default:
          jj_la1[30] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        try {
          jjtn000.setName(resolver.getQName(t.image));
        } catch (NameException e) {
          {if (true) throw new ParseException(e.getMessage());}
        } catch (NamespaceException e) {
          {if (true) throw new ParseException(e.getMessage());}
        }
        break;
      default:
        jj_la1[31] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    {if (true) return jjtn000.getName();}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
    throw new Error("Missing return statement in function");
  }

  final public Name ExcerptFunction() throws ParseException {
 /*@bgen(jjtree) ExcerptFunction */
  ASTExcerptFunction jjtn000 = new ASTExcerptFunction(JJTEXCERPTFUNCTION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(EXCERPT);
      jj_consume_token(LEFT_PAREN);
      jj_consume_token(PERIOD);
      jj_consume_token(RIGHT_PAREN);
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
    {if (true) return NameFactoryImpl.getInstance().create(Name.NS_REP_URI, "excerpt(.)");}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
    throw new Error("Missing return statement in function");
  }

  final public void OrderByClause() throws ParseException {
 /*@bgen(jjtree) OrderByClause */
  ASTOrderByClause jjtn000 = new ASTOrderByClause(JJTORDERBYCLAUSE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(ORDER);
      jj_consume_token(BY);
      OrderSpec();
      label_6:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case COMMA:
          ;
          break;
        default:
          jj_la1[32] = jj_gen;
          break label_6;
        }
        jj_consume_token(COMMA);
        OrderSpec();
      }
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public void OrderSpec() throws ParseException {
 /*@bgen(jjtree) OrderSpec */
  ASTOrderSpec jjtn000 = new ASTOrderSpec(JJTORDERSPEC);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      Identifier();
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case ASC:
      case DESC:
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case ASC:
          AscendingOrderSpec();
          break;
        case DESC:
          DescendingOrderSpec();
          break;
        default:
          jj_la1[33] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        break;
      default:
        jj_la1[34] = jj_gen;
        ;
      }
    } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public void AscendingOrderSpec() throws ParseException {
 /*@bgen(jjtree) AscendingOrderSpec */
  ASTAscendingOrderSpec jjtn000 = new ASTAscendingOrderSpec(JJTASCENDINGORDERSPEC);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(ASC);
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  final public void DescendingOrderSpec() throws ParseException {
 /*@bgen(jjtree) DescendingOrderSpec */
  ASTDescendingOrderSpec jjtn000 = new ASTDescendingOrderSpec(JJTDESCENDINGORDERSPEC);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
    try {
      jj_consume_token(DESC);
    } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
    }
  }

  public JCRSQLParserTokenManager token_source;
  SimpleCharStream jj_input_stream;
  public Token token, jj_nt;
  private int jj_ntk;
  private int jj_gen;
  final private int[] jj_la1 = new int[35];
  static private int[] jj_la1_0;
  static private int[] jj_la1_1;
  static private int[] jj_la1_2;
  static private int[] jj_la1_3;
  static {
      jj_la1_0();
      jj_la1_1();
      jj_la1_2();
      jj_la1_3();
   }
   private static void jj_la1_0() {
      jj_la1_0 = new int[] {0x200000,0x0,0xeae3e00,0x0,0xeae3e00,0x800000,0x0,0x0,0x6fe3e00,0x0,0x6ae3e00,0x8000,0x1000000,0x4020000,0x8000,0x4029000,0x8000,0x6fe3e00,0x6ae3e00,0x56fe3e00,0x500000,0x0,0x800,0x2000,0x76febe00,0x76fe3e00,0x6ae3e00,0x0,0x0,0x0,0x6ae3e00,0x6ae3e00,0x0,0x14000,0x14000,};
   }
   private static void jj_la1_1() {
      jj_la1_1 = new int[] {0x0,0x4000,0x10001000,0x10000,0x10000000,0x0,0x4000,0x10000,0x10000000,0x10000,0x10000000,0x0,0x0,0x0,0x0,0x700000,0x0,0x10000000,0x10010000,0x10000000,0x0,0x700000,0x0,0x0,0x10000400,0x10000400,0x10011000,0x0,0x0,0x400,0x0,0x10000000,0x4000,0x0,0x0,};
   }
   private static void jj_la1_2() {
      jj_la1_2 = new int[] {0x0,0x0,0x1,0x0,0x1,0x0,0x0,0x0,0x1,0x0,0x21401,0x0,0x0,0x0,0x0,0xe0,0x0,0x1,0x1,0x21401,0x0,0xe0,0x0,0x0,0x21401,0x21401,0x1,0x21400,0x0,0x0,0x0,0x1,0x0,0x0,0x0,};
   }
   private static void jj_la1_3() {
      jj_la1_3 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x4,0x4,0x0,0x4,0x4,0x0,0x0,0x0,0x0,0x0,0x0,};
   }

  public JCRSQLParser(java.io.InputStream stream) {
     this(stream, null);
  }
  public JCRSQLParser(java.io.InputStream stream, String encoding) {
    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source = new JCRSQLParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 35; i++) jj_la1[i] = -1;
  }

  public void ReInit(java.io.InputStream stream) {
     ReInit(stream, null);
  }
  public void ReInit(java.io.InputStream stream, String encoding) {
    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jjtree.reset();
    jj_gen = 0;
    for (int i = 0; i < 35; i++) jj_la1[i] = -1;
  }

  public JCRSQLParser(java.io.Reader stream) {
    jj_input_stream = new SimpleCharStream(stream, 1, 1);
    token_source = new JCRSQLParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 35; i++) jj_la1[i] = -1;
  }

  public void ReInit(java.io.Reader stream) {
    jj_input_stream.ReInit(stream, 1, 1);
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jjtree.reset();
    jj_gen = 0;
    for (int i = 0; i < 35; i++) jj_la1[i] = -1;
  }

  public JCRSQLParser(JCRSQLParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 35; i++) jj_la1[i] = -1;
  }

  public void ReInit(JCRSQLParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jjtree.reset();
    jj_gen = 0;
    for (int i = 0; i < 35; i++) jj_la1[i] = -1;
  }

  final private Token jj_consume_token(int kind) throws ParseException {
    Token oldToken;
    if ((oldToken = token).next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    if (token.kind == kind) {
      jj_gen++;
      return token;
    }
    token = oldToken;
    jj_kind = kind;
    throw generateParseException();
  }

  final public Token getNextToken() {
    if (token.next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    jj_gen++;
    return token;
  }

  final public Token getToken(int index) {
    Token t = token;
    for (int i = 0; i < index; i++) {
      if (t.next != null) t = t.next;
      else t = t.next = token_source.getNextToken();
    }
    return t;
  }

  final private int jj_ntk() {
    if ((jj_nt=token.next) == null)
      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
    else
      return (jj_ntk = jj_nt.kind);
  }

  private java.util.Vector jj_expentries = new java.util.Vector();
  private int[] jj_expentry;
  private int jj_kind = -1;

  public ParseException generateParseException() {
    jj_expentries.removeAllElements();
    boolean[] la1tokens = new boolean[101];
    for (int i = 0; i < 101; i++) {
      la1tokens[i] = false;
    }
    if (jj_kind >= 0) {
      la1tokens[jj_kind] = true;
      jj_kind = -1;
    }
    for (int i = 0; i < 35; i++) {
      if (jj_la1[i] == jj_gen) {
        for (int j = 0; j < 32; j++) {
          if ((jj_la1_0[i] & (1<<j)) != 0) {
            la1tokens[j] = true;
          }
          if ((jj_la1_1[i] & (1<<j)) != 0) {
            la1tokens[32+j] = true;
          }
          if ((jj_la1_2[i] & (1<<j)) != 0) {
            la1tokens[64+j] = true;
          }
          if ((jj_la1_3[i] & (1<<j)) != 0) {
            la1tokens[96+j] = true;
          }
        }
      }
    }
    for (int i = 0; i < 101; i++) {
      if (la1tokens[i]) {
        jj_expentry = new int[1];
        jj_expentry[0] = i;
        jj_expentries.addElement(jj_expentry);
      }
    }
    int[][] exptokseq = new int[jj_expentries.size()][];
    for (int i = 0; i < jj_expentries.size(); i++) {
      exptokseq[i] = (int[])jj_expentries.elementAt(i);
    }
    return new ParseException(token, exptokseq, tokenImage);
  }

  final public void enable_tracing() {
  }

  final public void disable_tracing() {
  }

}
