/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
package org.eclipse.persistence.internal.expressions;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.queries.MappedKeyMapContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;
import org.eclipse.persistence.mappings.querykeys.DirectQueryKey;
import org.eclipse.persistence.mappings.querykeys.ForeignReferenceQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.queries.ReadQuery;

/**
 * Represents expression on query keys or mappings.
 * This includes direct, relationships query keys and mappings.
 */
public class QueryKeyExpression extends ObjectExpression {

    /** The name of the query key. */
    protected String name;

    /** Cache the aliased field. Only applies to attributes. */
    protected DatabaseField aliasedField;

    /** Is this a query across a 1:many or many:many relationship. Does not apply to attributes. */
    protected boolean shouldQueryToManyRelationship;

    /** Cache the query key for performance. Store a boolean so we don't repeat the search if there isn't one. */
    transient protected QueryKey queryKey;
    protected boolean hasQueryKey;

    /** Cache the mapping for performance. Store a boolean so we don't repeat the search if there isn't one. */
    transient protected DatabaseMapping mapping;
    protected boolean hasMapping;

    /** PERF: Cache if the expression is an attribute expression. */
    protected Boolean isAttributeExpression;

    protected IndexExpression index;

    protected boolean isClonedForSubQuery = false;

    public QueryKeyExpression() {
        this.shouldQueryToManyRelationship = false;
        this.hasQueryKey = true;
        this.hasMapping = true;
    }

    public QueryKeyExpression(String aName, Expression base) {
        super();
        name = aName;
        baseExpression = base;
        shouldUseOuterJoin = false;
        shouldQueryToManyRelationship = false;
        hasQueryKey = true;
        hasMapping = true;
    }

    /**
     * INTERNAL:
     * Return if the expression is equal to the other.
     * This is used to allow dynamic expression's SQL to be cached.
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (!super.equals(object)) {
            return false;
        }
        QueryKeyExpression expression = (QueryKeyExpression) object;
        // Return false for anyOf expressions, as equality is unknown.
        if (shouldQueryToManyRelationship() || expression.shouldQueryToManyRelationship()) {
            return false;
        }
        return ((getName() == expression.getName()) || ((getName() != null) && getName().equals(expression.getName())));
    }

    /**
     * INTERNAL:
     * Compute a consistent hash-code for the expression.
     * This is used to allow dynamic expression's SQL to be cached.
     */
    @Override
    public int computeHashCode() {
        int hashCode = super.computeHashCode();
        if (getName() != null) {
            hashCode = hashCode + getName().hashCode();
        }
        return hashCode;
    }

    /**
     * INTERNAL:
     * Return the expression to join the main table of this node to any auxiliary tables.
     */
    @Override
    public Expression additionalExpressionCriteria() {
        if (getDescriptor() == null) {
            return null;
        }

        Expression criteria = getDescriptor().getQueryManager().getAdditionalJoinExpression();
        if (criteria != null) {
            criteria = this.baseExpression.twist(criteria, this);
            if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
                criteria.convertToUseOuterJoin();
            }
        }
        if(getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
            if(isUsingOuterJoinForMultitableInheritance()) {
                Expression childrenCriteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression();
                childrenCriteria = this.baseExpression.twist(childrenCriteria, this);
                childrenCriteria.convertToUseOuterJoin();
                if(criteria == null) {
                    criteria = childrenCriteria;
                } else {
                    criteria = criteria.and(childrenCriteria);
                }
            }
        }
        if (getDescriptor().getHistoryPolicy() != null) {
            Expression historyCriteria = getDescriptor().getHistoryPolicy().additionalHistoryExpression(this, this);
            if (criteria != null) {
                criteria = criteria.and(historyCriteria);
            } else {
                criteria = historyCriteria;
            }
        }
        return criteria;
    }

    /**
     * INTERNAL:
     * Used in case outer joins should be printed in FROM clause.
     * Each of the additional tables mapped to expressions that joins it.
     */
    @Override
    public Map additionalExpressionCriteriaMap() {
        if (getDescriptor() == null) {
            return null;
        }

        HashMap tablesJoinExpressions = new HashMap();
        Vector<DatabaseTable> tables = getDescriptor().getTables();
        // skip the main table - start with i=1
        int tablesSize = tables.size();
        if (shouldUseOuterJoin() || (!getSession().getPlatform().shouldPrintInnerJoinInWhereClause())) {
            for (int i=1; i < tablesSize; i++) {
                DatabaseTable table = (DatabaseTable)tables.elementAt(i);
                Expression joinExpression = getDescriptor().getQueryManager().getTablesJoinExpressions().get(table);
                joinExpression = this.baseExpression.twist(joinExpression, this);
                if (getDescriptor().getHistoryPolicy() != null) {
                    joinExpression = joinExpression.and(getDescriptor().getHistoryPolicy().additionalHistoryExpression(this, this, i));
                }
                tablesJoinExpressions.put(table, joinExpression);
            }
        }
        if (isUsingOuterJoinForMultitableInheritance()) {
            List<DatabaseTable> childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
            tablesSize = childrenTables.size();
            for (int i=0; i < tablesSize; i++) {
                DatabaseTable table = (DatabaseTable)childrenTables.get(i);
                Expression joinExpression = getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
                joinExpression = this.baseExpression.twist(joinExpression, this);
                tablesJoinExpressions.put(table, joinExpression);
            }
        }

        return tablesJoinExpressions;
    }

    /**
     * INTERNAL:
     * Find the alias for a given table
     */
    @Override
    public DatabaseTable aliasForTable(DatabaseTable table) {
        DatabaseMapping mapping = getMapping();
        if (isAttribute() || ((mapping != null) && (mapping.isAggregateObjectMapping() || mapping.isTransformationMapping()))) {
            return this.baseExpression.aliasForTable(table);
        }

        //"ref" and "structure" mappings, no table printed in the FROM clause, need to get the table alias form the parent table
        if ((mapping != null) && (mapping.isReferenceMapping() || mapping.isStructureMapping())) {
            DatabaseTable alias = this.baseExpression.aliasForTable(mapping.getDescriptor().getTables().firstElement());
            alias.setName(alias.getName() + "." + mapping.getField().getName());
            return alias;
        }

        // For direct-collection mappings the alias is store on the table expression.
        if ((mapping != null) && (mapping.isDirectCollectionMapping())) {
            if (tableAliases != null){
                DatabaseTable aliasedTable = tableAliases.keyAtValue(table);
                if (aliasedTable != null){
                    return aliasedTable;
                }
            }
            return getTable(table).aliasForTable(table);
        }

        return super.aliasForTable(table);
    }

    /**
     * ADVANCED:
     * Return an expression that allows you to treat its base as if it were a subclass of the class returned by the base
     * This can only be called on an ExpressionBuilder, the result of expression.get(String), expression.getAllowingNull(String),
     * the result of expression.anyOf("String") or the result of expression.anyOfAllowingNull("String")
     *
     * downcast uses Expression.type() internally to guarantee the results are of the specified class.
     * <p>Example:
     * <pre>
     *     EclipseLink: employee.get("project").treat(LargeProject.class).get("budget").equal(1000)
     *     Java: ((LargeProject)employee.getProjects().get(0)).getBudget() == 1000
     *     SQL: LPROJ.PROJ_ID (+)= PROJ.PROJ_ID AND L_PROJ.BUDGET = 1000 AND PROJ.TYPE = "L"
     * </pre>
     */
    @Override
    public Expression treat(Class castClass){
        //to be used in 'where treat(t as PerformanceTireInfo).speedRating > 100'
        QueryKeyExpression clonedExpression = new TreatAsExpression(castClass, this);
        clonedExpression.shouldQueryToManyRelationship = this.shouldQueryToManyRelationship;
        //using shouldUseOuterJoin to indicate the join to use between the t and PerformanceTireInfo subclass.
        clonedExpression.hasQueryKey = this.hasQueryKey;
        clonedExpression.hasMapping = this.hasMapping;

        this.addDerivedExpression(clonedExpression);
        return clonedExpression;
    }

    /**
     * INTERNAL:
     * Used for cloning.
     */
    @Override
    protected void postCopyIn(Map alreadyDone) {
        super.postCopyIn(alreadyDone);
        if (this.index != null) {
            this.index = (IndexExpression)this.index.copiedVersionFrom(alreadyDone);
        }
    }

    /**
     * INTERNAL:
     * Used for debug printing.
     */
    @Override
    public String descriptionOfNodeType() {
        return "Query Key";
    }

    /**
     * INTERNAL:
     */
    public void doQueryToManyRelationship() {
        shouldQueryToManyRelationship = true;
    }

    /**
     * INTERNAL:
     * Return any additional tables that belong to this expression
     * An example of how this method is used is to return any tables that belong to the map key
     * when this expression traverses a mapping that uses a Map
     */
    @Override
    public List<DatabaseTable> getAdditionalTables() {
        if (mapping != null && mapping.isCollectionMapping()){
            return mapping.getContainerPolicy().getAdditionalTablesForJoinQuery();
        }
        return null;
    }

    /**
     * INTERNAL:
     * Return the field appropriately aliased
     */
    @Override
    public DatabaseField getAliasedField() {
        if (aliasedField == null) {
            initializeAliasedField();
        }
        return aliasedField;

    }

    /**
     * Return the alias for our table
     */
    protected DatabaseTable getAliasedTable() {
        DataExpression base = (DataExpression)this.baseExpression;

        DatabaseTable alias = base.aliasForTable(getField().getTable());
        if (alias == null) {
            return getField().getTable();
        } else {
            return alias;
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public DatabaseField getField() {
        if (!isAttribute()) {
            return null;
        }
        QueryKey key = getQueryKeyOrNull();
        if ((key != null) && key.isDirectQueryKey()) {
            return ((DirectQueryKey)key).getField();
        }
        DatabaseMapping mapping = getMapping();
        if ((mapping == null) || mapping.getFields().isEmpty()) {
            return null;
        }
        return mapping.getFields().get(0);
    }

    /**
     * INTERNAL:
     * Return all the fields
     */
    @Override
    public Vector getFields() {
        if (isAttribute()) {
            Vector result = new Vector(1);
            DatabaseField field = getField();
            if (field != null) {
                result.addElement(field);
            }
            return result;
        } else {
            Vector result = new Vector();
            result.addAll(super.getFields());
            if ((this.mapping != null) && this.mapping.isCollectionMapping()){
                List<DatabaseField> fields = this.mapping.getContainerPolicy().getAdditionalFieldsForJoin((CollectionMapping)this.mapping);
                if (fields != null){
                    result.addAll(fields);
                }
            }
            return result;
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public List<DatabaseField> getSelectionFields(ReadQuery query) {
        if (isAttribute()) {
            List<DatabaseField> result = new ArrayList<>(1);
            DatabaseField field = getField();
            if (field != null) {
                result.add(field);
            }
            return result;
        } else {
            List<DatabaseField> result = new ArrayList<>();
            result.addAll(super.getSelectionFields(query));
            if ((this.mapping != null) && this.mapping.isCollectionMapping()){
                List<DatabaseField> fields = this.mapping.getContainerPolicy().getAdditionalFieldsForJoin((CollectionMapping)this.mapping);
                if (fields != null){
                    result.addAll(fields);
                }
            }
            return result;
        }
    }

    /**
     * INTERNAL:
     * Transform the object-level value into a database-level value
     */
    @Override
    public Object getFieldValue(Object objectValue, AbstractSession session) {
        DatabaseMapping mapping = getMapping();
        Object fieldValue = objectValue;
        if (mapping != null) {
            if (mapping.isAbstractDirectMapping() || mapping.isDirectCollectionMapping()) {
                // CR#3623207, check for IN Collection here not in mapping.
                if (objectValue instanceof Collection) {
                    // This can actually be a collection for IN within expressions... however it would be better for expressions to handle this.
                    Collection values = (Collection)objectValue;
                    Vector fieldValues = new Vector(values.size());
                    for (Iterator iterator = values.iterator(); iterator.hasNext();) {
                        Object value = iterator.next();
                        if (!(value instanceof Expression)){
                            value = getFieldValue(value, session);
                        }
                        fieldValues.add(value);
                    }
                    fieldValue = fieldValues;
                } else {
                    if (mapping.isAbstractColumnMapping()) {
                        fieldValue = ((AbstractColumnMapping)mapping).getFieldValue(objectValue, session);
                    } else if (mapping.isDirectCollectionMapping()) {
                        fieldValue = ((DirectCollectionMapping)mapping).getFieldValue(objectValue, session);
                    }
                }
            } else if ((objectValue instanceof Collection) && (mapping.isForeignReferenceMapping())) {
                // Was an IN with a collection of objects, extract their ids.
                List ids = new ArrayList();
                for (Object object : ((Collection)objectValue)) {
                    if ((mapping.getReferenceDescriptor() != null) && (mapping.getReferenceDescriptor().getJavaClass().isInstance(object))) {
                        Object id = mapping.getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(object, session);
                        if (id instanceof CacheId) {
                            id = Arrays.asList(((CacheId)id).getPrimaryKey());
                        }
                        ids.add(id);
                    } else {
                        ids.add(object);
                    }
                }
                fieldValue = ids;
            }
        }

        return fieldValue;
    }

    @Override
    public DatabaseMapping getMapping() {
        if (!hasMapping) {
            return null;
        }

        if (mapping == null) {
            mapping = super.getMapping();
            if (mapping == null) {
                hasMapping = false;
            }
        }
        return mapping;
    }

    public DatabaseMapping getMappingFromQueryKey() {
        QueryKey queryKey = getQueryKeyOrNull();
        if ((queryKey == null) || (!(queryKey instanceof DirectQueryKey))) {
            throw QueryException.cannotConformExpression();
        }
        mapping = queryKey.getDescriptor().getObjectBuilder().getMappingForField(((DirectQueryKey)queryKey).getField());
        if (mapping == null) {
            throw QueryException.cannotConformExpression();
        }
        return mapping;
    }

    @Override
    public String getName() {
        return name;
    }

    /**
     * INTERNAL:
     * Returns nested attribute name or null
     */
    public String getNestedAttributeName() {
        if(getMapping() != null) {
            String attributeName = getMapping().getAttributeName();
            if(this.baseExpression.isExpressionBuilder()) {
                return attributeName;
            } else if (this.baseExpression.isQueryKeyExpression()) {
                String nestedAttributeName = ((QueryKeyExpression)this.baseExpression).getNestedAttributeName();
                if(nestedAttributeName == null) {
                    return null;
                } else {
                    return nestedAttributeName + '.' + attributeName;
                }
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public List<DatabaseTable> getOwnedTables() {
        if ((getMapping() != null) && getMapping().isNestedTableMapping()) {
            List<DatabaseTable> nestedTable = null;
            if (shouldQueryToManyRelationship()) {
                nestedTable = new ArrayList(super.getOwnedTables());
            } else {
                nestedTable = new ArrayList(1);
            }

            nestedTable.add(new NestedTable(this));
            return nestedTable;
        }
        if ((getMapping() != null) && (getMapping().isReferenceMapping() || getMapping().isStructureMapping())) {
            return null;
        }

        return super.getOwnedTables();

    }

    @Override
    public QueryKey getQueryKeyOrNull() {
        if (!hasQueryKey) {
            return null;
        }

        // Oct 19, 2000 JED
        // Added try/catch. This was throwing a NPE in the following case
        // expresssionBuilder.get("firstName").get("bob")
        //moved by Gordon Yorke to cover validate and normalize
        if (getContainingDescriptor() == null) {
            throw QueryException.invalidQueryKeyInExpression(getName());
        }
        if (queryKey == null) {
            queryKey = getContainingDescriptor().getQueryKeyNamed(getName());
            if (queryKey == null) {
                hasQueryKey = false;
            }
        }
        return queryKey;

    }

    /*
     * PUBLIC:
     * Index method could be applied to QueryKeyExpression corresponding to CollectionMapping
     * that has non-null listOrderField (the field holding the index values).
     * <p>Example:
     * <pre><blockquote>
     *    ReportQuery query = new ReportQuery();
     *    query.setReferenceClass(Employee.class);
     *    ExpressionBuilder builder = query.getExpressionBuilder();
     *    Expression firstNameJohn = builder.get("firstName").equal("John");
     *    Expression anyOfProjects = builder.anyOf("projects");
     *    Expression exp = firstNameJohn.and(anyOfProjects.index().between(2, 4));
     *    query.setSelectionCriteria(exp);
     *    query.addAttribute("projects", anyOfProjects);
     *
     *    SELECT DISTINCT t0.PROJ_ID, t0.PROJ_TYPE, t0.DESCRIP, t0.PROJ_NAME, t0.LEADER_ID, t0.VERSION, t1.PROJ_ID, t1.BUDGET, t1.MILESTONE
     *    FROM OL_PROJ_EMP t4, OL_SALARY t3, OL_EMPLOYEE t2, OL_LPROJECT t1, OL_PROJECT t0
     *    WHERE ((((t2.F_NAME = 'John') AND (t4.PROJ_ORDER BETWEEN 2 AND 4)) AND (t3.OWNER_EMP_ID = t2.EMP_ID)) AND
     *    (((t4.EMP_ID = t2.EMP_ID) AND (t0.PROJ_ID = t4.PROJ_ID)) AND (t1.PROJ_ID (+) = t0.PROJ_ID)))
     * </blockquote></pre>
     */
    @Override
    public Expression index() {
        if(index == null) {
            index = new IndexExpression(this);
        }
        return index;
    }

    /**
     * INTERNAL:
     * Alias the database field for our current environment
     */
    protected void initializeAliasedField() {
        DatabaseField tempField = getField().clone();
        DatabaseTable aliasedTable = getAliasedTable();

        //  Put in a special check here so that if the aliasing does nothing we don't cache the
        // result because it's invalid. This saves us from caching premature data if e.g. debugging
        // causes us to print too early"
        //    if (aliasedTable.equals(getField().getTable())) {
        //        return;
        //    } else {
        aliasedField = tempField;
        aliasedField.setTable(aliasedTable);
        //    }
    }

    /**
     * INTERNAL:
     * Return if the expression is for a direct mapped attribute.
     */
    @Override
    public boolean isAttribute() {
        if (isAttributeExpression == null) {
            if (getSession() == null) {
                // We can't tell, so say no.
                return false;
            }
            QueryKey queryKey = getQueryKeyOrNull();
            if (queryKey != null) {
                isAttributeExpression = queryKey.isDirectQueryKey();
            } else {
                DatabaseMapping mapping = getMapping();
                if (mapping != null) {
                    if (mapping.isVariableOneToOneMapping()) {
                        throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(mapping, mapping.getDescriptor());
                    } else {
                        isAttributeExpression = mapping.isDirectToFieldMapping();
                    }
                } else {
                    isAttributeExpression = Boolean.FALSE;
                }
            }
        }
        return isAttributeExpression;
    }

    @Override
    public boolean isQueryKeyExpression() {
        return true;
    }

    /*
     * INTERNAL:
     * If this query key represents a foreign reference answer the
     * base expression -> foreign reference join criteria.
     */
    public Expression mappingCriteria(Expression base) {
        Expression selectionCriteria;

        // First look for a query key, then a mapping
        if (getQueryKeyOrNull() == null) {
            if ((getMapping() == null) || (!getMapping().isForeignReferenceMapping())) {
                return null;
            } else {
                // The join criteria is now twisted by the mappings.
                selectionCriteria = ((ForeignReferenceMapping)getMapping()).getJoinCriteria(this, base);
            }
        } else {
            if (!getQueryKeyOrNull().isForeignReferenceQueryKey()) {
                return null;
            } else {
                selectionCriteria = ((ForeignReferenceQueryKey)getQueryKeyOrNull()).getJoinCriteria();
                selectionCriteria = this.baseExpression.twist(selectionCriteria, base);
            }
        }

        if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
            selectionCriteria = selectionCriteria.convertToUseOuterJoin();
        }

        return selectionCriteria;
    }

    /**
     * INTERNAL:
     * Normalize the expression into a printable structure.
     * Any joins must be added to form a new root.
     */
    @Override
    public Expression normalize(ExpressionNormalizer normalizer) {
        return normalize(normalizer, this, null);
    }

    /**
     * INTERNAL:
     * Check if new expression need to be created for sub queries and re-normalized.
     */
    protected Expression checkJoinForSubSelectWithParent(ExpressionNormalizer normalizer, Expression base, List<Expression> foreignKeyJoinPointer) {
        SQLSelectStatement statement = normalizer.getStatement();
        if(!isClonedForSubQuery && statement.isSubSelect() && statement.getParentStatement().getBuilder().equals(getBuilder())) {
            if (baseExpression.isQueryKeyExpression()) {
                QueryKeyExpression baseQueryKeyExpression = (QueryKeyExpression) baseExpression;
                DatabaseMapping mapping = baseQueryKeyExpression.getMapping();
                if (mapping != null && mapping.isOneToOneMapping()) {
                    if (statement.getOptimizedClonedExpressions().containsKey(this)) {
                        return statement.getOptimizedClonedExpressions().get(this);
                    }

                    QueryKeyExpression clonedBaseExpression = null;
                    if (baseQueryKeyExpression.hasBeenNormalized()) {
                        // Call normalize again to get same expression.
                        clonedBaseExpression = (QueryKeyExpression) baseQueryKeyExpression.normalize(normalizer);
                    }

                    if (clonedBaseExpression == null && baseQueryKeyExpression.getBaseExpression().isQueryKeyExpression()) {
                        DatabaseMapping basebaseExprMapping = ((QueryKeyExpression)baseQueryKeyExpression.getBaseExpression()).getMapping();
                        if (basebaseExprMapping != null && basebaseExprMapping.isOneToOneMapping()) {
                            // Let base expression normalization re-create base base expression and normalize it if needed.
                            clonedBaseExpression = (QueryKeyExpression) baseQueryKeyExpression.normalize(normalizer);
                        }
                    }

                    if (clonedBaseExpression == null) {
                        // Clone base expression & normalize
                        clonedBaseExpression = new QueryKeyExpression(baseQueryKeyExpression.getName(), baseQueryKeyExpression.getBaseExpression());
                        clonedBaseExpression.shouldQueryToManyRelationship = baseQueryKeyExpression.shouldQueryToManyRelationship;
                        clonedBaseExpression.shouldUseOuterJoin = baseQueryKeyExpression.shouldUseOuterJoin;
                        clonedBaseExpression.hasQueryKey = baseQueryKeyExpression.hasQueryKey;
                        clonedBaseExpression.hasMapping = baseQueryKeyExpression.hasMapping;
                        clonedBaseExpression.isAttributeExpression = baseQueryKeyExpression.isAttributeExpression;
                        clonedBaseExpression.isClonedForSubQuery = true;

                        clonedBaseExpression = (QueryKeyExpression) clonedBaseExpression.normalize(normalizer);
                        statement.addOptimizedClonedExpressions(baseQueryKeyExpression, clonedBaseExpression);
                    }

                    // Clone expression, normalize & return.
                    QueryKeyExpression clonedExpression = new QueryKeyExpression(name, clonedBaseExpression);
                    clonedExpression.shouldQueryToManyRelationship = this.shouldQueryToManyRelationship;
                    clonedExpression.shouldUseOuterJoin = this.shouldUseOuterJoin;
                    clonedExpression.hasQueryKey = this.hasQueryKey;
                    clonedExpression.hasMapping = this.hasMapping;
                    clonedExpression.isAttributeExpression = this.isAttributeExpression;
                    clonedExpression.isClonedForSubQuery = true;

                    if (base == this) {
                        clonedExpression = (QueryKeyExpression) clonedExpression.normalize(normalizer, clonedExpression, foreignKeyJoinPointer);
                    } else {
                        // Caller invoked overloaded method with different base, RelationExpression in this case.
                        clonedExpression = (QueryKeyExpression) clonedExpression.normalize(normalizer, base, foreignKeyJoinPointer);
                    }
                    statement.addOptimizedClonedExpressions(this, clonedExpression);
                    return clonedExpression;
                }
            }
        }

        return null;
    }

    /**
     * INTERNAL:
     * For CR#2456 if this is part of an objExp.equal(objExp), do not need to add
     * additional expressions to normalizer both times, and the foreign key join
     * replaces the equal expression.
     */
    public Expression normalize(ExpressionNormalizer normalizer, Expression base, List<Expression> foreignKeyJoinPointer) {
        if (this.hasBeenNormalized) {
            return this;
        }
        // Bug 397619 - It should only be normalized by parent.
        // If subselect & not normalized, always clone and normalize
        // if it has parent builder.
        Expression clonedExpression = checkJoinForSubSelectWithParent(normalizer, base, foreignKeyJoinPointer);
        if (clonedExpression != null) {
            return clonedExpression;
        }
        super.normalize(normalizer);
        DatabaseMapping mapping = getMapping();
        SQLSelectStatement statement = normalizer.getStatement();
        if ((mapping != null) && mapping.isDirectToXMLTypeMapping()) {
            statement.setRequiresAliases(true);
        }

        // Check if any joins need to be added.
        if (isAttribute()) {
            return this;
        }

        ReadQuery query = normalizer.getStatement().getQuery();
        // Record any class used in a join to invalidate query results cache.
        if ((query != null) && query.shouldCacheQueryResults()) {
            if ((mapping != null) && (mapping.getReferenceDescriptor() != null) && (mapping.getReferenceDescriptor().getJavaClass() != null)) {
                query.getQueryResultsCachePolicy().getInvalidationClasses().add(mapping.getReferenceDescriptor().getJavaClass());
            } else {
                QueryKey queryKey = getQueryKeyOrNull();
                if ((queryKey != null) && queryKey.isForeignReferenceQueryKey()) {
                    query.getQueryResultsCachePolicy().getInvalidationClasses().add(((ForeignReferenceQueryKey)queryKey).getReferenceClass());
                }
            }
        }

        // If the mapping is 'ref' or 'structure', no join needed.
        if ((mapping != null) && (mapping.isReferenceMapping() || mapping.isStructureMapping())) {
            statement.setRequiresAliases(true);
            return this;
        }

        // Compute if a distinct is required during normalization.
        if (shouldQueryToManyRelationship() && (!statement.isDistinctComputed()) && (!statement.isAggregateSelect())) {
            statement.useDistinct();
        }

        // Turn off DISTINCT if nestedTableMapping is used (not supported by Oracle 8.1.5).
        if ((mapping != null) && mapping.isNestedTableMapping()) {
            // There are two types of nested tables, one used by clients, one used by mappings, do nothing in the mapping case.
            if (!shouldQueryToManyRelationship()) {
                return this;
            }
            statement.dontUseDistinct();
        }

        // Normalize the ON clause if present.  Need to use rebuild, not twist as parameters are real parameters.
        if (this.onClause != null) {
            this.onClause = this.onClause.normalize(normalizer);
        }

        Expression mappingExpression = mappingCriteria(base);
        if (mappingExpression != null) {
            mappingExpression = mappingExpression.normalize(normalizer);
        }
        if (mappingExpression != null) {
            // If the join was an outer join we must not add the join criteria to the where clause,
            // if the platform prints the join in the from clause.
            if (shouldUseOuterJoin() && (getSession().getPlatform().isInformixOuterJoin())) {
                setOuterJoinExpIndex(statement.addOuterJoinExpressionsHolders(this, mappingExpression, null, null));
                normalizer.addAdditionalExpression(mappingExpression.and(additionalExpressionCriteria()));
                return this;
            } else if ((shouldUseOuterJoin() && (!getSession().getPlatform().shouldPrintOuterJoinInWhereClause()))
                    || (!getSession().getPlatform().shouldPrintInnerJoinInWhereClause())) {
                setOuterJoinExpIndex(statement.addOuterJoinExpressionsHolders(this, mappingExpression, additionalExpressionCriteriaMap(), null));
                if ((getDescriptor() != null) && (getDescriptor().getHistoryPolicy() != null)) {
                    Expression historyOnClause = getDescriptor().getHistoryPolicy().additionalHistoryExpression(this, this, 0);
                    if (getOnClause() != null) {
                        setOnClause(getOnClause().and(historyOnClause));
                    } else {
                        setOnClause(historyOnClause);
                    }
                }
                return this;
            } else if (isUsingOuterJoinForMultitableInheritance() && (!getSession().getPlatform().shouldPrintOuterJoinInWhereClause())) {
                setOuterJoinExpIndex(statement.addOuterJoinExpressionsHolders(null, null, additionalExpressionCriteriaMap(), mapping.getReferenceDescriptor()));
                // fall through to the main case
            }

            // This must be added even if outer. Actually it should be converted to use a right outer join, but that gets complex
            // so we do not support this current which is a limitation in some cases.
            if (foreignKeyJoinPointer != null) {
                // If this expression is right side of an objExp.equal(objExp), one
                // need not add additionalExpressionCriteria twice.
                // Also the join will replace the original objExp.equal(objExp).
                // For CR#2456.
                foreignKeyJoinPointer.add(mappingExpression.and(this.onClause));
            } else {
                normalizer.addAdditionalExpression(mappingExpression.and(additionalExpressionCriteria()).and(this.onClause));
            }
        }
        // For bug 2900974 special code for DirectCollectionMappings moved to printSQL.
        return this;
    }

    /**
     * INTERNAL:
     * Print SQL onto the stream, using the ExpressionPrinter for context
     */
    @Override
    public void printSQL(ExpressionSQLPrinter printer) {
        if (isAttribute()) {
            printer.printField(getAliasedField());
        }

        // If the mapping is a direct collection then this falls into a gray area.
        // It must be treated as an attribute at this moment for it has a direct field.
        // However it is not an attribute in the sense that it also represents a foreign
        // reference and a mapping criteria has been added.
        // For bug 2900974 these are now handled as non-attributes during normalize but
        // as attributes when printing SQL.
        //
        if ((!isAttribute()) && (getMapping() != null) && getMapping().isDirectCollectionMapping()) {
            DirectCollectionMapping directCollectionMapping = (DirectCollectionMapping)getMapping();

            // The aliased table comes for free as it was a required part of the join criteria.
            TableExpression table = (TableExpression)getTable(directCollectionMapping.getReferenceTable());
            DatabaseTable aliasedTable = table.aliasForTable(table.getTable());
            DatabaseField aliasedField = directCollectionMapping.getDirectField().clone();
            aliasedField.setTable(aliasedTable);
            printer.printField(aliasedField);
        }

        if ((getMapping() != null) && getMapping().isNestedTableMapping()) {
            DatabaseTable tableAlias = aliasForTable(new NestedTable(this));
            printer.printString(tableAlias.getName());
        }
    }

    /**
     * INTERNAL:
     * Print java for project class generation
     */
    @Override
    public void printJava(ExpressionJavaPrinter printer) {
        this.baseExpression.printJava(printer);
        if (!shouldUseOuterJoin()) {
            if (!shouldQueryToManyRelationship()) {
                printer.printString(".get(");
            } else {
                printer.printString(".anyOf(");
            }
        } else {
            if (!shouldQueryToManyRelationship()) {
                printer.printString(".getAllowingNull(");
            } else {
                printer.printString(".anyOfAllowingNone(");
            }
        }
        printer.printString("\"" + getName() + "\")");
    }

    /**
     * INTERNAL:
     * This expression is built on a different base than the one we want. Rebuild it and
     * return the root of the new tree
     */
    @Override
    public Expression rebuildOn(Expression newBase) {
        Expression newLocalBase = this.baseExpression.rebuildOn(newBase);
        QueryKeyExpression result = null;

        // For bug 3096634 rebuild outer joins correctly from the start.
        if (shouldUseOuterJoin) {
            result = (QueryKeyExpression)newLocalBase.getAllowingNull(getName());
        } else {
            result = (QueryKeyExpression)newLocalBase.get(getName());
        }
        if (shouldQueryToManyRelationship) {
            result.doQueryToManyRelationship();
        }
        result.setSelectIfOrderedBy(selectIfOrderedBy());
        if (castClass != null){
            result.setCastClass(castClass);
        }
        return result;
    }

    /**
     * INTERNAL:
     * A special version of rebuildOn where the newBase need not be a new
     * ExpressionBuilder but any expression.
     * <p>
     * For nested joined attributes, the joined attribute query must have
     * its joined attributes rebuilt relative to it.
     */
    public Expression rebuildOn(Expression oldBase, Expression newBase) {
        if (this == oldBase) {
            return newBase;
        }
        Expression newLocalBase = ((QueryKeyExpression)this.baseExpression).rebuildOn(oldBase, newBase);
        QueryKeyExpression result = null;

        // For bug 3096634 rebuild outer joins correctly from the start.
        if (shouldUseOuterJoin) {
            result = (QueryKeyExpression)newLocalBase.getAllowingNull(getName());
        } else {
            result = (QueryKeyExpression)newLocalBase.get(getName());
        }
        if (shouldQueryToManyRelationship) {
            result.doQueryToManyRelationship();
        }
        result.setSelectIfOrderedBy(selectIfOrderedBy());
        return result;
    }

    /**
     * Reset cached information here so that we can be sure we're accurate.
     */
    @Override
    protected void resetCache() {
        hasMapping = true;
        mapping = null;
        hasQueryKey = true;
        queryKey = null;
    }

    public boolean shouldQueryToManyRelationship() {
        return shouldQueryToManyRelationship;
    }

    /**
     * INTERNAL:
     * Rebuild myself against the base, with the values of parameters supplied by the context
     * expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping)
     * into part of some larger expression. You normally would not call this directly, instead calling twist
     * See the comment there for more details"
     */
    @Override
    public Expression twistedForBaseAndContext(Expression newBase, Expression context, Expression oldBase) {
        if (oldBase == null || this.baseExpression == oldBase) {
            Expression twistedBase = this.baseExpression.twistedForBaseAndContext(newBase, context, oldBase);
            QueryKeyExpression result = (QueryKeyExpression)twistedBase.get(getName());
            if (shouldUseOuterJoin) {
                result.doUseOuterJoin();
            }
            if (shouldQueryToManyRelationship) {
                result.doQueryToManyRelationship();
            }
            return result;
        }

        return this;
    }

    /**
     * Do any required validation for this node. Throw an exception if it's incorrect.
     */
    @Override
    public void validateNode() {
        QueryKey queryKey = getQueryKeyOrNull();
        DatabaseMapping mapping = getMapping();

        if ((queryKey == null) && (mapping == null)) {
            throw QueryException.invalidQueryKeyInExpression(getName());
        }


        Object theOneThatsNotNull = null;
        boolean qkIsToMany = false;
        if (queryKey != null) {
            theOneThatsNotNull = queryKey;
            qkIsToMany = queryKey.isManyToManyQueryKey() || queryKey.isOneToManyQueryKey();
        }
        boolean isNestedMapping = false;
        if (mapping != null) {
            // Bug 2847621 - Add Aggregate Collection to the list of valid items for outer join.
            if (this.shouldUseOuterJoin && (!(mapping.isOneToOneMapping() || mapping.isOneToManyMapping() || mapping.isManyToManyMapping() || mapping.isAggregateCollectionMapping() || mapping.isDirectCollectionMapping()))) {
                throw QueryException.outerJoinIsOnlyValidForOneToOneMappings(mapping);
            }
            qkIsToMany = mapping.isCollectionMapping();
            if (this.index != null) {
                if (qkIsToMany) {
                    CollectionMapping collectionMapping = (CollectionMapping)mapping;
                    if(collectionMapping.getListOrderField() != null) {
                        this.index.setField(collectionMapping.getListOrderField());
                        addDerivedField(this.index);
                    } else {
                        throw QueryException.indexRequiresCollectionMappingWithListOrderField(this, collectionMapping);
                    }
                } else {
                    throw QueryException.indexRequiresCollectionMappingWithListOrderField(this, mapping);
                }
            }
            isNestedMapping = mapping.isNestedTableMapping();
            theOneThatsNotNull = mapping;
        } else {
            if (this.index != null) {
                throw QueryException.indexRequiresCollectionMappingWithListOrderField(this, null);
            }
        }
        if ((!shouldQueryToManyRelationship()) && qkIsToMany && (!isNestedMapping)) {
            throw QueryException.invalidUseOfToManyQueryKeyInExpression(theOneThatsNotNull);
        }
        if (shouldQueryToManyRelationship() && !qkIsToMany) {
            throw QueryException.invalidUseOfAnyOfInExpression(theOneThatsNotNull);
        }
    }

    /**
     * INTERNAL:
     * Return the value for in memory comparison.
     * This is only valid for valueable expressions.
     */
    @Override
    public Object valueFromObject(Object object, AbstractSession session, AbstractRecord translationRow, int valueHolderPolicy, boolean isObjectUnregistered) {
        // The expression may be across a relationship, in which case it must be traversed.
        if ((!this.baseExpression.isExpressionBuilder()) && this.baseExpression.isQueryKeyExpression()) {
            object = this.baseExpression.valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);

            // toDo: Null means the join filters out the row, returning null is not correct if an inner join,
            // outer/inner joins need to be fixed to filter correctly.
            if (object == null) {
                return null;
            }

            // If from an anyof the object will be a collection of values,
            // A new vector must union the object values and the values extracted from it.
            if (object instanceof Vector) {
                Vector comparisonVector = new Vector(((Vector)object).size() + 2);
                for (Enumeration valuesToIterate = ((Vector)object).elements();
                         valuesToIterate.hasMoreElements();) {
                    Object vectorObject = valuesToIterate.nextElement();
                    if (vectorObject == null) {
                        comparisonVector.addElement(null);
                    } else {
                        Object valueOrValues = valuesFromCollection(vectorObject, session, valueHolderPolicy, isObjectUnregistered);

                        // If a collection of values were extracted union them.
                        if (valueOrValues instanceof Vector) {
                            for (Enumeration nestedValuesToIterate = ((Vector)valueOrValues).elements();
                                     nestedValuesToIterate.hasMoreElements();) {
                                comparisonVector.addElement(nestedValuesToIterate.nextElement());
                            }
                        } else {
                            comparisonVector.addElement(valueOrValues);
                        }
                    }
                }
                return comparisonVector;
            }
        }
        return valuesFromCollection(object, session, valueHolderPolicy, isObjectUnregistered);
    }

    /**
     * INTERNAL
     * This method iterates through a collection and gets the values from the objects to conform in an in-memory query.
     */
    public Object valuesFromCollection(Object object, AbstractSession session, int valueHolderPolicy, boolean isObjectUnregistered) {
        // in case the mapping is null - this can happen if a query key is being used
        // In this case, check for the query key and find it's mapping.
        boolean readMappingFromQueryKey = false;
        if (getMapping() == null) {
            getMappingFromQueryKey();
            readMappingFromQueryKey = true;
        }

        // For bug 2780817 get the mapping directly from the object.  In EJB 2.0
        // inheritance, each child must override mappings defined in an abstract
        // class with its own.
        DatabaseMapping mapping = this.mapping;
        ClassDescriptor descriptor = mapping.getDescriptor();
        if (descriptor.hasInheritance() && (descriptor.getJavaClass() != object.getClass())) {
            descriptor = descriptor.getInheritancePolicy().getDescriptor(object.getClass());
            mapping = descriptor.getObjectBuilder().getMappingForAttributeName(mapping.getAttributeName());
        }

        //fetch group support
        if (descriptor.hasFetchGroupManager()) {
            FetchGroupManager fetchGroupManager = descriptor.getFetchGroupManager();
            if (fetchGroupManager.isPartialObject(object) && (!fetchGroupManager.isAttributeFetched(object, mapping.getAttributeName()))) {
                //the conforming attribute is not fetched, simply throw exception
                throw QueryException.cannotConformUnfetchedAttribute(mapping.getAttributeName());
            }
        }

        if (mapping.isAbstractColumnMapping()) {
            return mapping.valueFromObject(object, mapping.getField(), session);
        } else if (mapping.isForeignReferenceMapping()) {
            //CR 3677 integration of a ValueHolderPolicy
            Object valueFromMapping = mapping.getAttributeValueFromObject(object);
            if (!((ForeignReferenceMapping)mapping).getIndirectionPolicy().objectIsInstantiated(valueFromMapping)) {
                if (valueHolderPolicy  != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION) {
                    //If the client wishes us to trigger the indirection then we should do so,
                    //Other wise throw the exception
                    throw QueryException.mustInstantiateValueholders();// you should instantiate the valueholder for this to work
                }

                // maybe we should throw this exception from the start, to save time
            }
            Object valueToIterate = mapping.getRealAttributeValueFromObject(object, session);
            UnitOfWorkImpl uow = isObjectUnregistered ? (UnitOfWorkImpl)session : null;

            // First check that object in fact is unregistered.
            // toDo: ?? Why is this commented out? Why are we supporting the unregistered thing at all?
            // Does not seem to be any public API for this, nor every used internally?
            //if (isObjectUnregistered) {
            //    isObjectUnregistered = !uow.getCloneMapping().containsKey(object);
            //}
            if (mapping.isCollectionMapping() && (valueToIterate != null)) {
                // For bug 2766379 must use the correct version of vectorFor to
                // unwrap the result same time.
                valueToIterate = mapping.getContainerPolicy().vectorFor(valueToIterate, session);

                // toDo: If the value is empty, need to support correct inner/outer join filtering symantics.
                // For CR 2612601, try to partially replace the result with already
                // registered objects.
                if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) {
                    Vector objectValues = (Vector)valueToIterate;
                    for (int i = 0; i < objectValues.size(); i++) {
                        Object original = objectValues.elementAt(i);
                        Object clone = uow.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(original);
                        if (clone != null) {
                            objectValues.setElementAt(clone, i);
                        }
                    }
                }

                // For CR 2612601, conforming without registering, a query could be
                // bob.get("address").get("city").equal("Ottawa"); where the address
                // has been registered and modified in the UOW, but bob has not.  Thus
                // even though bob does not point to the modified address now, it will
                // as soon as it is registered, so should point to it here.
            } else if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) {
                Object clone = uow.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(valueToIterate);
                if (clone != null) {
                    valueToIterate = clone;
                }
            }
            return valueToIterate;
        } else if (mapping.isAggregateMapping()) {
            Object aggregateValue = mapping.getAttributeValueFromObject(object);
            // Bug 3995468 - if this query key is to a mapping in an aggregate object, get the object from actual mapping rather than the aggregate mapping
            while (readMappingFromQueryKey && mapping.isAggregateObjectMapping() && !((AggregateObjectMapping)mapping).getReferenceClass().equals(queryKey.getDescriptor().getJavaClass())) {
                mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(((DirectQueryKey)queryKey).getField());
                aggregateValue = mapping.getRealAttributeValueFromObject(aggregateValue, session);
            }
            return aggregateValue;
        } else {
            throw QueryException.cannotConformExpression();
        }
    }

    /**
     * INTERNAL:
     * Lookup the descriptor for this item by traversing its expression recursively.
     */
    @Override
    public ClassDescriptor getLeafDescriptor(DatabaseQuery query, ClassDescriptor rootDescriptor, AbstractSession session) {
        Expression baseExpression = getBaseExpression();
        ClassDescriptor baseDescriptor = baseExpression.getLeafDescriptor(query, rootDescriptor, session);

        if (isMapEntryExpression()) {
            // get the expression that owns the mapping for the table entry
            Expression owningExpression = ((QueryKeyExpression)baseExpression).getBaseExpression();
            ClassDescriptor owningDescriptor = owningExpression.getLeafDescriptor(query, rootDescriptor, session);

            // Get the mapping that owns the table
            CollectionMapping mapping = (CollectionMapping)owningDescriptor.getObjectBuilder().getMappingForAttributeName(baseExpression.getName());

            return mapping.getContainerPolicy().getDescriptorForMapKey();
        }

        ClassDescriptor descriptor = null;
        String attributeName = getName();

        DatabaseMapping mapping = baseDescriptor.getObjectBuilder().getMappingForAttributeName(attributeName);

        if (mapping == null) {
            QueryKey queryKey = baseDescriptor.getQueryKeyNamed(attributeName);
            if (queryKey != null) {
                if (queryKey.isForeignReferenceQueryKey()) {
                    descriptor = session.getDescriptor(((ForeignReferenceQueryKey)queryKey).getReferenceClass());
                } else { // if (queryKey.isDirectQueryKey())
                    descriptor = queryKey.getDescriptor();
                }
            }
            if (descriptor == null) {
                throw QueryException.invalidExpressionForQueryItem(this, query);
            }
        } else if (mapping.isAggregateMapping()) {
            descriptor = mapping.getReferenceDescriptor();
        } else if (mapping.isForeignReferenceMapping()) {
            descriptor = mapping.getReferenceDescriptor();
        }
        return descriptor;
    }

    /**
     * INTERNAL:
     * Lookup the mapping for this item by traversing its expression recursively.
     * If an aggregate of foreign mapping is found it is traversed.
     */
    @Override
    public DatabaseMapping getLeafMapping(DatabaseQuery query, ClassDescriptor rootDescriptor, AbstractSession session) {
        if (isMapEntryExpression()){
            MapEntryExpression mapEntryExpression = (MapEntryExpression)this;

            // get the expression that we want the table entry for
            QueryKeyExpression baseExpression = (QueryKeyExpression)mapEntryExpression.getBaseExpression();

            // get the expression that owns the mapping for the table entry
            Expression owningExpression = baseExpression.getBaseExpression();
            ClassDescriptor owningDescriptor = owningExpression.getLeafDescriptor(query, rootDescriptor, session);

            // Get the mapping that owns the table
            CollectionMapping mapping = (CollectionMapping)owningDescriptor.getObjectBuilder().getMappingForAttributeName(baseExpression.getName());

            if (mapEntryExpression.shouldReturnMapEntry()) {
                return mapping;
            }
            if (mapping.getContainerPolicy().isMappedKeyMapPolicy()){
                MappedKeyMapContainerPolicy policy = (MappedKeyMapContainerPolicy)mapping.getContainerPolicy();
                return (DatabaseMapping)policy.getKeyMapping();
            }
            return mapping;
        }

        Expression baseExpression = getBaseExpression();

        ClassDescriptor descriptor = baseExpression.getLeafDescriptor(query, rootDescriptor, session);
        if (descriptor == null){
            return null;
        }
        return descriptor.getObjectBuilder().getMappingForAttributeName(getName());
    }

    /**
     * INTERNAL:
     * Used to print a debug form of the expression tree.
     */
    @Override
    public void writeDescriptionOn(BufferedWriter writer) throws IOException {
        writer.write(getName());
        if (castClass != null){
            writer.write(" (" + castClass.getName() + ") ");
        }
        writer.write(tableAliasesDescription());
    }

    /**
     * INTERNAL:
     * Indicates whether this expression corresponds to DirectCollection.
     */
    @Override
    public boolean isDirectCollection() {
        if(getMapping() != null) {
            return getMapping().isDirectCollectionMapping();
        } else {
            if(getQueryKeyOrNull() != null) {
                return this.queryKey.isDirectCollectionQueryKey();
            } else {
                return false;
            }
        }
    }

    /**
     * INTERNAL:
     * Indicates whether this expression corresponds to OneToOne.
     */
    public boolean isOneToOne() {
        if(getMapping() != null) {
            return getMapping().isOneToOneMapping();
        } else {
            if(getQueryKeyOrNull() != null) {
                return this.queryKey.isOneToOneQueryKey();
            } else {
                return false;
            }
        }
    }

    /**
     * INTERNAL:
     * Indicates whether this expression corresponds to OneToMany.
     */
    public boolean isOneToMany() {
        if(getMapping() != null) {
            return getMapping().isOneToManyMapping();
        } else {
            if(getQueryKeyOrNull() != null) {
                return this.queryKey.isOneToManyQueryKey();
            } else {
                return false;
            }
        }
    }

    /**
     * INTERNAL:
     * Indicates whether this expression corresponds to ManyToMany.
     */
    public boolean isManyToMany() {
        if(getMapping() != null) {
            return getMapping().isManyToManyMapping();
        } else {
            if(getQueryKeyOrNull() != null) {
                return this.queryKey.isManyToManyQueryKey();
            } else {
                return false;
            }
        }
    }

    /**
     * INTERNAL:
     * Return if the expression if for a map key mapping where the key is a OneToOne.
     */
    public boolean isMapKeyObjectRelationship() {
        if (getMapping() != null) {
            return getMapping().isCollectionMapping() && ((CollectionMapping)getMapping()).isMapKeyObjectRelationship();
        } else {
            return false;
        }
    }

    /**
     * INTERNAL:
     * Return if descriptor for the map key mapping where the key is a OneToOne.
     */
    public ClassDescriptor getMapKeyDescriptor() {
        return getMapping().getContainerPolicy().getDescriptorForMapKey();
    }

    /**
     * Calculate the reference table for based on the various QueryKeyExpression
     * usages (join query keys, custom defined query keys, or query keys for
     * mappings).
     *
     * Called from {@link SQLSelectStatement#appendFromClauseForOuterJoin}.
     *
     * @return DatabaseTable
     */
    public DatabaseTable getReferenceTable() {
        if(getMapping() != null) {
            if (getMapping().isDirectCollectionMapping()) {
                return ((DirectCollectionMapping)getMapping()).getReferenceTable();
            } else {
                return getMapping().getReferenceDescriptor().getTables().firstElement();
            }
        } else {
            return ((ForeignReferenceQueryKey)getQueryKeyOrNull()).getReferenceTable(getDescriptor());
        }
    }

    /**
     * Calculate the source table for based on the various QueryKeyExpression
     * usages (join query keys, custom defined query keys, or query keys for
     * mappings).
     *
     * Called from {@link SQLSelectStatement#appendFromClauseForOuterJoin}.
     *
     * @return DatabaseTable
     */
    public DatabaseTable getSourceTable() {
        if (getBaseExpression().isExpressionBuilder() && getBuilder().hasViewTable()) {
            return getBuilder().getViewTable();
        }
        if (getMapping() != null) {
            // Grab the source table from the mapping not just the first table
            // from the descriptor. In an joined inheritance hierarchy, the
            // fk used in the outer join may be from a subclasses's table.
            if (getMapping().isObjectReferenceMapping() && ((ObjectReferenceMapping) getMapping()).isForeignKeyRelationship()) {
                 return getMapping().getFields().firstElement().getTable();
            } else {
                return ((ObjectExpression)this.baseExpression).getDescriptor().getTables().firstElement();
            }
        } else {
            return ((ForeignReferenceQueryKey)getQueryKeyOrNull()).getSourceTable();
        }
    }

    /**
     * Calculate the relation table for based on the various QueryKeyExpression
     * usages (join query keys, custom defined query keys, or query keys for
     * mappings).
     *
     * Called from {@link SQLSelectStatement#appendFromClauseForOuterJoin}.
     *
     * @return DatabaseTable
     */
    @Override
    public DatabaseTable getRelationTable() {
        if(getMapping() != null) {
            if(getMapping().isManyToManyMapping()) {
                return ((ManyToManyMapping)getMapping()).getRelationTable();
            } else if(getMapping().isOneToOneMapping()) {
                return ((OneToOneMapping)getMapping()).getRelationTable();
            }
        } else {
            if(getQueryKeyOrNull().isForeignReferenceQueryKey()) {
                return ((ForeignReferenceQueryKey)getQueryKeyOrNull()).getRelationTable(getDescriptor());
            }
        }
        return null;
    }
}
