/*
 * 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
package org.eclipse.persistence.internal.queries;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.expressions.BaseExpression;
import org.eclipse.persistence.internal.expressions.ForUpdateOfClause;
import org.eclipse.persistence.internal.expressions.ObjectExpression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.helper.NonSynchronizedSubVector;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.Cursor;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * <p><b>Purpose</b>:
 * A common class to be used by ObjectLevelReadQueries and ReportItems.  This
 * Class will be used to store Joined Attribute Expressions.  It will also
 * store the indexes for object construction.
 *
 * @author Gordon Yorke
 * @since EJB3.0 RI
 */

public class JoinedAttributeManager implements Cloneable, Serializable {

    /** Stores AggregateObjectMapping expressions used within local join expressions */
    protected transient List<DatabaseMapping> joinedAggregateMappings = new ArrayList(0);

    /** indexed list of mappings corresponding to */
    protected transient List<DatabaseMapping> joinedAttributeMappings = new ArrayList(0);

    /** Stores the joined attributes added through the query */
    protected List<Expression> joinedAttributeExpressions;

    /** Stores the joined attributes as specified in the descriptor */
    protected List<Expression> joinedMappingExpressions;

    /** PERF: Cache the local joined attribute expressions. */
    protected List<Expression> joinedAttributes;

    /** Used to determine if -m joining has been used. */
    protected boolean isToManyJoin = false;

    /** PERF: Used to avoid null checks for inner attribute joining. */
    protected boolean hasOuterJoinedAttribute = true;

    /** Used internally for joining. */
    protected transient Map<DatabaseMapping, Object> joinedMappingIndexes;

    /** Used internally for joining. */
    protected transient Map<DatabaseMapping, ObjectLevelReadQuery> joinedMappingQueries;

    /** PERF: Stores the cloned joinedMappingQueries. */
    protected transient Map<DatabaseMapping, ObjectLevelReadQuery> joinedMappingQueryClones;

    /** Stored all row results to -m joining. */
    protected transient List<AbstractRecord> dataResults;

    /** Stored all row results to -m joining by cache key. */
    protected transient Map<Object, List<AbstractRecord>> dataResultsByPrimaryKey;

    /** Stores the descriptor that these joins apply on */
    protected transient ClassDescriptor descriptor;

    /** Stores the base builder for resolving joined attributes by name. */
    protected ExpressionBuilder baseExpressionBuilder;

    /** Stores the last used base expression while adding joined attribute expression. */
    protected Expression lastJoinedAttributeBaseExpression;

    /** Stores the base query. */
    protected ObjectBuildingQuery baseQuery;

    /** Stores the result index of the parent, used for oneToMany joins. */
    protected int parentResultIndex;

    /** Determine if duplicate rows should be filter when using 1-m joining. */
    protected boolean shouldFilterDuplicates = true;

    //** Stores orderBy expressions of the joined CollectionMappings - in case the mapping has listFieldOrder */
    protected transient List<Expression> orderByExpressions;

    //** Stores additional field expressions of the joined CollectionMappings - in case the mapping has listFieldOrder */
    protected transient List<Expression> additionalFieldExpressions;

    public JoinedAttributeManager(){
    }

    public JoinedAttributeManager(ClassDescriptor descriptor, ExpressionBuilder baseBuilder, ObjectBuildingQuery baseQuery){
        this.descriptor = descriptor;
        this.baseQuery = baseQuery;
        this.baseExpressionBuilder = baseBuilder;
        this.parentResultIndex = 0;
    }

    /**
     * Return if duplicate rows should be filter when using 1-m joining.
     */
    public boolean shouldFilterDuplicates() {
        return shouldFilterDuplicates;
    }

    /**
     * Set if duplicate rows should be filter when using 1-m joining.
     */
    public void setShouldFilterDuplicates(boolean shouldFilterDuplicates) {
        this.shouldFilterDuplicates = shouldFilterDuplicates;
    }

    public void addJoinedAttribute(Expression attributeExpression) {
        this.getJoinedAttributes().add(attributeExpression);
    }

    public void addJoinedAttributeExpression(Expression attributeExpression) {
        if(!getJoinedAttributeExpressions().contains(attributeExpression)) {
            getJoinedAttributeExpressions().add(attributeExpression);
        }
    }

    /**
     * Add an attribute represented by the given attribute name to the list of joins for this query.
     * Note: Mapping level joins are represented separately from query level joins.
     */
    public void addJoinedMappingExpression(Expression mappingExpression) {
        getJoinedMappingExpressions().add(mappingExpression);
    }

    /**
     * Add an attribute represented by the given attribute name to the list of joins for this query.
     * Note: Mapping level joins are represented separately from query level joins.
     */
    public void addJoinedMapping(String attributeName) {
        addJoinedMappingExpression(this.baseExpressionBuilder.get(attributeName));
    }

    /**
     * Clones the Joined Attribute Manager.  Generally called from Query.clone().
     */
    @Override
    public JoinedAttributeManager clone(){
        JoinedAttributeManager joinManager = null;
        try {
            joinManager = (JoinedAttributeManager)super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new InternalError(exception.toString());
        }
        if (this.joinedAttributeExpressions != null) {
            joinManager.joinedAttributeExpressions = new ArrayList<>(this.joinedAttributeExpressions);
        }
        if (this.joinedMappingExpressions != null) {
            joinManager.joinedMappingExpressions = new ArrayList<>(this.joinedMappingExpressions);
        }
        if (this.joinedAttributes != null) {
            joinManager.joinedAttributes = new ArrayList<>(this.joinedAttributes);
        }
        if (this.joinedMappingIndexes != null) {
            joinManager.joinedMappingIndexes = new HashMap<>(this.joinedMappingIndexes);
        }
        if (this.joinedMappingQueries != null) {
            joinManager.joinedMappingQueries = new HashMap<>(this.joinedMappingQueries);
        }
        if (this.orderByExpressions != null) {
            joinManager.orderByExpressions = new ArrayList<>(this.orderByExpressions);
        }
        if (this.additionalFieldExpressions != null) {
            joinManager.additionalFieldExpressions = new ArrayList<>(this.additionalFieldExpressions);
        }
        if (this.joinedAttributeMappings != null) {
            joinManager.joinedAttributeMappings = new ArrayList<>(this.joinedAttributeMappings);
        }
        if (this.joinedAggregateMappings !=null) {
            joinManager.joinedAggregateMappings = new ArrayList<>(this.joinedAggregateMappings);
        }
        return joinManager;
    }

    /**
     * Copies settings from another manager. Should copy all the attributes that clone method clones.
     */
    public void copyFrom(JoinedAttributeManager otherJoinManager){
        this.joinedAttributeExpressions = otherJoinManager.joinedAttributeExpressions;
        this.joinedMappingExpressions = otherJoinManager.joinedMappingExpressions;
        this.joinedAttributes = otherJoinManager.joinedAttributes;
        this.joinedMappingIndexes = otherJoinManager.joinedMappingIndexes;
        this.joinedMappingQueries = otherJoinManager.joinedMappingQueries;
        this.orderByExpressions = otherJoinManager.orderByExpressions;
        this.additionalFieldExpressions = otherJoinManager.additionalFieldExpressions;
        this.joinedAttributeMappings = otherJoinManager.joinedAttributeMappings;
        this.joinedAggregateMappings = otherJoinManager.joinedAggregateMappings;
    }

    /**
     * Clear the joining state.  This is used to redefine a queries joins for nested joins.
     */
    public void clear(){
        this.joinedAttributeExpressions = null;
        this.joinedMappingExpressions = null;
        this.joinedAttributes = null;
        this.joinedMappingIndexes = null;
        this.isToManyJoin = false;
        this.hasOuterJoinedAttribute = false;
        this.joinedMappingQueries = null;
        this.joinedMappingQueryClones = null;
        this.orderByExpressions = null;
        this.additionalFieldExpressions = null;
        this.joinedAttributeMappings = null;
        this.joinedAggregateMappings = null;
    }

    /**
     * For joining the resulting rows include the field/values for many objects.
     * As some of the objects may have the same field names, these row partitions need to be calculated.
     * The indexes are stored in the query and used later when building the objects.
     */
    public int computeJoiningMappingIndexes(boolean includeAllSubclassFields, AbstractSession session, int offset) {
        if (!hasJoinedExpressions()) {
            return offset;
        }
        setJoinedMappingIndexes_(new HashMap(getJoinedAttributeExpressions().size() + getJoinedMappingExpressions().size()));
        int fieldIndex = 0;
        if (getBaseQuery().hasPartialAttributeExpressions()) {
            fieldIndex = getDescriptor().getPrimaryKeyFields().size(); // Query will select pks
            //next check for any partial attributes that are not joined attributes
            Iterator partialAttributes = ((ObjectLevelReadQuery)getBaseQuery()).getPartialAttributeExpressions().iterator();
            while(partialAttributes.hasNext()){
                Expression expression = (Expression)partialAttributes.next();
                if (expression.isQueryKeyExpression()){
                    if (!getJoinedMappingExpressions().contains(expression) && ! getJoinedAttributeExpressions().contains(expression)){
                        fieldIndex += ((QueryKeyExpression)expression).getFields().size();
                    }
                }
            }
        } else if (getBaseQuery().hasExecutionFetchGroup()) {
            fieldIndex = ((ObjectLevelReadQuery)getBaseQuery()).getFetchGroupNonNestedFieldsSet().size();
        } else {
            if (includeAllSubclassFields) {
                fieldIndex = getDescriptor().getAllSelectionFields((ObjectLevelReadQuery)getBaseQuery()).size();
            } else {
                fieldIndex = getDescriptor().getSelectionFields((ObjectLevelReadQuery)getBaseQuery()).size();
            }
        }
        fieldIndex += offset;
        fieldIndex = computeIndexesForJoinedExpressions(getJoinedAttributeExpressions(), fieldIndex, session);
        fieldIndex = computeIndexesForJoinedExpressions(getJoinedMappingExpressions(), fieldIndex, session);
        return fieldIndex;
    }

    /**
     * This method is used when computing the nested queries for joined mappings.
     * It recurses computing the nested mapping queries and their join indexes.
     */
    protected void computeNestedQueriesForJoinedExpressions(List joinedExpressions, AbstractSession session, ObjectLevelReadQuery readQuery) {
        for (int index = 0; index < joinedExpressions.size(); index++) {
            ObjectExpression objectExpression = (ObjectExpression)joinedExpressions.get(index);

            // Expression may not have been initialized.
            objectExpression.getBuilder().setSession(session.getRootSession(null));
            if (objectExpression.getBuilder().getQueryClass() == null){
                objectExpression.getBuilder().setQueryClass(descriptor.getJavaClass());
            }
            //get the first expression after the builder that is not an aggregate, and populate the aggregateMapping list if there are aggregates
            ObjectExpression baseExpression = objectExpression.getFirstNonAggregateExpressionAfterExpressionBuilder(getJoinedAggregateMappings());

            // PERF: Cache local join attribute Expression.
            this.addJoinedAttribute(baseExpression);

            DatabaseMapping mapping = baseExpression.getMapping();
            this.getJoinedAttributeMappings().add(mapping);

            // focus on the base expression.  Nested queries will handle nested expressions, and only need to be processed once
            if (mapping.isForeignReferenceMapping() && !getJoinedMappingQueries_().containsKey(mapping)) {
                // A nested query must be built to pass to the descriptor that looks like the real query execution would.
                ObjectLevelReadQuery nestedQuery = ((ForeignReferenceMapping)mapping).prepareNestedJoins(this, readQuery, session);
                if (nestedQuery != null) {
                    // Register the nested query to be used by the mapping for all the objects.
                    getJoinedMappingQueries_().put(mapping, nestedQuery);
                }
                if (mapping.isCollectionMapping()){
                    mapping.getContainerPolicy().addNestedJoinsQueriesForMapKey(this, readQuery, session);
                }
            }
        }
    }

    /**
     * Used to optimize joining by pre-computing the nested join queries for the mappings.
     */
    public void computeJoiningMappingQueries(AbstractSession session) {
        if (hasJoinedExpressions()) {
            this.joinedAttributeMappings = new ArrayList<>(getJoinedAttributeExpressions().size() + getJoinedMappingExpressions().size());
            this.joinedAttributes = new ArrayList<>(getJoinedAttributeExpressions().size() + getJoinedMappingExpressions().size());
            setJoinedMappingQueries_(new HashMap(getJoinedAttributeExpressions().size() + getJoinedMappingExpressions().size()));
            computeNestedQueriesForJoinedExpressions(getJoinedAttributeExpressions(), session, (ObjectLevelReadQuery)this.baseQuery);
            computeNestedQueriesForJoinedExpressions(getJoinedMappingExpressions(), session, (ObjectLevelReadQuery)this.baseQuery);
        }
    }

    /**
     * This method is used when computing the indexes for joined mappings. It iterates through a list of join
     * expressions and adds an index that represents where the fields represented by that expression will appear
     * in the row returned by a read query.
     * Method {@link #computeNestedQueriesForJoinedExpressions(List, AbstractSession, ObjectLevelReadQuery)}
     * must be already called.
     * @param joinedExpressions Join expressions {@link List}.
     * @param currentIndex      Current joined mapping index.
     * @param session           Current session.
     * @return Current joined mapping index updated.
     */
    protected int computeIndexesForJoinedExpressions(final List joinedExpressions, int currentIndex,
            final AbstractSession session) {
        for (int index = 0; index < joinedExpressions.size(); index++) {
            final ObjectExpression objectExpression = (ObjectExpression)joinedExpressions.get(index);
            final DatabaseMapping mapping = objectExpression.getMapping();
            // Only store the index if this is the local expression to avoid it being added multiple times.
            // This means the base local expression must be first on the list, followed by nested expressions.
            final ObjectExpression localExpression = objectExpression
                    .getFirstNonAggregateExpressionAfterExpressionBuilder(new ArrayList(1));
            if ((localExpression == objectExpression) && (mapping != null) && mapping.isForeignReferenceMapping()) {
                getJoinedMappingIndexes_().put(mapping, currentIndex);
            }
            final ClassDescriptor descriptor = mapping.getReferenceDescriptor();
            int numberOfFields = 0;
            if (descriptor == null) {
                // Direct-collection mappings do not have descriptor.
                if (mapping.isDirectCollectionMapping()) {
                    numberOfFields = 1;
                }
            } else {
                final ObjectLevelReadQuery nestedQuery = getNestedJoinedMappingQuery(objectExpression);
                FetchGroup fetchGroup = null;
                if(descriptor.hasFetchGroupManager()) {
                    fetchGroup = nestedQuery.getExecutionFetchGroup();
                }
                if(fetchGroup != null) {
                    numberOfFields = nestedQuery.getFetchGroupNonNestedFieldsSet(mapping).size();
                } else {
                    if (objectExpression.isQueryKeyExpression()
                            && objectExpression.isUsingOuterJoinForMultitableInheritance()) {
                        numberOfFields = descriptor.getAllSelectionFields(nestedQuery).size();
                    } else if(objectExpression.isQueryKeyExpression() && objectExpression.getDescriptor() != null
                            && objectExpression.getDescriptor().hasInheritance()
                            && objectExpression.getDescriptor().getInheritancePolicy().shouldReadSubclasses()) {
                        numberOfFields = descriptor.getAllFields().size();
                    } else {
                        numberOfFields = descriptor.getSelectionFields(nestedQuery).size();
                    }
                }
            }
            if (mapping.isCollectionMapping()){
                // map keys are indexed within the collection's row.
                // Therefore we use an offset from within the collections row
                numberOfFields += mapping.getContainerPolicy()
                        .updateJoinedMappingIndexesForMapKey(getJoinedMappingIndexes_(), numberOfFields);
            }
            currentIndex = currentIndex + numberOfFields;
        }
        return currentIndex;
    }

    /**
     * Get the list of additional field expressions.
     */
    public List<Expression> getAdditionalFieldExpressions() {
        if (this.additionalFieldExpressions == null){
            this.additionalFieldExpressions = new ArrayList<>();
        }
        return additionalFieldExpressions;
    }

    /**
     * Get the list of additional field expressions.
     */
    public List<Expression> getAdditionalFieldExpressions_() {
        return additionalFieldExpressions;
    }

    /**
     * Returns the base expression builder for this query.
     */
    public ExpressionBuilder getBaseExpressionBuilder(){
        return this.baseExpressionBuilder;
    }

    /**
     * Returns the base query.
     */
    public ObjectBuildingQuery getBaseQuery(){
        return this.baseQuery;
    }

    /**
     * Return  all of the rows fetched by the query, used for 1-m joining.
     */
    public List<AbstractRecord> getDataResults_() {
        return dataResults;
    }

    public ClassDescriptor getDescriptor(){
        if (this.descriptor == null){
            this.descriptor = this.baseQuery.getDescriptor();
        }
        return this.descriptor;
    }

    /**
     * Return if there are additional field expressions.
     */
    public boolean hasAdditionalFieldExpressions() {
        return (this.additionalFieldExpressions != null) && (!this.additionalFieldExpressions.isEmpty());
    }

    /**
     * Set the list of additional field expressions.
     */
    public void setAdditionalFieldExpressions_(List<Expression> expressions) {
        this.additionalFieldExpressions = expressions;
    }

    /**
     * Return the attributes that must be joined.
     */
    public List<DatabaseMapping> getJoinedAggregateMappings() {
        if (this.joinedAggregateMappings == null){
            this.joinedAggregateMappings = new ArrayList<>();
        }
        return joinedAggregateMappings;
    }

    /**
     * Return the attributes that must be joined.
     */
    public List<Expression> getJoinedAttributeExpressions() {
        if (this.joinedAttributeExpressions == null){
            this.joinedAttributeExpressions = new ArrayList<>();
        }
        return joinedAttributeExpressions;
    }

    /**
     * Return the attributes that must be joined.
     */
    public List<DatabaseMapping> getJoinedAttributeMappings() {
        if (this.joinedAttributeMappings == null){
            this.joinedAttributeMappings = new ArrayList<>();
        }
        return this.joinedAttributeMappings;
    }

    /**
     * Return the attributes that must be joined.
     */
    public List<Expression> getJoinedAttributes() {
        if (this.joinedAttributes == null){
            this.joinedAttributes = new ArrayList<>();
        }
        return this.joinedAttributes;
    }

    /**
     * Get the list of expressions that represent elements that are joined because of their
     * mapping for this query.
     */
    public List<Expression> getJoinedMappingExpressions() {
        if (this.joinedMappingExpressions == null){
            this.joinedMappingExpressions = new ArrayList<>();
        }
        return joinedMappingExpressions;
    }

    /**
     * Return the attributes that must be joined.
     */
    public boolean hasJoinedAttributeExpressions() {
        return (this.joinedAttributeExpressions != null) && (!this.joinedAttributeExpressions.isEmpty());
    }

    /**
     * This method checks both attribute expressions and mapping expressions and
     * determines if there are any joins to be made.
     */
    public boolean hasJoinedExpressions() {
        return hasJoinedAttributeExpressions() || hasJoinedMappingExpressions();
    }

    /**
     * Return the attributes that must be joined.
     */
    public boolean hasJoinedMappingExpressions() {
        return (this.joinedMappingExpressions != null) && (!this.joinedMappingExpressions.isEmpty());
    }

    /**
     * Return if any attributes are joined.  This is a convience method that
     * is only valid after prepare.
     */
    public boolean hasJoinedAttributes() {
        return (this.joinedAttributes != null) && (!this.joinedAttributes.isEmpty());
    }

    /**
     * PERF: Return if the query uses any outer attribute joins, used to avoid null checks in building objects.
     */
    public boolean hasOuterJoinedAttributeQuery() {
        return this.hasOuterJoinedAttribute;
    }

    /**
     * Get the list of orderBy expressions.
     */
    public List<Expression> getOrderByExpressions() {
        if (this.orderByExpressions == null){
            this.orderByExpressions = new ArrayList<>();
        }
        return orderByExpressions;
    }

    /**
     * Get the list of orderBy expressions.
     */
    public List<Expression> getOrderByExpressions_() {
        return orderByExpressions;
    }

    /**
     * INTERNAL:
     *  Helper method to get the value from the clone for the expression passed in, triggering joins on
     *  all intermediate steps.
     *  Example expression "emp.project.pk" with a clone Employee will trigger indirection and return
     *  the project pk value.
     * @param session
     * @param clone
     * @param expression
     * @return
     */
    public Object getValueFromObjectForExpression(AbstractSession session, Object clone, ObjectExpression expression){
        if (!expression.isExpressionBuilder()){
            //can only operate over querykeys representing aggregate Objects.  Indirection should not be needed
            Object baseValue = this.getValueFromObjectForExpression(session, clone, (ObjectExpression)expression.getBaseExpression());
            if ( baseValue == null ) {
                return null;
            }
            DatabaseMapping mapping = expression.getMapping();
            Object attributeValue = mapping.getRealAttributeValueFromObject(baseValue, session);
            if (attributeValue != null) {
                if (mapping.isForeignReferenceMapping() && (((ForeignReferenceMapping)mapping).getIndirectionPolicy().usesTransparentIndirection())) {
                    //getRealAttributeValueFromObject does not trigger transparent indirection, but instantiateObject will (it calls size on it)
                    ((ForeignReferenceMapping)mapping).getIndirectionPolicy().instantiateObject(baseValue, attributeValue);
                }
            }
            return attributeValue;

        }
        return clone;
    }

    /**
     * Return if there are orderBy expressions.
     */
    public boolean hasOrderByExpressions() {
        return (this.orderByExpressions != null) && (!this.orderByExpressions.isEmpty());
    }

    /**
     * Set the list of orderBy expressions.
     */
    public void setOrderByExpressions_(List<Expression> expressions) {
        this.orderByExpressions = expressions;
    }

    /**
     * Return if the query uses any -m joins, and thus return duplicate/multiple rows.
     */
    public boolean isToManyJoin() {
        return this.isToManyJoin;
    }

    /**
     * Return if the attribute is specified for joining.
     */
    public boolean isAttributeJoined(ClassDescriptor mappingDescriptor, DatabaseMapping attributeMapping) {
        // Since aggregates share the same query as their parent, must avoid the aggregate thinking
        // the parents mappings is for it, (queries only share if the aggregate was not joined).
        //This isn't taking into account inheritance - a query on a child may use/join parent level mappings
        if (this.hasJoinedAttributes()) {
            //if it has joined attributes, the other collections must also be set and so don't need to be checked
            if (attributeMapping.isAggregateMapping()){
                return this.getJoinedAggregateMappings().contains(attributeMapping);
            } else {
                return this.getJoinedAttributeMappings().contains(attributeMapping);
            }}
        return isAttributeExpressionJoined(attributeMapping) || isAttributeMappingJoined(attributeMapping);
    }

    /**
     * Iterate through a list of expressions searching for the given attribute name.
     * Return true if it is found, false otherwise.  Only use if the query was preprepared so that join expressions
     * were processed.
     */
    protected boolean isMappingInJoinedExpressionList(DatabaseMapping attributeMapping, List joinedExpressionList) {
        for (Iterator joinEnum = joinedExpressionList.iterator(); joinEnum.hasNext();) {
            List aggregateMappings = new ArrayList();
            ObjectExpression expression = ((ObjectExpression)joinEnum.next()).getFirstNonAggregateExpressionAfterExpressionBuilder(aggregateMappings);
            if (attributeMapping.isAggregateObjectMapping() && aggregateMappings.contains(attributeMapping)) {
                return true;
            } else if (attributeMapping.equals(expression.getMapping())) {//expression may not have been processed yet
                return true;
            }
        }
        return false;
    }


   /**
    * Iterate through a list of expressions searching for the given attribute name.
    * Return true if it is found, false otherwise.
    */
    protected boolean isAttributeNameInJoinedExpressionList(String attributeName, List joinedExpressionList) {
        for (Iterator joinEnum = joinedExpressionList.iterator(); joinEnum.hasNext();) {
            QueryKeyExpression expression = (QueryKeyExpression)joinEnum.next();
            while (!expression.getBaseExpression().isExpressionBuilder()) {
                expression = (QueryKeyExpression)expression.getBaseExpression();
            }
            if (expression.getName().equals(attributeName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return if the attribute is specified for joining.
     */
    protected boolean isAttributeExpressionJoined(DatabaseMapping attributeMapping) {
        return isMappingInJoinedExpressionList(attributeMapping, getJoinedAttributeExpressions());
    }

    /**
     * Return whether the given attribute is joined as a result of a join on a mapping
     */
    protected boolean isAttributeMappingJoined(DatabaseMapping attributeMapping) {
        return isAttributeNameInJoinedExpressionList(attributeMapping.getAttributeName(), getJoinedMappingExpressions());
    }

    /**
     * Set the list of expressions that represent elements that are joined because of their
     * mapping for this query.
     */
    public void setJoinedAttributeExpressions_(List joinedExpressions) {
        this.joinedAttributeExpressions = joinedExpressions;
    }

    /**
     * Set the list of expressions that represent elements that are joined because of their
     * mapping for this query.
     */
    public void setJoinedMappingExpressions_(List joinedMappingExpressions) {
        this.joinedMappingExpressions = joinedMappingExpressions;
    }

    /**
     * Return the joined mapping indexes, used to compute mapping row partitions.
     */
    public Map<DatabaseMapping, Object> getJoinedMappingIndexes_() {
        return joinedMappingIndexes;
    }

    /**
     * Return the joined mapping queries, used optimize joining, only compute the nested queries once.
     */
    public Map<DatabaseMapping, ObjectLevelReadQuery> getJoinedMappingQueries_() {
        return joinedMappingQueries;
    }

    /**
     * INTERNAL:
     * Returns the nested query corresponding to the expression.
     * The passed expression should be either join mapping or joined attribute expression.
     */
    public ObjectLevelReadQuery getNestedJoinedMappingQuery(Expression expression) {
        // the first element of the list is the passed expression,
        // next one is its base, ...
        // the last one's base is ExpressionBuilder.
        ObjectExpression currentExpression = (ObjectExpression)expression;
        ArrayList<Expression> expressionBaseList = new ArrayList();
        do {
            //skip aggregates since they do not have nested query objects added to JoinedMappingQueries, instead
            //reference mappings on aggregates are added to the parent's joinAttributeManager
            if (!currentExpression.getMapping().isAggregateObjectMapping()){
                expressionBaseList.add(currentExpression);
            }
            currentExpression = (ObjectExpression)currentExpression.getBaseExpression();
        } while(!currentExpression.isExpressionBuilder());

        // the last expression in the list is not nested - its mapping should have corresponding nestedQuery.
        DatabaseMapping currentMapping = ((QueryKeyExpression)expressionBaseList.get(expressionBaseList.size() - 1)).getMapping();
        ObjectLevelReadQuery nestedQuery = getJoinedMappingQueries_().get(currentMapping);

        // unless the passed expression was not nested, repeat moving up the list.
        // the last step is the passed expression (first on the list) getting nested query corresponding to its mapping.
        for(int i = expressionBaseList.size() - 2; i >= 0; i--) {
            currentMapping = ((QueryKeyExpression)expressionBaseList.get(i)).getMapping();
            nestedQuery = nestedQuery.getJoinedAttributeManager().getJoinedMappingQueries_().get(currentMapping);
        }
        return nestedQuery;
    }

    /**
     * Set the joined mapping queries, used optimize joining, only compute the nested queries once.
     */
    public void setJoinedMappingQueries_(Map joinedMappingQueries) {
        this.joinedMappingQueries = joinedMappingQueries;
    }

    /**
     * Set the joined mapping indexes, used to compute mapping row partitions.
     */
    public void setJoinedMappingIndexes_(Map joinedMappingIndexes) {
        this.joinedMappingIndexes = joinedMappingIndexes;
    }

    /**
     * PERF: Set if the query uses any outer attribute joins, used to avoid null checks in building objects.
     */
    protected void setIsOuterJoinedAttributeQuery(boolean isOuterJoinedAttribute) {
        this.hasOuterJoinedAttribute = isOuterJoinedAttribute;
    }

    /**
     * Set if the query uses any -m joins, and thus return duplicate/multiple rows.
     */
    public void setIsToManyJoinQuery(boolean isToManyJoin) {
        this.isToManyJoin = isToManyJoin;
    }


    /**
     * Validate and prepare join expressions.
     */
    public void prepareJoinExpressions(AbstractSession session) {
        // The prepareJoinExpression check for outer-joins to set this to true.
        setIsOuterJoinedAttributeQuery(false);
        Expression lastJoinedAttributeBaseExpression = null;
        List groupedExpressionList = new ArrayList(getJoinedAttributeExpressions().size());
        for (int index = 0; index < getJoinedAttributeExpressions().size(); index++) {
            Expression expression = getJoinedAttributeExpressions().get(index);
            expression = prepareJoinExpression(expression, session);
            //EL bug 307497: break base expressions out onto the list and sort/group expressions by base expression
            lastJoinedAttributeBaseExpression = addExpressionAndBaseToGroupedList(expression, groupedExpressionList, lastJoinedAttributeBaseExpression);
        }
        //use the grouped list instead of the original
        this.setJoinedAttributeExpressions_(groupedExpressionList);
        for (int index = 0; index < getJoinedMappingExpressions().size(); index++) {
            Expression expression = getJoinedMappingExpressions().get(index);
            expression = prepareJoinExpression(expression, session);
            getJoinedMappingExpressions().set(index, expression);
        }
    }

    /**
     * adds expression and its base expressions recursively to the expressionList in groups, so that an expression is never listed before
     * its base expression
     * @param expression
     * @param expressionlist
     * @param lastJoinedAttributeBaseExpression
     * @return
     */
    protected Expression addExpressionAndBaseToGroupedList(Expression expression, List expressionlist, Expression lastJoinedAttributeBaseExpression){
        if(!expressionlist.contains(expression)) {
            int baseExpressionIndex = -1;
            boolean sameBase = false;//better than using instanceof BaseExpression.  If its not an objectExpression, it will get an exception in prepare anyway
            if((expression.isObjectExpression())) {
                Expression baseExpression = ((BaseExpression)expression).getBaseExpression();
                //filter out aggregate expressions between this and the next node.
                while (!baseExpression.isExpressionBuilder() && ((QueryKeyExpression)baseExpression).getMapping().isAggregateMapping()){
                    baseExpression = ((BaseExpression)baseExpression).getBaseExpression();
                }

                if(baseExpression != null && !baseExpression.isExpressionBuilder()) {
                    addExpressionAndBaseToGroupedList(baseExpression, expressionlist, lastJoinedAttributeBaseExpression);
                    // EL bug 307497
                    if (baseExpression != lastJoinedAttributeBaseExpression) {
                        baseExpressionIndex = getJoinedAttributeExpressions().indexOf(baseExpression);
                    } else {
                        sameBase = true;
                    }
                }
            }

            // EL bug 307497
            if (baseExpressionIndex == -1) {
                expressionlist.add(expression);
                if (!sameBase) {
                    lastJoinedAttributeBaseExpression = expression;
                }
            } else {
                //Add attributeExpression at baseExpressionIndex + 1.
                expressionlist.add(baseExpressionIndex+1, expression);
            }
        }
        return lastJoinedAttributeBaseExpression;
    }

    /**
     * Validate and prepare the join expression.
     */
    protected Expression prepareJoinExpression(Expression expression, AbstractSession session) {
        // Must be query key expression.
        if (!expression.isQueryKeyExpression()) {
            throw QueryException.mappingForExpressionDoesNotSupportJoining(expression);
        }
        QueryKeyExpression objectExpression = (QueryKeyExpression)expression;

        // Expression may not have been initialized.
        if (objectExpression.getBuilder().getQueryClass() == null) {
            objectExpression = (QueryKeyExpression)objectExpression.rebuildOn(this.baseExpressionBuilder);

            if (objectExpression.getBuilder().getQueryClass() == null) {
                objectExpression.getBuilder().setQueryClass(this.descriptor.getJavaClass());
            }
        }
        objectExpression.getBuilder().setSession(session.getRootSession(null));

        // Can only join relationships.
        if ((objectExpression.getMapping() == null) || (!objectExpression.getMapping().isJoiningSupported())) {
            throw QueryException.mappingForExpressionDoesNotSupportJoining(objectExpression);
        }

        // Search if any of the expression traverse a 1-m.
        ObjectExpression baseExpression = objectExpression;
        while (!baseExpression.isExpressionBuilder()) {
            //pulled from prepareJoinExpressions
            baseExpression.setShouldUseOuterJoinForMultitableInheritance(true);

            if (((QueryKeyExpression)baseExpression).shouldQueryToManyRelationship()) {
                setIsToManyJoinQuery(true);
            }
            if (baseExpression.shouldUseOuterJoin()) {
                setIsOuterJoinedAttributeQuery(true);
            }
            baseExpression = (ObjectExpression)baseExpression.getBaseExpression();
        }

        return objectExpression;
    }

    /**
     * This method collects the Joined Mappings from the descriptor and initializes them.
     * Excludes the mapping that are not in the passed mappingsAllowedToJoin set (if it's not null).
     */
    public void processJoinedMappings(AbstractSession session) {
        Set<String> fetchGroupAttributes = null;
        FetchGroup fetchGroup = getBaseQuery().getExecutionFetchGroup();
        if(fetchGroup != null) {
            fetchGroupAttributes = fetchGroup.getAttributeNames();
        }
        ObjectBuilder objectBuilder = getDescriptor().getObjectBuilder();
        if (objectBuilder.hasJoinedAttributes()) {
            List mappingJoinedAttributes = objectBuilder.getJoinedAttributes();
            if (!hasJoinedAttributeExpressions()) {
                for (int i = 0; i < mappingJoinedAttributes.size(); i++) {
                    ForeignReferenceMapping mapping = (ForeignReferenceMapping) mappingJoinedAttributes.get(i);
                    if(fetchGroupAttributes == null || fetchGroupAttributes.contains(mapping.getAttributeName())) {
                        addAndPrepareJoinedMapping(mapping, session);
                    }
                }
            } else {
                for (int i = 0; i < mappingJoinedAttributes.size(); i++) {
                    ForeignReferenceMapping mapping = (ForeignReferenceMapping) mappingJoinedAttributes.get(i);
                    if (!isAttributeExpressionJoined(mapping)) {
                        if(fetchGroupAttributes == null || fetchGroupAttributes.contains(mapping.getAttributeName())) {
                            addAndPrepareJoinedMapping(mapping, session);
                        }
                    }
                }
            }
        }
    }

    /**
     * Add the mapping for join fetch, prepare and return the join expression being used.
     */
    public Expression addAndPrepareJoinedMapping(ForeignReferenceMapping mapping, AbstractSession session) {
        Expression joinMappingExpression = null;
        if (mapping.isCollectionMapping()) {
            if (mapping.isInnerJoinFetched()) {
                joinMappingExpression = getBaseExpressionBuilder().anyOf(mapping.getAttributeName(), false);
            } else if (mapping.isOuterJoinFetched()) {
                joinMappingExpression = getBaseExpressionBuilder().anyOfAllowingNone(mapping.getAttributeName(), false);
            }
        } else {
            if (mapping.isInnerJoinFetched()) {
                joinMappingExpression = getBaseExpressionBuilder().get(mapping.getAttributeName());
            } else if (mapping.isOuterJoinFetched()) {
                joinMappingExpression = getBaseExpressionBuilder().getAllowingNull(mapping.getAttributeName());
            }
        }
        if (joinMappingExpression != null) {
            joinMappingExpression = prepareJoinExpression(joinMappingExpression, session);
            addJoinedMappingExpression(joinMappingExpression);
        }
        return joinMappingExpression;
    }

    /**
     * Reset the JoinedAttributeManager.  This will be called when the Query is re-prepared
     */
    public void reset(){
        this.joinedMappingExpressions = null;
        this.joinedAttributes = null;
        this.isToManyJoin = false;
        this.hasOuterJoinedAttribute = true;
        this.joinedMappingIndexes = null;
        this.joinedMappingQueries = null;
        this.dataResults = null;
        this.joinedAttributeMappings = null;
        this.joinedAggregateMappings = null;
    }

    /**
     * This method is called from within this package it is used when
     * initializing a report Item
     */
    public void setBaseQuery(ObjectLevelReadQuery query){
        this.baseQuery = query;
    }

    /**
     * This method is called from within this package, it is used when
     * initializing a ReportItem
     */
    protected void setBaseExpressionBuilder(ExpressionBuilder builder){
        this.baseExpressionBuilder = builder;
    }

    /**
     * Return all of the rows fetched by the query by cache-key, used for 1-m joining.
     */
    public Map<Object, List<AbstractRecord>> getDataResultsByPrimaryKey() {
        return dataResultsByPrimaryKey;
    }

    /**
     * Set all of the rows fetched by the query by cache-key, used for 1-m joining.
     */
    protected void setDataResultsByPrimaryKey(Map<Object, List<AbstractRecord>> dataResultsByPrimaryKey) {
        this.dataResultsByPrimaryKey = dataResultsByPrimaryKey;
    }

    /**
     * Set all of the rows fetched by the query, used for 1-m joining.
     */
    public void setDataResults(List dataResults, AbstractSession session) {
        this.dataResults = dataResults;
        processDataResults(session);
    }

    /**
     * Process the data-results for joined data for a 1-m join.
     * This allows all the data to be processed once, instead of n times for each object.
     */
    protected void processDataResults(AbstractSession session) {
        this.dataResultsByPrimaryKey = new HashMap();
        int size = this.dataResults.size();
        Object firstKey = null;
        Object lastKey = null;
        List<AbstractRecord> childRows = null;
        ObjectBuilder builder = getDescriptor().getObjectBuilder();
        int parentIndex = getParentResultIndex();
        Vector trimedFields = null;
        for (int dataResultsIndex = 0; dataResultsIndex < size; dataResultsIndex++) {
            AbstractRecord row = this.dataResults.get(dataResultsIndex);
            AbstractRecord parentRow = row;
            // Must adjust for the parent index to ensure the correct pk is extracted.
            if (parentIndex > 0) {
                if (trimedFields == null) { // The fields are always the same, so only build once.
                    trimedFields = new NonSynchronizedSubVector(row.getFields(), parentIndex, row.size());
                }
                Vector trimedValues = new NonSynchronizedSubVector(row.getValues(), parentIndex, row.size());
                parentRow = new DatabaseRecord(trimedFields, trimedValues);
            }
            // Extract the primary key of the source object, to filter only the joined rows for that object.
            Object sourceKey = builder.extractPrimaryKeyFromRow(parentRow, session);
            // May be any outer-join so ignore null.
            if (sourceKey != null) {
                if (firstKey == null) {
                    firstKey = sourceKey;
                }
                if ((lastKey != null) && lastKey.equals(sourceKey)) {
                    childRows.add(row);
                    if (shouldFilterDuplicates()) {
                        // Also null out the row because it is a duplicate to avoid object building processing it.
                        this.dataResults.set(dataResultsIndex, null);
                    }
                } else {
                    childRows =  this.dataResultsByPrimaryKey.get(sourceKey);
                    if (childRows == null) {
                        childRows = new ArrayList();
                        this.dataResultsByPrimaryKey.put(sourceKey, childRows);
                    } else {
                        if (shouldFilterDuplicates()) {
                            // Also null out the row because it is a duplicate to avoid object building processing it.
                            this.dataResults.set(dataResultsIndex, null);
                        }
                    }
                    childRows.add(row);
                    lastKey = sourceKey;
                }
            }
        }
        // If pagination is used, the first and last rows may be missing their 1-m joined rows, so reject them from the results.
        // This will cause them to build normally by executing a query.
        if (this.isToManyJoin) {
            if ((lastKey != null) && (this.baseQuery.getMaxRows() > 0)) {
                this.dataResultsByPrimaryKey.remove(lastKey);
            }
            if ((firstKey != null) && (this.baseQuery.getFirstResult() > 0)) {
                this.dataResultsByPrimaryKey.remove(firstKey);
            }
        }
    }

    /**
     * Clear the data-results for joined data for a 1-m join.
     */
    public void clearDataResults() {
        this.dataResults = null;
        this.dataResultsByPrimaryKey = null;
    }

    /**
     * Process the data-results for joined data for a 1-m join.
     * This allows incremental processing for a cursor.
     */
    public AbstractRecord processDataResults(AbstractRecord row, Cursor cursor, boolean forward) {
        if (this.dataResultsByPrimaryKey == null) {
            this.dataResultsByPrimaryKey = new HashMap();
        }
        AbstractRecord parentRow = row;
        List<AbstractRecord> childRows = new ArrayList<>();
        childRows.add(row);
        int parentIndex = getParentResultIndex();
        // Must adjust for the parent index to ensure the correct pk is extracted.
        Vector trimedFields = new NonSynchronizedSubVector(row.getFields(), parentIndex, row.size());
        if (parentIndex > 0) {
            Vector trimedValues = new NonSynchronizedSubVector(row.getValues(), parentIndex, row.size());
            parentRow = new DatabaseRecord(trimedFields, trimedValues);
        }
        ObjectBuilder builder = getDescriptor().getObjectBuilder();
        AbstractSession session = cursor.getExecutionSession();
        // Extract the primary key of the source object, to filter only the joined rows for that object.
        Object sourceKey = builder.extractPrimaryKeyFromRow(parentRow, session);
        AbstractRecord extraRow = null;
        while (true) {
            AbstractRecord nextRow = null;
            if (forward) {
                nextRow = cursor.getAccessor().cursorRetrieveNextRow(cursor.getFields(), cursor.getResultSet(), session);
            } else {
                nextRow = cursor.getAccessor().cursorRetrievePreviousRow(cursor.getFields(), cursor.getResultSet(), session);
            }
            if (nextRow == null) {
                break;
            }
            AbstractRecord nextParentRow = nextRow;
            if (parentIndex > 0) {
                Vector trimedValues = new NonSynchronizedSubVector(nextParentRow.getValues(), parentIndex, nextParentRow.size());
                nextParentRow = new DatabaseRecord(trimedFields, trimedValues);
            }
            // Extract the primary key of the source object, to filter only the joined rows for that object.
            Object nextKey = builder.extractPrimaryKeyFromRow(nextParentRow, session);
            if ((sourceKey != null) && sourceKey.equals(nextKey)) {
                childRows.add(nextRow);
            } else {
                extraRow = nextRow;
                break;
            }
        }
        this.dataResultsByPrimaryKey.put(sourceKey, childRows);
        return extraRow;
    }

    /**
     * Called to set the descriptor on a Join Managerwith in a ReportItem, durring
     * initialization, and durring DatabaseQuery.checkDescriptor.
     */
    public void setDescriptor(ClassDescriptor descriptor){
        this.descriptor = descriptor;
    }

    /**
     * Used for joining in conjunction with pessimistic locking.
     * Iterate through a list of joined expressions and ensure expression is set on the locking
     * clause for each expression that represents a pessimisically locked descriptor.
     */
    public ForUpdateOfClause setupLockingClauseForJoinedExpressions(ForUpdateOfClause lockingClause, AbstractSession session) {
        if (hasJoinedAttributeExpressions()){
            return setupLockingClauseForJoinedExpressions(getJoinedAttributeExpressions(), session,lockingClause);
        }
        if (hasJoinedMappingExpressions()){
            return setupLockingClauseForJoinedExpressions(getJoinedMappingExpressions(), session,lockingClause);
        }
        return lockingClause;
    }

    /**
     * Used for joining in conjunction with pessimistic locking.
     * Iterate through a list of joined expressions and ensure expression is set on the locking
     * clause for each expression that represents a pessimisically locked descriptor.
     */
    private ForUpdateOfClause setupLockingClauseForJoinedExpressions(List joinedExpressions, AbstractSession session, ForUpdateOfClause lockingClause) {
        // Must iterate over all of the joined attributes, just check
        // if any of them have pessimistic locking defined on the descriptor.
        for (Iterator e = joinedExpressions.iterator(); e.hasNext();) {
            Expression expression = (Expression)e.next();

            // Expression has not yet been validated.
            if (expression.isObjectExpression()) {
                ObjectExpression joinedAttribute = (ObjectExpression)expression;

                // Expression may not have been initialized.
                joinedAttribute.getBuilder().setSession(session.getRootSession(null));
                if (joinedAttribute.getBuilder().getQueryClass() == null){
                    joinedAttribute.getBuilder().setQueryClass(descriptor.getJavaClass());
                }

                ClassDescriptor nestedDescriptor = joinedAttribute.getDescriptor();

                // expression may not be valid, no descriptor, validation occurs later.
                if (nestedDescriptor == null) {
                    return lockingClause;
                }
                if (nestedDescriptor.hasPessimisticLockingPolicy()) {
                    if (lockingClause == null) {
                        lockingClause = new ForUpdateOfClause();
                        lockingClause.setLockMode(nestedDescriptor.getCMPPolicy().getPessimisticLockingPolicy().getLockingMode());
                    }
                    lockingClause.addLockedExpression(joinedAttribute);
                }
            }
        }
        return lockingClause;
    }

    public void setParentResultIndex(int parentsResultIndex) {
        this.parentResultIndex = parentsResultIndex;
    }

    public int getParentResultIndex() {
        return parentResultIndex;
    }

    public Map<DatabaseMapping, ObjectLevelReadQuery> getJoinedMappingQueryClones() {
        return joinedMappingQueryClones;
    }

    public void setJoinedMappingQueryClones(Map joinedMappingQueryClones) {
        this.joinedMappingQueryClones = joinedMappingQueryClones;
    }
}
