/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the "License").  You may not use this file except 
 * in compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt or 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html. 
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * HEADER in each file and include the License file at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable, 
 * add the following below this CDDL HEADER, with the 
 * fields enclosed by brackets "[]" replaced with your 
 * own identifying information: Portions Copyright [yyyy] 
 * [name of copyright owner]
 */
// Copyright (c) 1998, 2006, Oracle. All rights reserved.  
package oracle.toplink.essentials.internal.parsing.ejbql;

import persistence.antlr.TokenBuffer;
import persistence.antlr.TokenStreamException;
import persistence.antlr.TokenStream;
import persistence.antlr.RecognitionException;
import persistence.antlr.ParserSharedInputState;

//toplink imports
import oracle.toplink.essentials.exceptions.EJBQLException;
import oracle.toplink.essentials.internal.helper.ConversionManager;
import oracle.toplink.essentials.internal.security.PrivilegedAccessController;
import oracle.toplink.essentials.exceptions.ConversionException;

//java imports
import java.lang.reflect.Field;

/*****************************************************************
 * EJBQLParser is the superclass of all parsers generated
 * for the different versions of ANTLR
 *****************************************************************
 */
public class EJBQLParser extends EJBQLParserBase {

    public static String antlrVersion = null;
    
    public EJBQLParser(TokenBuffer tokenBuf) {
        this(tokenBuf, 3);
    }

    protected EJBQLParser(persistence.antlr.TokenBuffer tokenBuf, int k_) {
        super(tokenBuf, k_);
        initialize();
    }

    public EJBQLParser(ParserSharedInputState state, int k_) {
        super(state, k_);
    }

    protected EJBQLParser(TokenStream lexer, int k) {
        super(lexer, k);
    }

    //Answer "2.7.3", "2.7.2" or "2.7.0", depending on the existence of the declared field,
    //"tokenTypeToASTClassMap", which was added in 2.7.2
    public static String ANTLRVersion() throws Exception {
        if (antlrVersion != null){
            return antlrVersion;
        }
        Class versionClass = null;
        try {
            versionClass = ConversionManager.loadClass("persistence.antlr.Version");
        } catch (ConversionException exception){}
        if (versionClass != null) {
            try{
                Field field = PrivilegedAccessController.getField(versionClass, "version", true);
                Object versionValue = PrivilegedAccessController.getValueFromField(field, null);
                field = PrivilegedAccessController.getField(versionClass, "subversion", true);
                Object subversionValue = PrivilegedAccessController.getValueFromField(field, null);
                field = PrivilegedAccessController.getField(versionClass, "patchlevel", true);
                Object patchlevelValue = PrivilegedAccessController.getValueFromField(field, null);
                if (versionValue.equals("2") && subversionValue.equals("7") && patchlevelValue.equals("3")){
                    antlrVersion = "2.7.3";
                } else {
                    antlrVersion = "2.7.2";
                }
            } catch (NoSuchFieldException e){
               antlrVersion = "2.7.2";
            }
        } else {
            antlrVersion = "2.7.0";
        }
        return antlrVersion;
    }

    /**
     * INTERNAL
     * Build a parser for the passed ejbql string, depending on the version of the parser
     */
    public static EJBQLParser buildParserFor(String ejbqlString) throws EJBQLException {
        try {
            return buildParserForANTLR273(ejbqlString);
        } catch (Exception exception) {
            throw EJBQLException.generalParsingException(ejbqlString, exception);
        }
    }

    public static EJBQLParser buildParserForANTLR270(String ejbqlString) throws Exception {
        Class parserClass = PrivilegedAccessController.getClassForName("oracle.toplink.essentials.internal.parsing.ejbql.antlr270.EJBQLParserBuilder");
        return (EJBQLParser)PrivilegedAccessController.invokeMethod(PrivilegedAccessController.getMethod(parserClass, "buildParser", new Class[] { String.class }, false), parserClass, new Object[] { ejbqlString });
    }

    public static EJBQLParser buildParserForANTLR272(String ejbqlString) throws Exception {
        Class parserClass = PrivilegedAccessController.getClassForName("oracle.toplink.essentials.internal.parsing.ejbql.antlr272.EJBQLParserBuilder");
        return (EJBQLParser)PrivilegedAccessController.invokeMethod(PrivilegedAccessController.getMethod(parserClass, "buildParser", new Class[] { String.class }, false), parserClass, new Object[] { ejbqlString });
    }

    public static EJBQLParser buildParserForANTLR273(String ejbqlString) throws Exception {
        Class parserClass = PrivilegedAccessController.getClassForName("oracle.toplink.essentials.internal.parsing.ejbql.antlr273.EJBQLParserBuilder");
        return (EJBQLParser)PrivilegedAccessController.invokeMethod(PrivilegedAccessController.getMethod(parserClass, "buildParser", new Class[] { String.class }, false), parserClass, new Object[] { ejbqlString });
    }

    public void document() throws RecognitionException, TokenStreamException {
        //this is implemented in the generated subclass. This is to simplify EJBQLCall.	
    }
}
