/*
 * Copyright (c) 1998, 2019 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 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 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 = Boolean.valueOf(queryKey.isDirectQueryKey());
            } else {
                DatabaseMapping mapping = getMapping();
                if (mapping != null) {
                    if (mapping.isVariableOneToOneMapping()) {
                        throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(mapping, mapping.getDescriptor());
                    } else {
                        isAttributeExpression = Boolean.valueOf(mapping.isDirectToFieldMapping());
                    }
                } else {
                    isAttributeExpression = Boolean.FALSE;
                }
            }
        }
        return isAttributeExpression.booleanValue();
    }

    @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;
    }
}
