/*
 * 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<Expression> partialAttributes = ((ObjectLevelReadQuery)getBaseQuery()).getPartialAttributeExpressions().iterator();
            while(partialAttributes.hasNext()){
                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.
     */
    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
     */
    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<DatabaseMapping> 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;
    }
}
