/*
 * 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.openjpa.kernel.jpql;

import java.io.PrintStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.AccessController;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;

import org.apache.openjpa.conf.Compatibility;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.BrokerFactory;
import org.apache.openjpa.kernel.ExpressionStoreQuery;
import org.apache.openjpa.kernel.FillStrategy;
import org.apache.openjpa.kernel.QueryContext;
import org.apache.openjpa.kernel.QueryOperations;
import org.apache.openjpa.kernel.ResultShape;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.kernel.exps.AbstractExpressionBuilder;
import org.apache.openjpa.kernel.exps.Context;
import org.apache.openjpa.kernel.exps.Expression;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.Literal;
import org.apache.openjpa.kernel.exps.Parameter;
import org.apache.openjpa.kernel.exps.Path;
import org.apache.openjpa.kernel.exps.QueryExpressions;
import org.apache.openjpa.kernel.exps.Resolver;
import org.apache.openjpa.kernel.exps.Subquery;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.Localizer.Message;
import org.apache.openjpa.lib.util.OrderedMap;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.UserException;


/**
 * Builder for JPQL expressions. This class takes the query parsed
 * in {@link JPQL} and converts it to an expression tree using
 * an {@link ExpressionFactory}. Public for unit testing purposes.
 *
 * @author Marc Prud'hommeaux
 * @author Patrick Linskey
 */
public class JPQLExpressionBuilder
    extends AbstractExpressionBuilder
    implements JPQLTreeConstants {

    private static final int VAR_PATH = 1;
    private static final int VAR_ERROR = 2;

    private static final Localizer _loc = Localizer.forPackage
        (JPQLExpressionBuilder.class);

    private final Stack<Context> contexts = new Stack<>();
    private OrderedMap<Object, Class<?>> parameterTypes;
    private int aliasCount = 0;
    private boolean inAssignSubselectProjection = false;
    private boolean hasParameterizedInExpression = false;

    /**
     * Constructor.
     *
     * @param factory the expression factory to use
     * @param query used to resolve variables, parameters,
     * and class names used in the query
     * @param parsedQuery the parsed query
     */
    public JPQLExpressionBuilder(ExpressionFactory factory,
        ExpressionStoreQuery query, Object parsedQuery) {
        super(factory, query.getResolver());

        contexts.push(new Context(parsedQuery instanceof ParsedJPQL
            ? (ParsedJPQL) parsedQuery
            : parsedQuery instanceof String
            ? getParsedQuery((String) parsedQuery)
            : null, null, null));

        if (ctx().parsed == null)
            throw new InternalException(parsedQuery + "");
    }

    @Override
    protected Localizer getLocalizer() {
        return _loc;
    }

    @Override
    protected ClassLoader getClassLoader() {
        // we don't resolve in the context of anything but ourselves
        return getClass().getClassLoader();
    }

    protected ParsedJPQL getParsedQuery() {
        return ctx().parsed;
    }

    protected ParsedJPQL getParsedQuery(String jpql) {
        return new ParsedJPQL(jpql);
    }

    private void setCandidate(ClassMetaData cmd, String schemaAlias) {
        addAccessPath(cmd);

        if (cmd != null)
            ctx().meta = cmd;

        if (schemaAlias != null)
            ctx().schemaAlias = schemaAlias;
    }

    private String nextAlias() {
        return "jpqlalias" + (++aliasCount);
    }

    protected ClassMetaData resolveClassMetaData(JPQLNode node) {
        // handle looking up alias names
        String schemaName = assertSchemaName(node);
        ClassMetaData cmd = getClassMetaData(schemaName, false);
        if (cmd != null)
            return cmd;

        // we might be referencing a collection field of a subquery's parent
        if (isPath(node)) {
            Path path = getPath(node);
            FieldMetaData fmd = path.last();
            cmd = getFieldType(fmd);
            if (cmd == null && fmd.isElementCollection())
                cmd = fmd.getDefiningMetaData();
            return cmd;
        }

        // now run again to throw the correct exception
        return getClassMetaData(schemaName, true);
    }

    private ClassMetaData getClassMetaData(String alias, boolean assertValid) {
        ClassLoader loader = getClassLoader();
        MetaDataRepository repos = resolver.getConfiguration().
            getMetaDataRepositoryInstance();

        // first check for the alias
        ClassMetaData cmd = repos.getMetaData(alias, loader, false);

        if (cmd != null)
            return cmd;

        // now check for the class name; this is not technically permitted
        // by the JPA spec, but is required in order to be able to execute
        // JPQL queries from other facades (like JDO) that do not have
        // the concept of entity names or aliases
        Class<?> c = resolver.classForName(alias, null);
        if (c != null)
            cmd = repos.getMetaData(c, loader, assertValid);
        else if (assertValid)
            cmd = repos.getMetaData(alias, loader, false);

        if (cmd == null && assertValid) {
            String close = repos.getClosestAliasName(alias);
            if (close != null)
                throw parseException(EX_USER, "not-schema-name-hint",
                    new Object[]{ alias, close, repos.getAliasNames() }, null);
            else
                throw parseException(EX_USER, "not-schema-name",
                    new Object[]{ alias, repos.getAliasNames() }, null);
        }

        return cmd;
    }

    private Class<?> getCandidateType() {
        return getCandidateMetaData().getDescribedType();
    }

    private ClassMetaData getCandidateMetaData() {
        if (ctx().meta != null)
            return ctx().meta;

        ClassMetaData cls = getCandidateMetaData(root());
        if (cls == null)
            throw parseException(EX_USER, "not-schema-name",
                new Object[]{ root() }, null);

        setCandidate(cls, null);
        return cls;
    }

    protected ClassMetaData getCandidateMetaData(JPQLNode node) {
        // examing the node to find the candidate query
        // ### this should actually be the primary SELECT instance
        // resolved against the from variable declarations
        JPQLNode from = node.findChildByID(JJTFROMITEM, true);
        if (from == null) {
            // OPENJPA-15 allow subquery without a FROMITEM
            if (node.id == JJTSUBSELECT) {
                from = node.findChildByID(JJTFROM, true);
            }
            else {
                throw parseException(EX_USER, "no-from-clause", null, null);
            }
        }

        for (int i = 0; i < from.children.length; i++) {
            JPQLNode n = from.children[i];

            if (n.id == JJTABSTRACTSCHEMANAME) {
                // we simply return the first abstract schema child
                // as resolved into a class
                ClassMetaData cmd = resolveClassMetaData(n);

                if (cmd != null)
                    return cmd;

                // not a schema: treat it as a class
                String cls = assertSchemaName(n);
                if (cls == null)
                    throw parseException(EX_USER, "not-schema-name",
                        new Object[]{ root() }, null);

                return getClassMetaData(cls, true);
            }
            // OPENJPA-15 support subquery's from clause do not start with
            // identification_variable_declaration()
            if (node.id == JJTSUBSELECT) {
                if (n.id == JJTINNERJOIN) {
                    n = n.getChild(0);
                }
                if (n.id == JJTPATH) {
                    Path path = getPath(n);
                    FieldMetaData fmd = path.last();
                    ClassMetaData cmd = getFieldType(fmd);
                    if (cmd == null && fmd.isElementCollection())
                        cmd = fmd.getDefiningMetaData();
                    if (cmd != null) {
                        return cmd;
                    }
                    else {
                        throw parseException(EX_USER, "no-alias",
                                new Object[]{ n }, null);
                    }
                }
            }
        }

        return null;
    }

    @Override
    protected String currentQuery() {
        return ctx().parsed == null || root().parser == null ? null
            : root().parser.jpql;
    }

    QueryExpressions getQueryExpressions() {
        QueryExpressions exps = new QueryExpressions();
        exps.setContexts(contexts);

        evalQueryOperation(exps);

        Expression filter = null;
        Expression from = ctx().from;
        if (from == null)
            from = evalFromClause(root().id == JJTSELECT);
        filter = and(from, filter);
        filter = and(evalWhereClause(), filter);
        filter = and(evalSelectClause(exps), filter);

        exps.filter = filter == null ? factory.emptyExpression() : filter;

        evalGroupingClause(exps);
        evalHavingClause(exps);
        evalFetchJoins(exps);
        evalSetClause(exps);
        evalOrderingClauses(exps);

        if (parameterTypes != null)
            exps.parameterTypes = parameterTypes;

        exps.accessPath = getAccessPath();
        exps.hasInExpression = this.hasParameterizedInExpression;

        // verify parameters are consistent.
        validateParameters();

        return exps;
    }

    private Expression and(Expression e1, Expression e2) {
        return e1 == null ? e2 : e2 == null ? e1 : factory.and(e1, e2);
    }

    private static String assemble(JPQLNode node) {
        return assemble(node, ".", 0);
    }

    /**
     * Assemble the children of the specific node by appending each
     * child, separated by the delimiter.
     */
    private static String assemble(JPQLNode node, String delimiter, int last) {
        StringBuilder result = new StringBuilder();
        JPQLNode[] parts = node.children;
        for (int i = 0; parts != null && i < parts.length - last; i++)
            result.append(result.length() > 0 ? delimiter : "").
                append(parts[i].text);

        return result.toString();
    }

    private Expression assignSubselectProjection(JPQLNode node,
        QueryExpressions exps) {
        inAssignSubselectProjection = true;
        exps.projections = new Value[1];
        exps.projectionClauses = new String[1];
        exps.projectionAliases = new String[1];

        Value val = getValue(node);
        exps.projections[0] = val;
        exps.projectionClauses[0] =
            projectionClause(node.id == JJTSCALAREXPRESSION ?
                firstChild(node) : node);
        inAssignSubselectProjection = false;
        return null;
    }

    /**
     * Assign projections for NEW contructor in selection list.
     *     Example:  SELECT NEW Person(p.name) FROM Person p WHERE ...
     */
    private Expression assignProjections(JPQLNode parametersNode,
        QueryExpressions exps, List<Value> projections,
        List<String> projectionClauses, List<String> projectionAliases) {
        int count = parametersNode.getChildCount();

        Expression exp = null;
        for (int i = 0; i < count; i++) {
            JPQLNode parent = parametersNode.getChild(i);
            JPQLNode node = firstChild(parent);
            JPQLNode aliasNode = parent.children.length > 1 ? right(parent)
                : null;
            Value proj = getValue(node);
            String alias = aliasNode != null ? aliasNode.text :
                projectionClause(node.id == JJTSCALAREXPRESSION ?
                        firstChild(node) : node);
            if (aliasNode != null)
                proj.setAlias(alias);
            projections.add(proj);
            projectionClauses.add(alias);
            projectionAliases.add(alias);
        }
        return exp;
    }

    private void evalProjectionsResultShape(JPQLNode selectionsNode,
        QueryExpressions exps,
        List<Value> projections,
        List<String> projectionClauses,
        List<String> projectionAliases) {
        int count = selectionsNode.getChildCount();
        Class<?> resultClass = null;
        ResultShape<?> resultShape = null;
        if (count > 1) {
            // muti-selection
            resultClass = Object[].class;
            resultShape = new ResultShape(resultClass, new FillStrategy.Array<>(Object[].class));
        }

        for (int i = 0; i < count; i++) {
            JPQLNode parent = selectionsNode.getChild(i);
            JPQLNode node = firstChild(parent);
            if (node.id == JJTCONSTRUCTOR) {
                // build up the fully-qualified result class name by
                // appending together the components of the children
                String resultClassName = assemble(left(node));
                Class<?> constructor = resolver.classForName(resultClassName, null);
                if (constructor == null) {
                    // try resolve it again using simple name
                    int n = left(node).getChildCount();
                    String baseName = left(node).getChild(n-1).text;
                    constructor = resolver.classForName(baseName, null);
                }

                if (constructor == null && resolver.getConfiguration().getUseTCCLinSelectNew()) {
                    try {
                        if (System.getSecurityManager() != null) {
                            constructor = AccessController.doPrivileged(
                                    J2DoPrivHelper.getForNameAction(resultClassName, false,
                                        AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction())));
                        }
                        else {
                            constructor = Thread.currentThread().getContextClassLoader().loadClass(resultClassName);
                        }
                    } catch (Exception e) {
                        // ignore
                    }
                }

                if (constructor == null)
                    throw parseException(EX_USER, "no-constructor",
                            new Object[]{ resultClassName }, null);

                List<Value> terms = new ArrayList<>();
                List<String> aliases = new ArrayList<>();
                List<String> clauses = new ArrayList<>();
                // now assign the arguments to the select clause as the projections
                assignProjections(right(node), exps, terms, aliases, clauses);
                FillStrategy fill = new FillStrategy.NewInstance(constructor);
                ResultShape<?> cons = new ResultShape(constructor, fill);
                for (Value val : terms) {
                    Class<?> type = val.getType();
                    cons.nest(new ResultShape(type, new FillStrategy.Assign(), type.isPrimitive()));
                }
                if (count == 1) {
                    resultClass = constructor;
                    resultShape = cons;
                }
                else
                    resultShape.nest(cons);
                projections.addAll(terms);
                projectionAliases.addAll(aliases);
                projectionClauses.addAll(clauses);

            } else {
                JPQLNode aliasNode = parent.children.length > 1 ? right(parent)
                        : null;
                Value proj = getValue(node);
                String alias = aliasNode != null ? aliasNode.text :
                    projectionClause(node.id == JJTSCALAREXPRESSION ?
                            firstChild(node) : node);
                if (aliasNode != null)
                    proj.setAlias(alias);
                projections.add(proj);
                projectionClauses.add(alias);
                projectionAliases.add(alias);
                Class<?> type = proj.getType();
                ResultShape<?> projShape = new ResultShape(type, new FillStrategy.Assign(), type.isPrimitive());

                if (count == 1)
                    resultShape = projShape;
                else
                    resultShape.nest(projShape);
            }
        }
        exps.shape = resultShape;
        exps.resultClass = resultClass;
    }

    private String projectionClause(JPQLNode node) {
        switch (node.id) {
        case JJTTYPE:
            return projectionClause(firstChild(node));
        default:
            return assemble(node);
        }
    }

    private void evalQueryOperation(QueryExpressions exps) {
        // determine whether we want to select, delete, or update
        if (root().id == JJTSELECT || root().id == JJTSUBSELECT)
            exps.operation = QueryOperations.OP_SELECT;
        else if (root().id == JJTDELETE)
            exps.operation = QueryOperations.OP_DELETE;
        else if (root().id == JJTUPDATE)
            exps.operation = QueryOperations.OP_UPDATE;
        else
            throw parseException(EX_UNSUPPORTED, "unrecognized-operation",
                new Object[]{ root() }, null);
    }

    private void evalGroupingClause(QueryExpressions exps) {
        // handle GROUP BY clauses
        JPQLNode groupByNode = root().findChildByID(JJTGROUPBY, false);

        if (groupByNode == null)
            return;

        int groupByCount = groupByNode.getChildCount();

        exps.grouping = new Value[groupByCount];

        for (int i = 0; i < groupByCount; i++) {
            JPQLNode node = groupByNode.getChild(i);
            Value val = getValue(node);
            if (val instanceof Path) {
                FieldMetaData fmd = ((Path) val).last();
                if (fmd != null && fmd.getValue().getTypeMetaData() != null && fmd.getValue().isEmbedded())
                    throw parseException(EX_USER, "cant-groupby-embeddable",
                        new Object[]{ node.getChildCount() > 1 ? assemble(node) : node.text }, null);
            }
            exps.grouping[i] = val;
        }
    }

    private void evalHavingClause(QueryExpressions exps) {
        // handle HAVING clauses
        JPQLNode havingNode = root().findChildByID(JJTHAVING, false);

        if (havingNode == null)
            return;

        exps.having = getExpression(onlyChild(havingNode));
    }

    private void evalOrderingClauses(QueryExpressions exps) {
        // handle ORDER BY clauses
        JPQLNode orderby = root().findChildByID(JJTORDERBY, false);
        if (orderby != null) {
            int ordercount = orderby.getChildCount();
            exps.ordering = new Value[ordercount];
            exps.orderingClauses = new String[ordercount];
            exps.orderingAliases = new String[ordercount];
            exps.ascending = new boolean[ordercount];
            for (int i = 0; i < ordercount; i++) {
                JPQLNode node = orderby.getChild(i);
                JPQLNode firstChild = firstChild(node);
                exps.ordering[i] = getValue(firstChild);
                exps.orderingClauses[i] = assemble(firstChild);
                exps.orderingAliases[i] = firstChild.text;

                // ommission of ASC/DESC token implies ascending
                exps.ascending[i] = node.getChildCount() <= 1 ||
                    lastChild(node).id == JJTASCENDING ? true : false;
            }
            // check if order by select item result alias
            for (int i = 0; i < ordercount; i++) {
                if (exps.orderingClauses[i] != null &&
                    !exps.orderingClauses[i].equals(""))
                    continue;
                for (int j = 0; j < exps.projections.length; j++) {
                    if (exps.projectionAliases[j].equalsIgnoreCase(
                        exps.orderingAliases[i])) {
                        exps.ordering[i] = exps.projections[j];
                        break;
                    }
                }
            }
        }
    }

    private Expression evalSelectClause(QueryExpressions exps) {
        if (exps.operation != QueryOperations.OP_SELECT)
            return null;

        JPQLNode selectNode = root();

        JPQLNode selectClause = selectNode.
            findChildByID(JJTSELECTCLAUSE, false);
        if (selectClause != null && selectClause.hasChildID(JJTDISTINCT))
            exps.distinct = QueryExpressions.DISTINCT_TRUE
                          | QueryExpressions.DISTINCT_AUTO;
        else
            exps.distinct = QueryExpressions.DISTINCT_FALSE;

        // handle SELECT clauses
        JPQLNode expNode = selectNode.
        findChildByID(JJTSELECTEXPRESSIONS, true);
        if (expNode == null) {
            return null;
        }

        int selectCount = expNode.getChildCount();
        JPQLNode selectChild = firstChild(expNode);

        if (selectClause.parent.id == JJTSUBSELECT) {
            exps.distinct &= ~QueryExpressions.DISTINCT_AUTO;
            return assignSubselectProjection(onlyChild(selectChild), exps);
        }
        // if we are selecting just one thing and that thing is the
        // schema's alias, then do not treat it as a projection
        if (selectCount == 1 && selectChild != null &&
            selectChild.getChildCount() == 1 &&
            onlyChild(selectChild) != null) {
            JPQLNode child = onlyChild(selectChild);
            if (child.id == JJTSCALAREXPRESSION)
                child = onlyChild(child);
            if (assertSchemaAlias().equalsIgnoreCase(child.text)) {
                return null;
            }
        }
        // JPQL does not filter relational joins for projections
        exps.distinct &= ~QueryExpressions.DISTINCT_AUTO;
        exps.projections = new Value[selectCount];
        List<Value> projections = new ArrayList<>();
        List<String> aliases = new ArrayList<>();
        List<String> clauses = new ArrayList<>();
        evalProjectionsResultShape(expNode, exps, projections, aliases, clauses);
        exps.projections = projections.toArray(new Value[projections.size()]);
        exps.projectionAliases = aliases.toArray(new String[aliases.size()]);
        exps.projectionClauses = clauses.toArray(new String[clauses.size()]);
        return null;
    }

    private String assertSchemaAlias() {
        String alias = ctx().schemaAlias;

        if (alias == null)
            throw parseException(EX_USER, "alias-required",
                new Object[]{ ctx().meta }, null);

        return alias;
    }

    protected Expression evalFetchJoins(QueryExpressions exps) {
        Expression filter = null;

        // handle JOIN FETCH
        Set<String> joins = null;
        Set<String> innerJoins = null;

        JPQLNode[] outers = root().findChildrenByID(JJTOUTERFETCHJOIN);
        for (int i = 0; outers != null && i < outers.length; i++)
            (joins == null ? joins = new TreeSet<>() : joins).
                add(getPath(onlyChild(outers[i])).last().getFullName(false));

        JPQLNode[] inners = root().findChildrenByID(JJTINNERFETCHJOIN);
        for (int i = 0; inners != null && i < inners.length; i++) {
            String path = getPath(onlyChild(inners[i])).last()
                .getFullName(false);
            (joins == null ? joins = new TreeSet<>() : joins).add(path);
            (innerJoins == null
                    ? innerJoins = new TreeSet<>()
                    : innerJoins).add(path);
        }

        if (joins != null)
            exps.fetchPaths = joins.
                toArray(new String[joins.size()]);
        if (innerJoins != null)
            exps.fetchInnerPaths = innerJoins.
                toArray(new String[innerJoins.size()]);

        return filter;
    }

    protected void evalSetClause(QueryExpressions exps) {
        // handle SET field = value
        JPQLNode[] nodes = root().findChildrenByID(JJTUPDATEITEM);
        for (int i = 0; nodes != null && i < nodes.length; i++) {
            Path path = getPath(firstChild(nodes[i]));
            if (path.last().getValue().getEmbeddedMetaData() != null)
                throw parseException(EX_USER, "cant-bulk-update-embeddable",
                        new Object[]{assemble(firstChild(nodes[i]))}, null);

            JPQLNode lastChild = lastChild(nodes[i]);
            Value val = (lastChild.children == null)
                      ? null : getValue(onlyChild(lastChild));
            exps.putUpdate(path, val);
        }
    }

    private Expression evalWhereClause() {
        // evaluate the WHERE clause
        JPQLNode whereNode = root().findChildByID(JJTWHERE, false);
        if (whereNode == null)
            return null;
        return (Expression) eval(whereNode);
    }

    private Expression evalFromClause(boolean needsAlias) {
        // build up the alias map in the FROM clause
        JPQLNode from = root().findChildByID(JJTFROM, false);
        if (from == null)
            throw parseException(EX_USER, "no-from-clause", null, null);
        return evalFromClause(from, needsAlias);
    }

    private Expression evalFromClause(JPQLNode from, boolean needsAlias) {
        Expression exp = null;

        for (int i = 0; i < from.children.length; i++) {
            JPQLNode node = from.children[i];

            if (node.id == JJTFROMITEM)
                exp = evalFromItem(exp, node, needsAlias);
            else if (node.id == JJTOUTERJOIN)
                exp = addJoin(node, false, exp);
            else if (node.id == JJTINNERJOIN)
                exp = addJoin(node, true, exp);
            else if (node.id == JJTINNERFETCHJOIN)
                ; // we handle inner fetch joins in the evalFetchJoins() method
            else if (node.id == JJTOUTERFETCHJOIN)
                ; // we handle outer fetch joins in the evalFetchJoins() method
            else
                throw parseException(EX_USER, "not-schema-name",
                    new Object[]{ node }, null);
        }

        return exp;
    }

    private Expression getSubquery(String alias, Path path, Expression exp) {
        Value var = getVariable(alias, true);
        // this bind is for validateMapPath to resolve alias
        Expression bindVar = factory.bindVariable(var, path);
        FieldMetaData fmd = path.last();
        ClassMetaData candidate = getFieldType(fmd);
        if (candidate == null && fmd.isElementCollection())
            candidate = fmd.getDefiningMetaData();

        setCandidate(candidate, alias);

        Context subContext = ctx();
        Subquery subquery = ctx().getSubquery();
        if (subquery == null){
            subquery = factory.newSubquery(candidate, true, alias);
            subContext.setSubquery(subquery);
        }
        else {
            subquery.setSubqAlias(alias);
        }

        Path subpath = factory.newPath(subquery);
        subpath.setSchemaAlias(path.getCorrelationVar());
        subpath.setMetaData(candidate);
        subquery.setMetaData(candidate);
        if (fmd.isElementCollection())
            exp = and(exp, bindVar);
        else
            exp = and(exp, factory.equal(path, subpath));

        return exp;
    }

    /**
     * Adds a join condition to the given expression.
     *
     * @param node the node to check
     * @param inner whether or not the join should be an inner join
     * @param exp an existing expression to AND, or null if none
     * @return the Expression with the join condition added
     */
    private Expression addJoin(JPQLNode node, boolean inner, Expression exp) {
        // the type will be the declared type for the field
        JPQLNode firstChild = firstChild(node);
        Path path = null;
        if (firstChild.id == JJTQUALIFIEDPATH)
            path = getQualifiedPath(firstChild);
        else
            path = getPath(firstChild, false, inner);

        JPQLNode alias = node.getChildCount() >= 2 ? right(node) : null;
        // OPENJPA-15 support subquery's from clause do not start with
        // identification_variable_declaration()
        if (inner && ctx().getParent() != null && ctx().schemaAlias == null) {
            return getSubquery(alias.text, path, exp);
        }

        return addJoin(path, alias, exp);
    }

    private Expression addJoin(Path path, JPQLNode aliasNode,
        Expression exp) {
        FieldMetaData fmd = path.last();

        if (fmd == null)
            throw parseException(EX_USER, "path-no-meta",
                new Object[]{ path, null }, null);

        String alias = aliasNode != null ? aliasNode.text : nextAlias();

        Value var = getVariable(alias, true);
        var.setMetaData(getFieldType(fmd));

        Expression join = null;

        // if the variable is already bound, get the var's value and
        // do a regular contains with that
        boolean bound = isBound(var);
        if (bound) {
            var = getValue(aliasNode, VAR_PATH);
        } else {
            bind(var);
            join = and(join, factory.bindVariable(var, path));
        }

        if (!fmd.isTypePC()) // multi-valued relation
        {
            if (bound)
                join = and(join, factory.contains(path, var));

            setImplicitContainsTypes(path, var, CONTAINS_TYPE_ELEMENT);
        }

        return and(exp, join);
    }

    private Expression evalFromItem(Expression exp, JPQLNode node,
        boolean needsAlias) {
        ClassMetaData cmd = resolveClassMetaData(firstChild(node));

        String alias = null;

        if (node.getChildCount() < 2) {
            if (needsAlias)
                throw parseException(EX_USER, "alias-required",
                    new Object[]{ cmd }, null);
        } else {
            alias = right(node).text;
            JPQLNode left = left(node);
            addSchemaToContext(alias, cmd);

            // check to see if the we are referring to a path in the from
            // clause, since we might be in a subquery against a collection
            if (isPath(left)) {
                Path path = getPath(left);
                return getSubquery(alias, path, exp);
            } else {
                // we have an alias: bind it as a variable
                Value var = getVariable(alias, true);
                var.setMetaData(cmd);
                bind(var);
            }
        }

        // ### we assign the first FROMITEM instance we see as
        // the global candidate, which is incorrect: we should
        // instead be mapping this to the SELECTITEM to see
        // which is the desired candidate
        if (ctx().schemaAlias == null)
            setCandidate(cmd, alias);
        else
            addAccessPath(cmd);

        return exp;
    }

    @Override
    protected boolean isDeclaredVariable(String name) {
        // JPQL doesn't support declaring variables
        return false;
    }

    /**
     * Check to see if the specific node is a path (vs. a schema name)
     */
    boolean isPath(JPQLNode node) {
        if (node.getChildCount() < 2)
            return false;

        final String name = firstChild(node).text;
        if (name == null)
            return false;

        // handle the case where the class name is the alias
        // for the candidate (we don't use variables for this)
        if (getMetaDataForAlias(name) != null)
            return true;

        if (!isSeenVariable(name))
            return false;

        final Value var = getVariable(name, false);

        if (var != null)
            return isBound(var);

        return false;
    }

    private static ClassMetaData getFieldType(FieldMetaData fmd) {
        if (fmd == null)
            return null;

        ClassMetaData cmd = null;
        ValueMetaData vmd;

        if ((vmd = fmd.getElement()) != null)
            cmd = vmd.getDeclaredTypeMetaData();
        else if ((vmd = fmd.getKey()) != null)
            cmd = vmd.getDeclaredTypeMetaData();
        else if ((vmd = fmd.getValue()) != null)
            cmd = vmd.getDeclaredTypeMetaData();

        if (cmd == null || cmd.getDescribedType() == Object.class)
            cmd = fmd.getDeclaredTypeMetaData();

        return cmd;
    }

    /**
     * Identification variables in JPQL are case insensitive, so lower-case
     * all variables we are going to bind.
     */
    @Override
    protected Value getVariable(String id, boolean bind) {
        if (id == null)
            return null;

        if (bind && getDefinedVariable(id) == null)
            return createVariable(id, bind);

        return super.getVariable(id.toLowerCase(), bind);
    }

    protected Value getDefinedVariable(String id) {
        return ctx().getVariable(id);
    }

    @Override
    protected boolean isSeenVariable(String var) {
        Context c = ctx().findContext(var);
        if (c != null)
            return true;
        return false;
    }

    /**
     * Returns the class name using the children of the JPQLNode.
     */
    private String assertSchemaName(JPQLNode node) {
        if (node.id != JJTABSTRACTSCHEMANAME)
            throw parseException(EX_USER, "not-identifer",
                new Object[]{ node }, null);

        return assemble(node);
    }

    private void checkEmbeddable(Value val) {
        checkEmbeddable(val, currentQuery());
    }

    public static void checkEmbeddable(Value val, String currentQuery) {
        Path path = val instanceof Path ? (Path) val : null;
        if (path == null)
            return;

        FieldMetaData fmd = path.last();
        if (fmd == null)
            return;

        ValueMetaData vm = fmd.isElementCollection() ? fmd.getElement()
            : fmd.getValue();
        if (vm.getEmbeddedMetaData() != null) {
            //throw parseException(EX_USER, "bad-predicate",
            //    new Object[]{ currentQuery() }, null);
            String argStr = _loc.get("bad-predicate",
                new Object[] {fmd.getName()}).getMessage();
            Message msg = _loc.get("parse-error", argStr, currentQuery);
            throw new UserException(msg, null);
        }
    }

    /**
     * Recursive helper method to evaluate the given node.
     */
    private Object eval(JPQLNode node) {
        Value val1 = null;
        Value val2 = null;
        Value val3 = null;

        boolean not = node.not;

        switch (node.id) {
            case JJTSCALAREXPRESSION:
                return eval(onlyChild(node));

            case JJTTYPE:
                return getType(onlyChild(node));

            case JJTTYPELITERAL:
                return getTypeLiteral(node);

            case JJTCLASSNAME:
                return getPathOrConstant(node);

            case JJTCASE:
                return eval(onlyChild(node));

            case JJTSIMPLECASE:
                return getSimpleCaseExpression(node);

            case JJTGENERALCASE:
                return getGeneralCaseExpression(node);

            case JJTWHEN:
                return getWhenCondition(node);

            case JJTWHENSCALAR:
                return getWhenScalar(node);

            case JJTCOALESCE:
                return getCoalesceExpression(node);

            case JJTNULLIF:
                return getNullIfExpression(node);

            case JJTWHERE: // top-level WHERE clause
                return getExpression(onlyChild(node));

            case JJTBOOLEANLITERAL:
                return factory.newLiteral("true".equalsIgnoreCase
                    (node.text) ? Boolean.TRUE : Boolean.FALSE,
                    Literal.TYPE_BOOLEAN);

            case JJTINTEGERLITERAL:
                // use BigDecimal because it can handle parsing exponents
                BigDecimal intlit = new BigDecimal
                    (node.text.endsWith("l") || node.text.endsWith("L")
                        ? node.text.substring(0, node.text.length() - 1)
                        : node.text).
                    multiply(new BigDecimal(negative(node)));
                return factory.newLiteral(intlit.longValue(),
                    Literal.TYPE_NUMBER);

            case JJTDECIMALLITERAL:
                BigDecimal declit = new BigDecimal
                    (node.text.endsWith("d") || node.text.endsWith("D") ||
                        node.text.endsWith("f") || node.text.endsWith("F")
                        ? node.text.substring(0, node.text.length() - 1)
                        : node.text).
                    multiply(new BigDecimal(negative(node)));
                return factory.newLiteral(declit, Literal.TYPE_NUMBER);

            case JJTSTRINGLITERAL:
            case JJTTRIMCHARACTER:
            case JJTESCAPECHARACTER:
                return factory.newLiteral(trimQuotes(node.text),
                    Literal.TYPE_SQ_STRING);

            case JJTSTRINGLITERAL2:
                return factory.newLiteral(trimDoubleQuotes(node.text),
                    Literal.TYPE_SQ_STRING);

            case JJTPATTERNVALUE:
                return eval(firstChild(node));

            case JJTNAMEDINPUTPARAMETER:
                return getParameter(onlyChild(node).text, false, false);

            case JJTPOSITIONALINPUTPARAMETER:
                return getParameter(node.text, true, false);

            case JJTCOLLECTIONPARAMETER:
                JPQLNode child = onlyChild(node);
                boolean positional = child.id == JJTPOSITIONALINPUTPARAMETER;
                if (!positional)
                    child = onlyChild(child);
                return getParameter(child.text,
                    positional, true);

            case JJTOR: // x OR y
                return factory.or(getExpression(left(node)),
                    getExpression(right(node)));

            case JJTAND: // x AND y
                return and(getExpression(left(node)),
                    getExpression(right(node)));

            case JJTEQUALS: // x = y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, null);
                return factory.equal(val1, val2);

            case JJTNOTEQUALS: // x <> y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, null);
                return factory.notEqual(val1, val2);

            case JJTLESSTHAN: // x < y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, null);
                return factory.lessThan(val1, val2);

            case JJTLESSOREQUAL: // x <= y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, null);
                return factory.lessThanEqual(val1, val2);

            case JJTGREATERTHAN: // x > y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, null);
                return factory.greaterThan(val1, val2);

            case JJTGREATEROREQUAL: // x >= y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, null);
                return factory.greaterThanEqual(val1, val2);

            case JJTADD: // x + y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, TYPE_NUMBER);
                return factory.add(val1, val2);

            case JJTSUBTRACT: // x - y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, TYPE_NUMBER);
                return factory.subtract(val1, val2);

            case JJTMULTIPLY: // x * y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, TYPE_NUMBER);
                return factory.multiply(val1, val2);

            case JJTDIVIDE: // x / y
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, TYPE_NUMBER);
                return factory.divide(val1, val2);

            case JJTBETWEEN: // x.field [NOT] BETWEEN 5 AND 10
                val1 = getValue(child(node, 0, 3));
                val2 = getValue(child(node, 1, 3));
                val3 = getValue(child(node, 2, 3));
                setImplicitTypes(val1, val2, null);
                setImplicitTypes(val1, val3, null);
                return evalNot(not, and(factory.greaterThanEqual(val1, val2),
                    factory.lessThanEqual(val1, val3)));

            case JJTIN: // x.field [NOT] IN ('a', 'b', 'c')
                        // TYPE(x...) [NOT] IN (entityTypeLiteral1,...)
                Expression inExp = null;
                Iterator<JPQLNode> inIterator = node.iterator();
                // the first child is the path
                JPQLNode first = inIterator.next();
                val1 = getValue(first);
                while (inIterator.hasNext()) {
                    JPQLNode next = inIterator.next();
                    if (first.id == JJTTYPE && next.id == JJTTYPELITERAL)
                        val2 = getTypeLiteral(next);
                    else
                        val2 = getValue(next);
                    if (val2 instanceof Parameter) {
                        hasParameterizedInExpression = true;
                    }
                    // special case for <value> IN (<subquery>) or
                    // <value> IN (<single value>)
                    if (useContains(not, val1, val2, node))
                        return evalNot(not, factory.contains(val2, val1));

                    // this is currently a sequence of OR expressions, since we
                    // do not have support for IN expressions
                    setImplicitTypes(val1, val2, null);
                    if (isVerticalTypeInExpr(val1, node) && not) {
                        if (inExp == null)
                            inExp = factory.notEqual(val1, val2);
                        else
                            inExp = factory.and(inExp, factory.notEqual(val1, val2));
                    } else {
                        if (inExp == null)
                            inExp = factory.equal(val1, val2);
                        else
                            inExp = factory.or(inExp, factory.equal(val1, val2));
                    }
                }


                // we additionally need to add in a "NOT NULL" clause, since
                // the IN behavior that is expected by the CTS also expects
                // to filter our NULLs
                if (isVerticalTypeInExpr(val1, node))
                    return inExp;
                else
                    return and(evalNot(not, inExp),
                            factory.notEqual(val1, factory.getNull()));

            case JJTISNULL: // x.field IS [NOT] NULL
                val1 = getValue(onlyChild(node));
                checkEmbeddable(val1);
                if (not)
                    return factory.notEqual
                        (val1, factory.getNull());
                else
                    return factory.equal
                        (val1, factory.getNull());

            case JJTPATH:
                return getPathOrConstant(node);

            case JJTIDENTIFIER:
            case JJTIDENTIFICATIONVARIABLE:
                return getIdentifier(node);

            case JJTQUALIFIEDPATH:
                return getQualifiedPath(node);

            case JJTQUALIFIEDIDENTIFIER:
                // KEY(e), VALUE(e), ENTRY(e)
                return getQualifiedIdentifier(node);

            case JJTGENERALIDENTIFIER:
                // KEY(e), VALUE(e)
                if (node.parent.parent.id == JJTWHERE || node.parent.id == JJTGROUPBY)
                    return getGeneralIdentifier(onlyChild(node), true);
                return getQualifiedIdentifier(onlyChild(node));

            case JJTNOT:
                return factory.not(getExpression(onlyChild(node)));

            case JJTLIKE: // field LIKE '%someval%'
                val1 = getValue(left(node));
                val2 = getValue(right(node));

                setImplicitType(val1, TYPE_STRING);
                setImplicitType(val2, TYPE_STRING);

                // look for an escape character beneath the node
                String escape = null;
                JPQLNode escapeNode = right(node).
                    findChildByID(JJTESCAPECHARACTER, true);
                if (escapeNode != null)
                    escape = trimQuotes(onlyChild(escapeNode).text);

                if (not)
                    return factory.notMatches(val1, val2, "_", "%", escape);
                else
                    return factory.matches(val1, val2, "_", "%", escape);

            case JJTISEMPTY:
                return evalNot(not,
                    factory.isEmpty(getValue(onlyChild(node))));

            case JJTSIZE:
                return factory.size(getValue(onlyChild(node)));

            case JJTINDEX:
                return factory.index(getValue(onlyChild(node)));

            case JJTUPPER:
                val1 = getValue(onlyChild(node));
                setImplicitType(val1, TYPE_STRING);
                return factory.toUpperCase(val1);

            case JJTLOWER:
                return factory.toLowerCase(getStringValue(onlyChild(node)));

            case JJTLENGTH:
                return factory.stringLength(getStringValue(onlyChild(node)));

            case JJTABS:
                return factory.abs(getNumberValue(onlyChild(node)));

            case JJTSQRT:
                return factory.sqrt(getNumberValue(onlyChild(node)));

            case JJTMOD:
                val1 = getValue(left(node));
                val2 = getValue(right(node));
                setImplicitTypes(val1, val2, TYPE_NUMBER);
                return factory.mod(val1, val2);

            case JJTTRIM: // TRIM([[where] [char] FROM] field)
                val1 = getValue(lastChild(node));
                setImplicitType(val1, TYPE_STRING);

                Boolean trimWhere = null;

                JPQLNode firstTrimChild = firstChild(node);

                if (node.getChildCount() > 1) {
                    trimWhere =
                        firstTrimChild.id == JJTTRIMLEADING ? Boolean.TRUE
                            :
                            firstTrimChild.id == JJTTRIMTRAILING ? Boolean.FALSE
                                : null;
                }

                Value trimChar;

                // if there are 3 children, then we know the trim
                // char is the second node
                if (node.getChildCount() == 3)
                    trimChar = getValue(secondChild(node));
                    // if there are two children, then we need to check to see
                    // if the first child is a leading/trailing/both node,
                    // or the trim character node
                else if (node.getChildCount() == 2
                    && firstTrimChild.id != JJTTRIMLEADING
                    && firstTrimChild.id != JJTTRIMTRAILING
                    && firstTrimChild.id != JJTTRIMBOTH)
                    trimChar = getValue(firstChild(node));
                    // othwerwise, we default to trimming the space character
                else
                    trimChar = factory.newLiteral(" ", Literal.TYPE_STRING);

                return factory.trim(val1, trimChar, trimWhere);

            case JJTCONCAT:
                if (node.children.length < 2)
                	throw parseException(EX_USER, "less-child-count",
                        new Object[]{2, node,
                            Arrays.asList(node.children) }, null);

                val1 = getValue(firstChild(node));
                val2 = getValue(secondChild(node));
                setImplicitType(val1, TYPE_STRING);
                setImplicitType(val2, TYPE_STRING);
                Value concat = factory.concat(val1, val2);
                for (int i = 2; i < node.children.length; i++) {
                	val2 = getValue(node.children[i]);
                    setImplicitType(val2, TYPE_STRING);
                	concat = factory.concat(concat, val2);
                }
                return concat;

            case JJTSUBSTRING:
                // Literals are forced to be Integers because PostgreSQL rejects Longs in SUBSTRING parameters.
                // This however does not help if an expression like 1+1 is passed as parameter.
                val1 = getValue(firstChild(node));
                JPQLNode child2 = secondChild(node);
                if (child2.id == JJTINTEGERLITERAL) {
                    val2 = getIntegerValue(child2);
                } else {
                    val2 = getValue(child2);
                }
                if (node.getChildCount() == 3) {
                    JPQLNode child3 = thirdChild(node);
                    if (child3.id == JJTINTEGERLITERAL) {
                        val3 = getIntegerValue(child3);
                    } else {
                        val3 = getValue(child3);
                    }
                }
                setImplicitType(val1, TYPE_STRING);
                setImplicitType(val2, Integer.TYPE);
                if (node.children.length == 3)
                    setImplicitType(val3, Integer.TYPE);

                return convertSubstringArguments(factory, val1, val2, val3);

            case JJTLOCATE:
                Value locatePath = getValue(firstChild(node));
                Value locateSearch = getValue(secondChild(node));
                Value locateFromIndex = null;
                // Literals are forced to be Integers because PostgreSQL rejects Longs in POSITION parameters.
                // This however does not help if an expression like 1+1 is passed as parameter.
                if (node.getChildCount() > 2) { // optional start index arg
                    JPQLNode child3 = thirdChild(node);
                    if (child3.id == JJTINTEGERLITERAL) {
                        locateFromIndex = getIntegerValue(child3);
                    } else
                        locateFromIndex = getValue(child3);
                }
                setImplicitType(locatePath, TYPE_STRING);
                setImplicitType(locateSearch, TYPE_STRING);

                if (locateFromIndex != null)
                    setImplicitType(locateFromIndex, Integer.TYPE);

                return factory.indexOf(locateSearch,
                    locateFromIndex == null ? locatePath
                        : factory.newArgumentList(locatePath, locateFromIndex));

            case JJTAGGREGATE:
                // simply pass-through while asserting a single child
                return eval(onlyChild(node));

            case JJTCOUNT:
                JPQLNode c = lastChild(node);
                if (c.id == JJTIDENTIFIER)
                    // count(e)
                    return factory.count(getPath(node, false, true));
                return factory.count(getValue(c));

            case JJTMAX:
                return factory.max(getNumberValue(onlyChild(node)));

            case JJTMIN:
                return factory.min(getNumberValue(onlyChild(node)));

            case JJTSUM:
                return factory.sum(getNumberValue(onlyChild(node)));

            case JJTAVERAGE:
                return factory.avg(getNumberValue(onlyChild(node)));

            case JJTDISTINCTPATH:
                return factory.distinct(getValue(onlyChild(node)));

            case JJTEXISTS:
                return factory.isNotEmpty((Value) eval(onlyChild(node)));

            case JJTANY:
                return factory.any((Value) eval(onlyChild(node)));

            case JJTALL:
                return factory.all((Value) eval(onlyChild(node)));

            case JJTSUBSELECT:
                return getSubquery(node);

            case JJTMEMBEROF:
                val1 = getValue(left(node), VAR_PATH);
                val2 = getValue(right(node), VAR_PATH);
                checkEmbeddable(val2);
                setImplicitContainsTypes(val2, val1, CONTAINS_TYPE_ELEMENT);
                return evalNot(not, factory.contains(val2, val1));

            case JJTCURRENTDATE:
                return factory.getCurrentDate(Date.class);

            case JJTCURRENTTIME:
                return factory.getCurrentTime(Time.class);

            case JJTCURRENTTIMESTAMP:
                return factory.getCurrentTimestamp(Timestamp.class);

            case JJTSELECTEXTENSION:
                assertQueryExtensions("SELECT");
                return eval(onlyChild(node));

            case JJTGROUPBYEXTENSION:
                assertQueryExtensions("GROUP BY");
                return eval(onlyChild(node));

            case JJTORDERBYEXTENSION:
                assertQueryExtensions("ORDER BY");
                return eval(onlyChild(node));

            case JJTDATELITERAL:
                return factory.newLiteral(node.text, Literal.TYPE_DATE);

            case JJTTIMELITERAL:
                return factory.newLiteral(node.text, Literal.TYPE_TIME);

            case JJTTIMESTAMPLITERAL:
                return factory.newLiteral(node.text, Literal.TYPE_TIMESTAMP);

            default:
                throw parseException(EX_FATAL, "bad-tree",
                    new Object[]{ node }, null);
        }
    }

    private boolean useContains(boolean not, Value val1, Value val2, JPQLNode node) {
        if (isVerticalTypeInExpr(val1, node) && not)
            return false;
        else
            return (!(val2 instanceof Literal) && node.getChildCount() == 2);
    }

    private boolean isVerticalTypeInExpr(Value val, JPQLNode node) {
        if (node.id != JJTIN)
            return false;
        return factory.isVerticalType(val);
    }

    private Value getIntegerValue(JPQLNode node) {
        BigDecimal bigdec = new BigDecimal
        (node.text.endsWith("l") || node.text.endsWith("L")
            ? node.text.substring(0, node.text.length() - 1)
            : node.text).
        multiply(new BigDecimal(negative(node)));
        return factory.newLiteral(bigdec.intValue(),
                Literal.TYPE_NUMBER);
    }

    /**
     * Converts JPQL substring() function to OpenJPA ExpressionFactory
     * substring() arguments.
     *
     * @param val1 the original String
     * @param val2 the 1-based start index as per JPQL substring() semantics
     * @param val3 the length of the returned string as per JPQL semantics
     *
     */
    public static Value convertSubstringArguments(ExpressionFactory factory,
    		Value val1, Value val2, Value val3) {
        if (val3 != null)
            return factory.substring(val1, factory.newArgumentList(val2, val3));
        else
            return factory.substring(val1, val2);
    }
    private void assertQueryExtensions(String clause) {
        OpenJPAConfiguration conf = resolver.getConfiguration();
        switch(conf.getCompatibilityInstance().getJPQL()) {
            case Compatibility.JPQL_WARN:
                // check if we've already warned for this query-factory combo
                StoreContext ctx = resolver.getQueryContext().getStoreContext();
                String query = currentQuery();
                if (ctx.getBroker() != null && query != null) {
                    String key = getClass().getName() + ":" + query;
                    BrokerFactory factory = ctx.getBroker().getBrokerFactory();
                    Object hasWarned = factory.getUserObject(key);
                    if (hasWarned != null)
                        break;
                    else
                        factory.putUserObject(key, Boolean.TRUE);
                }
                Log log = conf.getLog(OpenJPAConfiguration.LOG_QUERY);
                if (log.isWarnEnabled())
                    log.warn(_loc.get("query-extensions-warning", clause,
                        currentQuery()));
                break;
            case Compatibility.JPQL_STRICT:
                throw new ParseException(_loc.get("query-extensions-error",
                    clause, currentQuery()).getMessage());
            case Compatibility.JPQL_EXTENDED:
                break;
            default:
                throw new IllegalStateException(
                    "Compatibility.getJPQL() == "
                        + conf.getCompatibilityInstance().getJPQL());
        }
    }

    @Override
    public void setImplicitTypes(Value val1, Value val2,
        Class<?> expected) {
        String currQuery = currentQuery();
        setImplicitTypes(val1, val2, expected, resolver, parameterTypes,
            currQuery);
    }


    public static void setImplicitTypes(Value val1, Value val2,
        Class<?> expected, Resolver resolver, OrderedMap<Object,Class<?>> parameterTypes,
        String currentQuery) {
        AbstractExpressionBuilder.setImplicitTypes(val1, val2, expected,
            resolver);

        // as well as setting the types for conversions, we also need to
        // ensure that any parameters are declared with the correct type,
        // since the JPA spec expects that these will be validated
        Parameter param = val1 instanceof Parameter ? (Parameter) val1
            : val2 instanceof Parameter ? (Parameter) val2 : null;
        Path path = val1 instanceof Path ? (Path) val1
            : val2 instanceof Path ? (Path) val2 : null;

        // we only check for parameter-to-path comparisons
        if (param == null || path == null || parameterTypes == null)
            return;

        FieldMetaData fmd = path.last();
        if (fmd == null)
            return;

        if (expected == null)
            checkEmbeddable(path, currentQuery);

        Class<?> type = path.getType();
        if (type == null)
            return;

        Object paramKey = param.getParameterKey();
        if (paramKey == null)
            return;

        // make sure we have already declared the parameter
        if (parameterTypes.containsKey(paramKey))
            parameterTypes.put(paramKey, type);
    }

    private Value getStringValue(JPQLNode node) {
        return getTypeValue(node, TYPE_STRING);
    }

    private Value getNumberValue(JPQLNode node) {
        return getTypeValue(node, TYPE_NUMBER);
    }

    private Value getTypeValue(JPQLNode node, Class<?> implicitType) {
        Value val = getValue(node);
        setImplicitType(val, implicitType);
        return val;
    }

    private Value getSubquery(JPQLNode node) {
        final boolean subclasses = true;

        // parse the subquery
        ParsedJPQL parsed = new ParsedJPQL(node.parser.jpql, node);
        Context subContext = new Context(parsed, null, ctx());
        contexts.push(subContext);

        ClassMetaData candidate = getCandidateMetaData(node);
        Subquery subq = subContext.getSubquery();
        if (subq == null) {
            subq = factory.newSubquery(candidate, subclasses, nextAlias());
            subContext.setSubquery(subq);
        }
        subq.setMetaData(candidate);

        // evaluate from clause for resolving variables defined in subquery
        JPQLNode from = node.getChild(1);
        subContext.from = evalFromClause(from, true);

        try {
            QueryExpressions subexp = getQueryExpressions();
            subq.setQueryExpressions(subexp);
            if (subexp.projections.length > 0)
                checkEmbeddable(subexp.projections[0]);
            return subq;
        } finally {
            // remove the subquery parse context
            contexts.pop();
        }
    }

    /**
     * Creates and records the names and order of parameters. The parameters are
     * identified by a key with its type preserved. The second argument
     * determines whether the first argument is used as-is or converted to
     * an Integer as parameter key.
     *
     * @param id the text as it appears in the parsed node
     * @param positional if true the first argument is converted to an integer
     * @param isCollectionValued true for collection-valued parameters
     */
    private Parameter getParameter(String id, boolean positional,
        boolean isCollectionValued) {
        if (parameterTypes == null)
            parameterTypes = new OrderedMap<>();
        Object paramKey = positional ? Integer.parseInt(id) : id;
        if (!parameterTypes.containsKey(paramKey))
            parameterTypes.put(paramKey, TYPE_OBJECT);

        ClassMetaData meta = null;
        int index;
        if (positional) {
            try {
                // indexes in JPQL are 1-based, as opposed to 0-based in
                // the core ExpressionFactory
                index = Integer.parseInt(id) - 1;
            } catch (NumberFormatException e) {
                throw parseException(EX_USER, "bad-positional-parameter",
                    new Object[]{ id }, e);
            }

            if (index < 0)
                throw parseException(EX_USER, "bad-positional-parameter",
                    new Object[]{ id }, null);
        } else {
            index = parameterTypes.indexOf(id);
        }
        Parameter param = isCollectionValued
            ? factory.newCollectionValuedParameter(paramKey, TYPE_OBJECT)
            : factory.newParameter(paramKey, TYPE_OBJECT);
        param.setMetaData(meta);
        param.setIndex(index);

        return param;
    }

    /**
     * Checks to see if we should evaluate for a NOT expression.
     */
    private Expression evalNot(boolean not, Expression exp) {
        return not ? factory.not(exp) : exp;
    }

    /**
     * Trim off leading and trailing single-quotes, and then
     * replace any internal '' instances with ' (since repeating the
     * quote is the JPQL mechanism of escaping a single quote).
     */
    private String trimQuotes(String str) {
        if (str == null || str.length() <= 1)
            return str;

        if (str.startsWith("'") && str.endsWith("'"))
            str = str.substring(1, str.length() - 1);

        int index = -1;

        while ((index = str.indexOf("''", index + 1)) != -1)
            str = str.substring(0, index + 1) + str.substring(index + 2);

        return str;
    }

    /**
     * Trim off leading and trailing double-quotes.
     */
    private String trimDoubleQuotes(String str) {
        if (str == null || str.length() <= 1)
            return str;

        if (str.startsWith("\"") && str.endsWith("\""))
            str = str.substring(1, str.length() - 1);

        return str;
    }

    /**
     * An IntegerLiteral and DecimalLiteral node will
     * have a child node of Negative if it is negative:
     * if so, this method returns -1, else it returns 1.
     */
    private short negative(JPQLNode node) {
        if (node.children != null && node.children.length == 1
            && firstChild(node).id == JJTNEGATIVE)
            return -1;
        else
            return 1;
    }

    private Value getIdentifier(JPQLNode node) {
        final String name = node.text;
        final Value val = getVariable(name, false);

        ClassMetaData cmd = getMetaDataForAlias(name);

        if (cmd != null) {
            // handle the case where the class name is the alias
            // for the candidate (we don't use variables for this)
            Value thiz = null;
            if (ctx().subquery == null ||
                ctx().getSchema(name.toLowerCase()) == null) {
                if (ctx().subquery != null && inAssignSubselectProjection)
                    thiz = factory.newPath(ctx().subquery);
                else
                    thiz = factory.getThis();
            } else {
                thiz = factory.newPath(ctx().subquery);
            }
            ((Path)thiz).setSchemaAlias(name);
            thiz.setMetaData(cmd);
            return thiz;
        } else if (val instanceof Path) {
            return val;
        } else if (val instanceof Value) {
            if (val.isVariable()) {
                // can be an entity type literal
                Class<?> c = resolver.classForName(name, null);
                if (c != null) {
                    Value lit = factory.newTypeLiteral(c, Literal.TYPE_CLASS);
                    Class<?> candidate = getCandidateType();
                    ClassMetaData can = getClassMetaData(candidate.getName(),
                            false);
                    ClassMetaData meta = getClassMetaData(name, false);
                    if (candidate.isAssignableFrom(c))
                        lit.setMetaData(meta);
                    else
                        lit.setMetaData(can);
                    return lit;
                }
            }
            return val;
        }

        throw parseException(EX_USER, "unknown-identifier",
            new Object[]{ name }, null);
    }

    private Path validateMapPath(JPQLNode node, JPQLNode id) {
        Path path = (Path) getValue(id);
        FieldMetaData fld = path.last();

        if (fld == null && ctx().subquery != null) {
            Value var = getVariable(id.text, false);
            if (var != null) {
                path = factory.newPath(var);
                fld = path.last();
            }
        }

        if (fld != null) {
            // validate the field is of type java.util.Map
            if (fld.getDeclaredTypeCode() != JavaTypes.MAP) {
                String oper = "VALUE";
                if (node.id == JJTENTRY)
                    oper = "ENTRY";
                else if (node.id == JJTKEY)
                    oper = "KEY";
                throw parseException(EX_USER, "bad-qualified-identifier",
                    new Object[]{ id.text, oper}, null);
            }
        }
        else
            throw parseException(EX_USER, "unknown-type",
                new Object[]{ id.text}, null);

        return path;
    }

    private Value getGeneralIdentifier(JPQLNode node, boolean verifyEmbeddable) {
        JPQLNode id = onlyChild(node);
        Path path = validateMapPath(node, id);

        if (node.id == JJTKEY)
            path = (Path) factory.getKey(path);
        FieldMetaData fld = path.last();
        ClassMetaData meta = fld.getKey().getTypeMetaData();
        if (verifyEmbeddable &&
            (node.id == JJTKEY && meta != null && fld.getKey().isEmbedded()) ||
            (node.id == JJTVALUE && fld.isElementCollection() &&
                 fld.getElement().getEmbeddedMetaData() != null)) {
                 // check basic type
            if (node.parent.parent.id == JJTGROUPBY)
                throw parseException(EX_USER, "cant-groupby-key-value-embeddable",
                    new Object[]{ node.id == JJTVALUE ? "VALUE" : "KEY", id.text }, null);
            else
                throw parseException(EX_USER, "bad-general-identifier",
                    new Object[]{ node.id == JJTVALUE ? "VALUE" : "KEY", id.text }, null);
        }
        return path;
    }

    private Value getQualifiedIdentifier(JPQLNode node) {
        JPQLNode id = onlyChild(node);
        Path path = validateMapPath(node, id);

        if (node.id == JJTVALUE)
            return path;

        Value value = getValue(id);
        if (node.id == JJTKEY)
            return factory.mapKey(path, value);
        else
            return factory.mapEntry(path, value);
    }

    private Path getQualifiedPath(JPQLNode node) {
        return getQualifiedPath(node, false, true);
    }

    private Path getQualifiedPath(JPQLNode node, boolean pcOnly, boolean inner)
    {
        int nChild = node.getChildCount();
        JPQLNode firstChild = firstChild(node);
        JPQLNode id = firstChild.id == JJTKEY ? onlyChild(firstChild) :
               firstChild;
        Path path = validateMapPath(firstChild, id);

        if (firstChild.id == JJTIDENTIFIER)
            return getPath(node);

        FieldMetaData fld = path.last();
        path = (Path) factory.getKey(path);
        ClassMetaData meta = fld.getKey().getTypeMetaData();

        if (meta == null)
            throw parseException(EX_USER, "bad-qualified-path",
                new Object[]{ id.text }, null);

        path.setMetaData(meta);

        // walk through the children and assemble the path
        boolean allowNull = !inner;
        for (int i = 1; i < nChild; i++) {
            path = (Path) traversePath(path, node.children[i].text, pcOnly,
                allowNull);

            // all traversals but the first one will always be inner joins
            allowNull = false;
        }
        return path;
    }

    private Value getTypeLiteral(JPQLNode node) {
        JPQLNode type = onlyChild(node);
        final String name = type.text;
        final Value val = getVariable(name, false);

        if (val instanceof Value && val.isVariable()) {
            Class<?> c = resolver.classForName(name, null);
            if (c != null) {
                Value typeLit = factory.newTypeLiteral(c, Literal.TYPE_CLASS);
                typeLit.setMetaData(getClassMetaData(name, false));
                return typeLit;
            }
        }

        throw parseException(EX_USER, "not-type-literal",
            new Object[]{ name }, null);
    }

    private Value getPathOrConstant(JPQLNode node) {
        // first check to see if the path is an enum or static field, and
        // if so, load it
        String className = assemble(node, ".", 1);
        Class<?> c = resolver.classForName(className, null);
        if (c != null) {
            String fieldName = lastChild(node).text;
            int type = (c.isEnum() ? Literal.TYPE_ENUM : Literal.TYPE_UNKNOWN);
            try {
                Field field = c.getField(fieldName);
                Object value = field.get(null);
                return factory.newLiteral(value, type);
            } catch (NoSuchFieldException nsfe) {
                if (node.inEnumPath)
                    throw parseException(EX_USER, "no-field",
                        new Object[]{ c.getName(), fieldName }, nsfe);
                else
                    return getPath(node, false, true);
            } catch (Exception e) {
                throw parseException(EX_USER, "unaccessible-field",
                    new Object[]{ className, fieldName }, e);
            }
        } else {
            return getPath(node, false, true);
        }
    }

    /**
     * Process type_discriminator
     *     type_discriminator ::=
     *         TYPE(general_identification_variable |
     *         single_valued_object_path_expression |
     *         input_parameter )
     */
    private Value getType(JPQLNode node) {
        switch (node.id) {
        case JJTIDENTIFIER:
            return factory.type(getValue(node));

        case JJTNAMEDINPUTPARAMETER:
            return factory.type(getParameter(node.text, false, false));

        case JJTPOSITIONALINPUTPARAMETER:
            return factory.type(getParameter(node.text, true, false));

        case JJTGENERALIDENTIFIER:
            return factory.type(getQualifiedIdentifier(onlyChild(node)));

        default:
            // TODO: enforce jpa2.0 spec rules.
            // A single_valued_object_field is designated by the name of
            // an association field in a one-to-one or many-to-one relationship
            // or a field of embeddable class type.
            // The type of a single_valued_object_field is the abstract schema
            // type of the related entity or embeddable class
            Value path = getPath(node, false, true);
            return factory.type(path);
        }
    }

    private Path getPath(JPQLNode node) {
        return getPath(node, false, true);
    }

    private Path getPath(JPQLNode node, boolean pcOnly, boolean inner) {
        // resolve the first element against the aliases map ...
        // i.e., the path "SELECT x.id FROM SomeClass x where x.id > 10"
        // will need to have "x" in the alias map in order to resolve
        Path path = null;

        final String name = firstChild(node).text;
        final Value val = getVariable(name, false);

        // handle the case where the class name is the alias
        // for the candidate (we don't use variables for this)
        if (name.equalsIgnoreCase(ctx().schemaAlias)) {
            if (ctx().subquery != null) {
                path = factory.newPath(ctx().subquery);
                path.setMetaData(ctx().subquery.getMetaData());
            } else {
                path = factory.newPath();
                path.setMetaData(ctx().meta);
            }
        } else if (getMetaDataForAlias(name) != null)
            path = newPath(null, getMetaDataForAlias(name));
        else if (val instanceof Path)
            path = (Path) val;
        else if (val.getMetaData() != null)
            path = newPath(val, val.getMetaData());
        else
            throw parseException(EX_USER, "path-invalid",
                new Object[]{ assemble(node), name }, null);

        path.setSchemaAlias(name);

        // walk through the children and assemble the path
        boolean allowNull = !inner;
        for (int i = 1; i < node.children.length; i++) {
            if (path.isXPath()) {
                for (int j = i; j <node.children.length; j++)
                    path = (Path) traverseXPath(path, node.children[j].text);
                return path;
            }
            path = (Path) traversePath(path, node.children[i].text, pcOnly,
                allowNull);
            if (ctx().getParent() != null && ctx().getVariable(path.getSchemaAlias()) == null) {
                path.setSubqueryContext(ctx(), name);
            }

            // all traversals but the first one will always be inner joins
            allowNull = false;
        }

        return path;
    }

    @Override
    protected Class<?> getDeclaredVariableType(String name) {
        ClassMetaData cmd = getMetaDataForAlias(name);
        if (cmd != null)
            return cmd.getDescribedType();

        if (name != null && name.equals(ctx().schemaAlias))
            return getCandidateType();

        // JPQL has no declared variables
        return null;
    }

    /**
     * Returns an Expression for the given node by eval'ing it.
     */
    private Expression getExpression(JPQLNode node) {
        Object exp = eval(node);

        // check for boolean values used as expressions
        if (!(exp instanceof Expression))
            return factory.asExpression((Value) exp);
        return (Expression) exp;
    }

    /**
     * Returns a Simple Case Expression for the given node by eval'ing it.
     */
    private Value getSimpleCaseExpression(JPQLNode node) {
        Object caseOperand = eval(node.getChild(0));
        int nChild = node.getChildCount();

        Object val = eval(lastChild(node));
        Object exp[] = new Expression[nChild - 2];
        for (int i = 1; i < nChild - 1; i++)
            exp[i-1] = eval(node.children[i]);

        return factory.simpleCaseExpression((Value) caseOperand,
            (Expression[]) exp, (Value) val);
    }

    /**
     * Returns a General Case Expression for the given node by eval'ing it.
     */
    private Value getGeneralCaseExpression(JPQLNode node) {
        int nChild = node.getChildCount();

        Object val = eval(lastChild(node));
        Object exp[] = new Expression[nChild - 1];
        for (int i = 0; i < nChild - 1; i++)
            exp[i] = eval(node.children[i]);

        return factory.generalCaseExpression((Expression[]) exp, (Value) val);
    }

    private Expression getWhenCondition(JPQLNode node) {
        Object exp = eval(firstChild(node));
        Object val = eval(secondChild(node));
        return factory.whenCondition((Expression) exp, (Value) val);
    }

    private Expression getWhenScalar(JPQLNode node) {
        Object val1 = eval(firstChild(node));
        Object val2 = eval(secondChild(node));
        return factory.whenScalar((Value) val1, (Value) val2);
    }

    private Value getCoalesceExpression(JPQLNode node) {
        int nChild = node.getChildCount();

        Object vals[] = new Value[nChild];
        for (int i = 0; i < nChild; i++)
            vals[i] = eval(node.children[i]);

        return factory.coalesceExpression((Value[]) vals);
    }

    private Value getNullIfExpression(JPQLNode node) {
        Object val1 = eval(firstChild(node));
        Object val2 = eval(secondChild(node));

        return factory.nullIfExpression((Value) val1, (Value) val2);
    }

    private Value getValue(JPQLNode node) {
        if (node.id == JJTQUALIFIEDIDENTIFIER)
            return getQualifiedIdentifier(onlyChild(node));
        return getValue(node, VAR_PATH);
    }

    private Path newPath(Value val, ClassMetaData meta) {
        Path path = val == null ? factory.newPath() : factory.newPath(val);
        if (meta != null)
            path.setMetaData(meta);
        return path;
    }

    /**
     * Returns a Value for the given node by eval'ing it.
     */
    private Value getValue(JPQLNode node, int handleVar) {
        Value val = (Value) eval(node);

        // determined how to evaluate a variable
        if (!val.isVariable())
            return val;
        else if (handleVar == VAR_PATH && !(val instanceof Path))
            return newPath(val, val.getMetaData());
        else if (handleVar == VAR_ERROR)
            throw parseException(EX_USER, "unexpected-var",
                new Object[]{ node.text }, null);
        else
            return val;
    }

    ////////////////////////////
    // Parse Context Management
    ////////////////////////////

    private Context ctx() {
        return  contexts.peek();
    }

    private JPQLNode root() {
        return ctx().parsed.root;
    }

    private ClassMetaData getMetaDataForAlias(String alias) {
        for (int i = contexts.size() - 1; i >= 0; i--) {
            Context context =  contexts.get(i);
            if (alias.equalsIgnoreCase(context.schemaAlias))
                return context.meta;
        }

        return null;
    }

    @Override
    protected void addSchemaToContext(String id, ClassMetaData meta) {
        ctx().addSchema(id.toLowerCase(), meta);
    }

    @Override
    protected void addVariableToContext(String id, Value var) {
        ctx().addVariable(id, var);
    }

    @Override
    protected Value getVariable(String var) {
        Context c = ctx();
        Value v = c.getVariable(var);
        if (v != null)
            return v;
        if (c.getParent() != null)
            return c.getParent().findVariable(var);

        return null;
    }

    ////////////////////////////
    // Node traversal utilities
    ////////////////////////////

    private JPQLNode onlyChild(JPQLNode node)
        throws UserException {
        JPQLNode child = firstChild(node);

        if (node.children.length > 1)
            throw parseException(EX_USER, "multi-children",
                new Object[]{ node, Arrays.asList(node.children) }, null);

        return child;
    }

    /**
     * Returns the left node (the first of the children), and asserts
     * that there are exactly two children.
     */
    private JPQLNode left(JPQLNode node) {
        return child(node, 0, 2);
    }

    /**
     * Returns the right node (the second of the children), and asserts
     * that there are exactly two children.
     */
    private JPQLNode right(JPQLNode node) {
        return child(node, 1, 2);
    }

    private JPQLNode child(JPQLNode node, int childNum, int assertCount) {
        if (node.children.length != assertCount)
            throw parseException(EX_USER, "wrong-child-count",
                new Object[]{assertCount, node,
                    Arrays.asList(node.children) }, null);

        return node.children[childNum];
    }

    private JPQLNode firstChild(JPQLNode node) {
        if (node.children == null || node.children.length == 0)
            throw parseException(EX_USER, "no-children",
                new Object[]{ node }, null);
        return node.children[0];
    }

    private static JPQLNode secondChild(JPQLNode node) {
        return node.children[1];
    }

    private static JPQLNode thirdChild(JPQLNode node) {
        return node.children[2];
    }

    private static JPQLNode lastChild(JPQLNode node) {
        return lastChild(node, 0);
    }

    /**
     * The Nth from the last child. E.g.,
     * lastChild(1) will return the second-to-the-last child.
     */
    private static JPQLNode lastChild(JPQLNode node, int fromLast) {
        return node.children[node.children.length - (1 + fromLast)];
    }

    /**
     * Base node that will be generated by the JPQLExpressionBuilder; base
     * class of the {@link SimpleNode} that is used by {@link JPQL}.
     *
     * @author Marc Prud'hommeaux
     * @see Node
     * @see SimpleNode
     */
    protected abstract static class JPQLNode
        implements Node, Serializable {

        private static final long serialVersionUID = 1L;
        final int id;
        final JPQL parser;
        JPQLNode parent;
        JPQLNode[] children;
        String text;
        boolean not = false;
        boolean inEnumPath = false;

        public JPQLNode(JPQL parser, int id) {
            this.id = id;
            this.parser = parser;
            this.inEnumPath = parser.inEnumPath;
        }

        public void jjtOpen() {
        }

        public void jjtClose() {
        }

        JPQLNode[] findChildrenByID(int id) {
            Collection<JPQLNode> set = new LinkedHashSet<>();
            findChildrenByID(id, set);
            return set.toArray(new JPQLNode[set.size()]);
        }

        private void findChildrenByID(int id, Collection<JPQLNode> set) {
            for (int i = 0; children != null && i < children.length; i++) {
                if (children[i].id == id)
                    set.add(children[i]);

                children[i].findChildrenByID(id, set);
            }
        }

        boolean hasChildID(int id) {
            return findChildByID(id, false) != null;
        }

        JPQLNode findChildByID(int id, boolean recurse) {
            for (int i = 0; children != null && i < children.length; i++) {
                JPQLNode child = children[i];

                if (child.id == id)
                    return children[i];

                if (recurse) {
                    JPQLNode found = child.findChildByID(id, recurse);
                    if (found != null)
                        return found;
                }
            }

            // not found
            return null;
        }

        public void jjtSetParent(Node parent) {
            this.parent = (JPQLNode) parent;
        }

        public Node jjtGetParent() {
            return this.parent;
        }

        public void jjtAddChild(Node n, int i) {
            if (children == null) {
                children = new JPQLNode[i + 1];
            } else if (i >= children.length) {
                JPQLNode c[] = new JPQLNode[i + 1];
                System.arraycopy(children, 0, c, 0, children.length);
                children = c;
            }

            children[i] = (JPQLNode) n;
        }

        public Node jjtGetChild(int i) {
            return children[i];
        }

        public int getChildCount() {
            return jjtGetNumChildren();
        }

        public JPQLNode getChild(int index) {
            return (JPQLNode) jjtGetChild(index);
        }

        public Iterator<JPQLNode> iterator() {
            return Arrays.asList(children).iterator();
        }

        public int jjtGetNumChildren() {
            return (children == null) ? 0 : children.length;
        }

        void setText(String text) {
            this.text = text;
        }

        void setToken(Token t) {
            setText(t.image);
        }

        @Override
        public String toString() {
            return JPQLTreeConstants.jjtNodeName[this.id];
        }

        public String toString(String prefix) {
            return prefix + toString();
        }

        /**
         * Debugging method.
         *
         * @see #dump(java.io.PrintStream,String)
         */
        public void dump(String prefix) {
            dump(System.out, prefix);
        }

        public void dump() {
            dump(" ");
        }

        /**
         * Debugging method to output a parse tree.
         *
         * @param out the stream to which to write the debugging info
         * @param prefix the prefix to write out before lines
         */
        public void dump(PrintStream out, String prefix) {
            dump(out, prefix, false);
        }

        public void dump(PrintStream out, String prefix, boolean text) {
            out.println(toString(prefix)
                + (text && this.text != null ? " [" + this.text + "]" : ""));
            if (children != null) {
                for (JPQLNode n : children) {
                    if (n != null) {
                        n.dump(out, prefix + " ", text);
                    }
                }
            }
        }
    }

    /**
     * Public for unit testing purposes.
         */
    public static class ParsedJPQL implements Serializable {
        private static final long serialVersionUID = 1L;

        // This is only ever used during parse; when ParsedJPQL instances
        // are serialized, they will have already been parsed.
        private final transient JPQLNode root;

        private final String query;

        // cache of candidate type data. This is stored here in case this
        // parse tree is reused in a context that does not know what the
        // candidate type is already.
        private Class<?> _candidateType;

        ParsedJPQL(String jpql) {
            this(jpql, parse(jpql));
        }

        ParsedJPQL(String query, JPQLNode root) {
            this.root = root;
            this.query = query;
        }

        private static JPQLNode parse(String jpql) {
            if (jpql == null)
                jpql = "";

            try {
                return (JPQLNode) new JPQL(jpql).parseQuery();
            } catch (Error e) {
                // special handling for Error subclasses, which the
                // parser may sometimes (unfortunately) throw
                throw new UserException(_loc.get("parse-error",
                    new Object[]{ e.toString(), jpql }));
            }
        }

        void populate(ExpressionStoreQuery query) {
            QueryContext ctx = query.getContext();

            // if the owning query's context does not have
            // any candidate class, then set it here
            if (ctx.getCandidateType() == null) {
                if (_candidateType == null)
                    _candidateType = new JPQLExpressionBuilder
                        (null, query, this).getCandidateType();
                ctx.setCandidateType(_candidateType, true);
            }
        }

        /**
         * Public for unit testing purposes.
         */
        public Class<?> getCandidateType() {
            return _candidateType;
        }

        @Override
        public String toString ()
		{
			return this.query;
		}
	}


    // throws an exception if there are numeric parameters which do not start with 1.
    private void validateParameters() {
        if (parameterTypes == null || parameterTypes.isEmpty()) {
            return;
        }

        boolean numericParms = false;
        boolean namedParms = false;

        for (Object key : parameterTypes.keySet()) {

            if (key instanceof Number) {
                if (namedParms) {
                    throw new UserException(_loc.get("mixed-parameter-types", resolver.getQueryContext()
                        .getQueryString(), parameterTypes.keySet().toString()));
                }
                numericParms = true;
            } else {
                if (numericParms) {
                    throw new UserException(_loc.get("mixed-parameter-types", resolver.getQueryContext()
                        .getQueryString(), parameterTypes.keySet().toString()));
                }
                namedParms = true;
            }
        }

        if (numericParms) {
            if (!parameterTypes.keySet().contains(1)) {
                throw new UserException(_loc.get("missing-positional-parameter", resolver.getQueryContext()
                    .getQueryString(), parameterTypes.keySet().toString()));
            }
        }
    }
}

