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

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     05/19/2010-2.1 ailitchev - Bug 244124 - Add Nested FetchGroup
package org.eclipse.persistence.descriptors;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.queries.AttributeItem;
import org.eclipse.persistence.internal.queries.EntityFetchGroup;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;

/**
 * <p><b>Purpose</b>: The fetch group manager controls the named fetch groups defined at
 * the descriptor level. EclipseLink supports multiple, overlapped fetch groups, optionally with
 * one of them as the default fetch group.
 * <p>
 * The domain object must implement org.eclipse.persistence.queries.FetchGroupTracker interface,
 * in order to make use of the fetch group performance enhancement feature.
 * <p>
 * Please refer to FetchGroup class for the pros and cons of fetch group usage.
 *
 * @see org.eclipse.persistence.queries.FetchGroup
 * @see org.eclipse.persistence.queries.FetchGroupTracker
 *
 * @author King Wang, dclarke
 * @since TopLink 10.1.3.
 */
public class FetchGroupManager implements Cloneable, java.io.Serializable {
    //The group map is keyed by the group name, valued by the fetch group object.
    private Map<String, FetchGroup> fetchGroups = null;

    // EntityFetchGroups mapped by their AttributeNames Sets.
    private transient Map<Set<String>, EntityFetchGroup> entityFetchGroups = new ConcurrentHashMap();

    //default fetch group
    private FetchGroup defaultFetchGroup;
    private EntityFetchGroup defaultEntityFetchGroup;

    // full fetch group - contains all attributes, none of them nested.
    private FetchGroup fullFetchGroup;

    // minimal fetch group - contains primary key attribute(s) and version.
    private FetchGroup minimalFetchGroup;

    // identity fetch group - contains primary key attribute(s) only.
    private EntityFetchGroup idEntityFetchGroup;

    // non relational fetch group - contains intersection of non-relational attributes
    // and defaultEntityFetchGroup.
    private EntityFetchGroup nonReferenceEntityFetchGroup;

    //ref to the descriptor
    private ClassDescriptor descriptor;

    // indicates whether defaultFetchGroup should be copied from the parent if not set.
    private boolean shouldUseInheritedDefaultFetchGroup = true;

    /**
     * Constructor
     */
    public FetchGroupManager() {
    }

    /**
     * Add a named fetch group to the descriptor
     */
    public void addFetchGroup(FetchGroup group) {
        //create a new fetch group and put it in the group map.
        getFetchGroups().put(group.getName(), group);
    }

    /**
     * Return the fetch group map: keyed by the group name, valued by the fetch group object.
     */
    public Map<String, FetchGroup> getFetchGroups() {
        if (this.fetchGroups == null) {
            //lazy initialized
            this.fetchGroups = new HashMap<>(2);
        }

        return this.fetchGroups;
    }

    /**
     * Return the descriptor-level default fetch group.
     * All read object and read all queries would use the default fetch group if no fetch group
     * is explicitly defined for the query, unless setShouldUseDefaultFetchGroup(false); is also
     * called on the query.
     *
     * Default fetch group should be used carefully. It would be beneficial if most of the system queries
     * are for the subset of the object, so un-needed attributes data would not have to be read, and the
     * users do not have to setup every query for the given fetch group, as default one is always used.
     * However, if queries on object are mostly use case specific and not systematic, using default fetch group
     * could cause undesirable extra round-trip and performance degradation.
     *
     * @see org.eclipse.persistence.queries.ObjectLevelReadQuery#setShouldUseDefaultFetchGroup(boolean)
     */
    public FetchGroup getDefaultFetchGroup() {
        return this.defaultFetchGroup;
    }

    /**
     * INTERNAL:
     * Returns EntityFetchGroup corresponding to default FetchGroup.
     */
    public EntityFetchGroup getDefaultEntityFetchGroup() {
        return this.defaultEntityFetchGroup;
    }

    /**
     * PUBLIC:
     * Returns clone of the minimal fetch group.
     * Could be used as a starting point for a new user-defined fetch group.
     */
    public FetchGroup createMinimalFetchGroup() {
        return this.minimalFetchGroup.clone();
    }

    /**
     * PUBLIC:
     * Indicates whether the passed fetch group is minimal.
     */
    public boolean isMinimalFetchGroup(FetchGroup fetchGroup) {
        return this.minimalFetchGroup.equals(fetchGroup);
    }

    /**
     * INTERNAL:
     * Returns EntityFetchGroup corresponding to primary key attribute(s).
     */
    public EntityFetchGroup getIdEntityFetchGroup() {
        return this.idEntityFetchGroup;
    }

    /**
     * INTERNAL:
     * Returns EntityFetchGroup corresponding to non relational attributes
     * intersected with defaultFetchGroup.
     */
    public EntityFetchGroup getNonReferenceEntityFetchGroup() {
        return this.nonReferenceEntityFetchGroup;
    }

    /**
     * INTERNAL:
     * Returns EntityFetchGroup corresponding to non relational attributes
     * intersected with defaultFetchGroup.
     */
    public EntityFetchGroup getNonReferenceEntityFetchGroup(boolean addPk, boolean addVersion) {
        if(addPk && addVersion) {
            return getNonReferenceEntityFetchGroup();
        }
        FetchGroup nonReferenceFetchGroup = new FetchGroup();
        for (DatabaseMapping mapping : getDescriptor().getMappings()) {
            if(!mapping.isForeignReferenceMapping()) {
                String name = mapping.getAttributeName();
                if(this.defaultEntityFetchGroup == null || this.defaultEntityFetchGroup.containsAttribute(name)) {
                    nonReferenceFetchGroup.addAttribute(name);
                }
            }
        }
        if(addPk) {
            for(DatabaseMapping mapping : descriptor.getObjectBuilder().getPrimaryKeyMappings()) {
                String name = mapping.getAttributeName();
                if(!nonReferenceFetchGroup.containsAttribute(name)) {
                    nonReferenceFetchGroup.addAttribute(name);
                }
            }
        } else {
            for(DatabaseMapping mapping : descriptor.getObjectBuilder().getPrimaryKeyMappings()) {
                if(mapping.isForeignReferenceMapping()) {
                    String name = mapping.getAttributeName();
                    if(!nonReferenceFetchGroup.containsAttribute(name)) {
                        // always add foreign reference pk
                        nonReferenceFetchGroup.addAttribute(name);
                    }
                }
            }
        }
        if(addVersion) {
            String lockAttribute = descriptor.getObjectBuilder().getLockAttribute();
            if(lockAttribute != null) {
                if(!nonReferenceFetchGroup.containsAttribute(lockAttribute)) {
                    nonReferenceFetchGroup.addAttribute(lockAttribute);
                }
            }
        }
        return getEntityFetchGroup(nonReferenceFetchGroup);
    }

    /**
     * INTERNAL:
     * Add primary key and version attributes to the passed fetch group.
     */
    public void addMinimalFetchGroup(FetchGroup fetchGroup) {
        if (this.minimalFetchGroup == null) {
            return;
        }
        Iterator<String> it = this.minimalFetchGroup.getAttributeNames().iterator();
        while(it.hasNext()) {
            String name = it.next();
            if(!fetchGroup.containsAttribute(name)) {
                fetchGroup.addAttribute(name);
            }
        }
    }

    /**
     * PUBLIC:
     * Add primary key and version attributes to the passed fetch group
     * and all the fetch group it contains.
     * Also verifies that all the attributes have corresponding mappings.
     * Could be used for fetch group preparation and validation.
     * Called by ObjectLevelReadQuery prepareFetchgroup method.
     */
    public void prepareAndVerify(FetchGroup fetchGroup) {
        prepareAndVerifyInternal(fetchGroup, "");
    }

    /**
     * INTERNAL:
     * Add primary key and version attributes to the passed fetch group
     * and all the fetch group it contains.
     * Also verifies that all the attributes have corresponding mappings.
     */
    protected void prepareAndVerifyInternal(FetchGroup fetchGroup, String attributePrefix) {
        addMinimalFetchGroup(fetchGroup);
        ObjectBuilder builder = this.descriptor.getObjectBuilder();
        if (fetchGroup.isValidated()){
            return;
        }
        Iterator<Map.Entry<String, AttributeItem>> it = fetchGroup.getAllItems().entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry<String, AttributeItem> entry = it.next();
            String name = entry.getKey();
            DatabaseMapping mapping = builder.getMappingForAttributeName(name);
            if(mapping != null) {
                FetchGroup nestedFetchGroup = (FetchGroup)entry.getValue().getGroup();
                if(nestedFetchGroup != null) {
                   if(mapping.isForeignReferenceMapping()) {
                       ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
                       if(referenceDescriptor != null) {
                           FetchGroupManager nestedFetchGroupManager = referenceDescriptor.getFetchGroupManager();
                           if(nestedFetchGroupManager != null) {
                               nestedFetchGroupManager.prepareAndVerifyInternal(nestedFetchGroup, attributePrefix + name + '.');
                           } else {
                               // target descriptor does not support fetch groups
                               throw ValidationException.fetchGroupHasWrongReferenceClass(fetchGroup, name);
                           }
                       } else {
                           // no reference descriptor found
                           throw ValidationException.fetchGroupHasWrongReferenceAttribute(fetchGroup, name);
                       }
                   } else if (mapping.isAggregateObjectMapping()){
                       ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
                       if(referenceDescriptor != null) {
                           FetchGroupManager nestedFetchGroupManager = referenceDescriptor.getFetchGroupManager();
                           if(nestedFetchGroupManager != null) {
                               nestedFetchGroupManager.prepareAndVerifyInternal(nestedFetchGroup, attributePrefix + name + '.');
                           } else {
                               // target descriptor does not support fetch groups
                               throw ValidationException.fetchGroupHasWrongReferenceClass(fetchGroup, name);
                           }
                       } else {
                           // no reference descriptor found
                           throw ValidationException.fetchGroupHasWrongReferenceAttribute(fetchGroup, name);
                       }

                   } else {
                       // no reference mapping found
                       throw ValidationException.fetchGroupHasWrongReferenceAttribute(fetchGroup, name);
                   }
                }
            } else {
                // no mapping found
                throw ValidationException.fetchGroupHasUnmappedAttribute(fetchGroup, name);
            }
        }
    }

    /**
     * PUBLIC:
     * Returns clone of the default fetch group.
     * Could be used as a starting point for a new user-defined fetch group.
     */
    public FetchGroup createDefaultFetchGroup() {
        return this.defaultFetchGroup.clone();
    }

    /**
     * PUBLIC:
     * Returns clone of the full fetch group - contains all the attributes, no nesting.
     * Could be used as a starting point for a new user-defined fetch group.
     */
    public FetchGroup createFullFetchGroup() {
        return this.fullFetchGroup.clone();
    }

    /**
     * PUBLIC:
     * Indicates whether the passed fetch group contains all the attributes, no nesting.
     */
    public boolean isFullFetchGroup(FetchGroup fetchGroup) {
        return this.fullFetchGroup.equals(fetchGroup);
    }

    /**
     * INTERNAL:
     * Returns entity fetch group corresponding to the passed set of attributes.
     */
    public EntityFetchGroup getEntityFetchGroup(Set<String> attributeNames) {
        if(attributeNames == null || attributeNames.isEmpty()) {
            return null;
        }
        EntityFetchGroup entityFetchGroup = this.entityFetchGroups.get(attributeNames);
        if(entityFetchGroup == null) {
            entityFetchGroup = new EntityFetchGroup(attributeNames);
            // EntityFetchGroup that contains all attributes is equivalent to no fetch group
            if(entityFetchGroup.equals(this.fullFetchGroup)) {
                return null;
            }
            this.entityFetchGroups.put(entityFetchGroup.getAttributeNames(), entityFetchGroup);
        }

        return entityFetchGroup;
    }

    /**
     * INTERNAL:
     * Returns entity fetch group corresponding to the passed fetch group.
     */
    public EntityFetchGroup getEntityFetchGroup(FetchGroup fetchGroup) {
        if(fetchGroup == null) {
            return null;
        }else{
            return fetchGroup.getEntityFetchGroup(this);
        }
    }

    /**
     * Return a pre-defined named fetch group.
     *
     * Lookup the FetchGroup to use given a name taking into
     * consideration descriptor inheritance to ensure parent descriptors are
     * searched for named FetchGroups.
     */
    public FetchGroup getFetchGroup(String groupName) {
        FetchGroup fg =  this.fetchGroups.get(groupName);
        if (fg == null){
            AttributeGroup ag = this.descriptor.getAttributeGroup(groupName);
            if (ag != null){
                fg = ag.toFetchGroup();
            }
        }
        if (fg == null && getDescriptor().isChildDescriptor()) {
            ClassDescriptor current = this.descriptor;

            while (fg == null && current.isChildDescriptor()) {
                ClassDescriptor parent = current.getInheritancePolicy().getParentDescriptor();
                if (parent.hasFetchGroupManager()) {
                    fg = parent.getFetchGroupManager().getFetchGroup(groupName);
                }
                if (fg == null){
                    AttributeGroup ag = parent.getAttributeGroup(groupName);
                    if (ag != null){
                        fg = ag.toFetchGroup();
                    }
                }
                current = parent;
            }
        }
        return fg;
    }

    /**
     * Lookup the FetchGroup to use given a name and a flag taking into
     * consideration descriptor inheritance to ensure parent descriptors are
     * searched for named and default FetchGroup. This is used to determine the
     * FetchGroup to use in a query's prepare.
     */
    public FetchGroup getFetchGroup(String groupName, boolean useDefault) {
        FetchGroup fg = null;

        if (groupName != null) {
            fg = getFetchGroup(groupName);
        }

        // Process default using hierarchy
        if (fg == null && useDefault) {
            fg = getDefaultFetchGroup();
        }

        return fg;
    }

    /**
     * Set the descriptor-level default fetch group.
     * All read object and read all queries would use the default fetch group if no fetch group is
     * explicitly defined for the query, unless setShouldUseDefaultFetchGroup(false);
     * is also called on the query.
     *
     * Default fetch group should be used carefully. It would be beneficial if most of the system queries
     * are for the subset of the object, so un-needed attributes data would not have to be read, and the
     * users do not have to setup every query for the given fetch group, as default one is always used.
     * However, if queries on object are mostly use case specific and not systematic, using default fetch group
     * could cause undesirable extra round-trip and performance degradation.
     *
     * @see org.eclipse.persistence.queries.ObjectLevelReadQuery#setShouldUseDefaultFetchGroup(boolean)
     */
    public void setDefaultFetchGroup(FetchGroup newDefaultFetchGroup) {
        if(this.defaultFetchGroup != newDefaultFetchGroup) {
            if(this.descriptor.isFullyInitialized()) {
                // don't do that before descriptors are initialized.
                if(newDefaultFetchGroup != null) {
                    prepareAndVerify(newDefaultFetchGroup);
                    this.defaultEntityFetchGroup = this.getEntityFetchGroup(newDefaultFetchGroup);
                } else {
                    this.defaultEntityFetchGroup = null;
                }
            }
            this.defaultFetchGroup = newDefaultFetchGroup;
            if(this.descriptor.isFullyInitialized()) {
                // don't do that before descriptors are initialized.
                initNonReferenceEntityFetchGroup();
            }
        }
    }

    /**
     * INTERNAL:
     * Return true if the object is partially fetched and cached.
     * It applies to the query with fetch group.
     */
    public boolean isPartialObject(Object domainObject) {
        if (domainObject != null) {
            FetchGroup fetchGroupInCache = ((FetchGroupTracker)domainObject)._persistence_getFetchGroup();

            //if the fetch group reference is not null, it means the object is partial.
            return (fetchGroupInCache != null);
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return if the cached object data is sufficiently valid against a fetch group
     */
    public boolean isObjectValidForFetchGroup(Object object, FetchGroup fetchGroup) {
        FetchGroup groupInObject = ((FetchGroupTracker)object)._persistence_getFetchGroup();
        return (groupInObject == null) || groupInObject.isSupersetOf(fetchGroup);
    }

    /**
     * INTERNAL:
     * Return true if the cached object data should be written in clone.
     * It is used in Fetch Group case when filling in the clone from the cached object.
     */
    public boolean shouldWriteInto(Object cachedObject, Object clone) {
        FetchGroup fetchGroupInTarg = ((FetchGroupTracker)clone)._persistence_getFetchGroup();
        if (fetchGroupInTarg != null) {
            FetchGroup fetchGroupInSrc = ((FetchGroupTracker)cachedObject)._persistence_getFetchGroup();

            //should write if target's fetch group is not a superset of that of the source,
            //or if refresh is required, should always write (either refresh or revert) data from the cache to the clones.
            return !fetchGroupInTarg.isSupersetOf(fetchGroupInSrc) || ((FetchGroupTracker) cachedObject)._persistence_shouldRefreshFetchGroup();
        }
        return false;
    }

    /**
     * INTERNAL:
     * Write data of the partially fetched object into the working and backup clones
     */
    public void writePartialIntoClones(Object partialObject, Object workingClone, Object backupClone, UnitOfWorkImpl uow) {
        FetchGroup fetchGroupInClone = ((FetchGroupTracker)workingClone)._persistence_getFetchGroup();
        FetchGroup fetchGroupInObject = ((FetchGroupTracker)partialObject)._persistence_getFetchGroup();

        // Update fetch group in clone as the union of two,
        // do this first to avoid fetching during method access.
        EntityFetchGroup union = flatUnionFetchGroups(fetchGroupInObject, fetchGroupInClone, false);// this method is not called for aggregates
        // Finally, update clone's fetch group reference.
        setObjectFetchGroup(workingClone, union, uow);
        if (workingClone != backupClone) {
            setObjectFetchGroup(backupClone, union, uow);
        }
        ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
        // Turn it 'off' to prevent unwanted events.
        policy.dissableEventProcessing(workingClone);
        try {
            //if refresh is set, force to fill in fetch group data
            if (((FetchGroupTracker)partialObject)._persistence_shouldRefreshFetchGroup()) {
                //refresh and fill in the fetch group data
                refreshFetchGroupIntoClones(partialObject, workingClone, backupClone, fetchGroupInObject, fetchGroupInClone, uow);
            } else {//no refresh is enforced
                //revert the unfetched attributes of the clones.
                revertDataIntoUnfetchedAttributesOfClones(partialObject, workingClone, backupClone, fetchGroupInObject, fetchGroupInClone, uow);
            }
        } finally {
            policy.enableEventProcessing(workingClone);
        }
    }

    /**
     * INTERNAL:
     * Refresh the fetch group data into the working and backup clones.
     * This is called if refresh is enforced
     */
    // TODO-244124-dclarke: Needs to be updated to reflect new FetchGroup behaviour
    private void refreshFetchGroupIntoClones(Object cachedObject, Object workingClone, Object backupClone, FetchGroup fetchGroupInObject, FetchGroup fetchGroupInClone, UnitOfWorkImpl uow) {
        Vector mappings = descriptor.getMappings();
        boolean isObjectPartial = (fetchGroupInObject != null);
        Set fetchedAttributes = isObjectPartial ? fetchGroupInObject.getAttributeNames() : null;
        int size = mappings.size();
        for (int index = 0; index < size; index++) {
            DatabaseMapping mapping = (DatabaseMapping)mappings.get(index);
            if ((!isObjectPartial) || ((fetchedAttributes != null) && fetchedAttributes.contains(mapping.getAttributeName()))) {
                // Only refresh the fetched attributes into clones.
                mapping.buildClone(cachedObject, null, workingClone, null, uow);
                if (workingClone != backupClone) {
                    mapping.buildClone(workingClone, null, backupClone, null, uow);
                }
            } else if (mapping.isAggregateObjectMapping()){
                Object attributeValue = mapping.getAttributeValueFromObject(cachedObject);
                Object cloneAttrbute = mapping.getAttributeValueFromObject(workingClone);
                Object backupAttribute = mapping.getAttributeValueFromObject(backupClone);
                if ((cloneAttrbute == null && attributeValue != null) || (cloneAttrbute != null && attributeValue == null)){
                    mapping.buildClone(cachedObject, null, workingClone, null, uow);
                }else if (attributeValue != null && mapping.getReferenceDescriptor().getFetchGroupManager().shouldWriteInto(attributeValue, cloneAttrbute)) {
                    //there might be cases when reverting/refreshing clone is needed.
                    mapping.getReferenceDescriptor().getFetchGroupManager().writePartialIntoClones(attributeValue, cloneAttrbute, backupAttribute, uow);
                }
            }
        }
    }

    /**
     * Revert the clones' unfetched attributes, and leave fetched ones intact.
     */
    private void revertDataIntoUnfetchedAttributesOfClones(Object cachedObject, Object workingClone, Object backupClone, FetchGroup fetchGroupInObject, FetchGroup fetchGroupInClone, UnitOfWorkImpl uow) {
        // Fetched attributes set in working clone.
        Set fetchedAttributesClone = fetchGroupInClone.getAttributeNames();
        // Fetched attributes set in cached object.
        Set fetchedAttributesCached = null;
        if (fetchGroupInObject != null) {
            fetchedAttributesCached = fetchGroupInObject.getAttributeNames();
        }

        for (DatabaseMapping mapping : descriptor.getMappings()) {
            String attributeName = mapping.getAttributeName();
            if ((fetchedAttributesCached == null || fetchedAttributesCached.contains(attributeName)) && !fetchedAttributesClone.contains(attributeName)) {
                mapping.buildClone(cachedObject, null, workingClone, null, uow);
                if (workingClone != backupClone) {
                    mapping.buildClone(workingClone, null, backupClone, null, uow);
                }
            }else if (mapping.isAggregateObjectMapping()){
                if (mapping.getReferenceDescriptor().hasFetchGroupManager()){
                    Object attributeValue = mapping.getAttributeValueFromObject(cachedObject);
                    Object cloneAttrbute = mapping.getAttributeValueFromObject(workingClone);
                    Object backupAttribute = mapping.getAttributeValueFromObject(backupClone);
                    if ((cloneAttrbute == null && attributeValue != null) || (cloneAttrbute != null && attributeValue == null)){
                        mapping.buildClone(cachedObject, null, workingClone, null, uow);
                    }else if (attributeValue != null && mapping.getReferenceDescriptor().getFetchGroupManager().shouldWriteInto(attributeValue, cloneAttrbute)) {
                        //there might be cases when reverting/refreshing clone is needed.
                        mapping.getReferenceDescriptor().getFetchGroupManager().writePartialIntoClones(attributeValue, cloneAttrbute, backupAttribute, uow);
                    }
                }
            }
            // Only revert the attribute which is fetched by the cached object, but not fetched by the clone.
        }
    }

    /**
     * INTERNAL:
     * Copy fetch group reference from the source object to the target
     */
    public void copyAggregateFetchGroupInto(Object source, Object target, Object rootEntity, AbstractSession session) {
        if (isPartialObject(source)) {
            FetchGroup newGroup = ((FetchGroupTracker)source)._persistence_getFetchGroup().clone(); // must clone because original is linked to orig root
            newGroup.setRootEntity((FetchGroupTracker) rootEntity);
            setObjectFetchGroup(target, newGroup, session);
        }
    }

    /**
     * INTERNAL:
     * Copy fetch group reference from the source object to the target
     */
    public void copyFetchGroupInto(Object source, Object target, AbstractSession session) {
        if (isPartialObject(source)) {
            setObjectFetchGroup(target, ((FetchGroupTracker)source)._persistence_getFetchGroup(), session);
        }
    }

    /**
     * INTERNAL:
     * Union the fetch group of the domain object with the new fetch group.
     */
    public void unionEntityFetchGroupIntoObject(Object source, EntityFetchGroup newEntityFetchGroup, AbstractSession session, boolean shouldClone) {
        //this order is important as we need to be merging into the target fetchgroup
        setObjectFetchGroup(source, flatUnionFetchGroups(newEntityFetchGroup, ((FetchGroupTracker)source)._persistence_getFetchGroup(), shouldClone), session);
    }

    /**
     * INTERNAL:
     * Union two fetch groups.
     */
    public FetchGroup unionFetchGroups(FetchGroup first, FetchGroup second) {
        if ((first == null) || (second == null)) {
            return null;
        }

        //return the superset if applied
        if (first == second || first.isSupersetOf(second)) {
            return first;
        } else if (second.isSupersetOf(first)) {
            return second;
        }

        Set<String> unionAttributeNames = new HashSet();
        unionAttributeNames.addAll(first.getAttributeNames());
        unionAttributeNames.addAll(second.getAttributeNames());
        return getEntityFetchGroup(unionAttributeNames);
    }

    /**
     * INTERNAL:
     * Union two fetch groups as EntityFetchGroups.
     * Ignores all nested attributes.
     */
    public EntityFetchGroup flatUnionFetchGroups(FetchGroup first, FetchGroup second, boolean shouldClone) {
        if ((first == null) || (second == null)) {
            return null;
        }

        //return the superset if applied
        if (first == second) {
            return getEntityFetchGroup(first);
        }

        Set<String> unionAttributeNames = new HashSet();
        unionAttributeNames.addAll(first.getAttributeNames());
        unionAttributeNames.addAll(second.getAttributeNames());
        EntityFetchGroup newGroup = getEntityFetchGroup(unionAttributeNames);
        if (shouldClone){
            newGroup = (EntityFetchGroup) newGroup.clone();
            newGroup.setRootEntity(second.getRootEntity());
        }
        return newGroup;
    }

    /**
     * INTERNAL:
     * Reset object attributes to the default values.
     */
    public void reset(Object source) {
        ((FetchGroupTracker)source)._persistence_resetFetchGroup();
    }

    /**
     * INTERNAL:
     * Return FetchGroup held by the object.
     */
    public FetchGroup getObjectFetchGroup(Object domainObject) {
        if (domainObject != null) {
            return ((FetchGroupTracker)domainObject)._persistence_getFetchGroup();
        }
        return null;
    }

    /**
     * INTERNAL:
     * Return FetchGroup held by the object.
     */
    public EntityFetchGroup getObjectEntityFetchGroup(Object domainObject) {
        if (domainObject != null) {
            FetchGroup fetchGroup = ((FetchGroupTracker)domainObject)._persistence_getFetchGroup();
            if(fetchGroup != null) {
                if(fetchGroup.isEntityFetchGroup()) {
                    return (EntityFetchGroup)fetchGroup;
                }
                return getEntityFetchGroup(fetchGroup);
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Set fetch group into the object.
     */
    public void setObjectFetchGroup(Object source, FetchGroup fetchGroup, AbstractSession session) {
        FetchGroupTracker tracker = (FetchGroupTracker)source;
        if(fetchGroup == null) {
            tracker._persistence_setFetchGroup(null);
            tracker._persistence_setSession(null);
        } else {
            if(fetchGroup.isEntityFetchGroup()) {
                // it's EntityFetchGroup - just set it
                tracker._persistence_setFetchGroup(fetchGroup);
                tracker._persistence_setSession(session);
            } else {
                EntityFetchGroup entityFetchGroup = this.getEntityFetchGroup(fetchGroup);
                if(entityFetchGroup != null) {
                    tracker._persistence_setFetchGroup(entityFetchGroup);
                    tracker._persistence_setSession(session);
                } else {
                    tracker._persistence_setFetchGroup(null);
                    tracker._persistence_setSession(null);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Set if the tracked object is fetched from executing a query with or without refresh.
     */
    public void setRefreshOnFetchGroupToObject(Object source, boolean shouldRefreshOnFetchgroup) {
        ((FetchGroupTracker)source)._persistence_setShouldRefreshFetchGroup(shouldRefreshOnFetchgroup);
    }

    /**
     * Return true if the attribute of the object has already been fetched
     */
    public boolean isAttributeFetched(Object entity, String attributeName) {
        FetchGroup fetchGroup = ((FetchGroupTracker) entity)._persistence_getFetchGroup();
        if (fetchGroup == null) {
            return true;
        }
        return fetchGroup.containsAttributeInternal(attributeName);
    }

    /**
     * PUBLIC:
     * Return the referenced descriptor.
     */
    public ClassDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * Set the referenced descriptor.
     */
    public void setDescriptor(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    /**
     * Return true if a fetch group exists for the given group name.
     */
    public boolean hasFetchGroup(String groupName) {
        return getFetchGroups().containsKey(groupName);
    }

    /**
     * INTERNAL: Initialize the fetch groups. XXX-dclarke: added support for
     * reinit the query manager's queries if they exist
     */
    public void initialize(AbstractSession session) throws DescriptorException {
        if (this.entityFetchGroups == null) {
            this.entityFetchGroups = new ConcurrentHashMap();
        }
        if (!(Helper.classImplementsInterface(getDescriptor().getJavaClass(), ClassConstants.FetchGroupTracker_class))) {
            //to use fetch group, the domain class must implement FetchGroupTracker interface
            session.getIntegrityChecker().handleError(DescriptorException.needToImplementFetchGroupTracker(getDescriptor().getJavaClass(), getDescriptor()));
        }
        this.minimalFetchGroup = new FetchGroup();
        this.fullFetchGroup = new FetchGroup();
        for (DatabaseMapping mapping : getDescriptor().getMappings()) {
            String name = mapping.getAttributeName();
            if(mapping.isPrimaryKeyMapping()) {
                this.minimalFetchGroup.addAttribute(name);
            }
            this.fullFetchGroup.addAttribute(name);
        }
        this.idEntityFetchGroup = null;
        if (this.descriptor.isChildDescriptor()) {
            FetchGroupManager parentManager = this.descriptor.getInheritancePolicy().getParentDescriptor().getFetchGroupManager();
            if (parentManager != null) {
                // copy idEntityFetchGroup from the parent
                this.idEntityFetchGroup = parentManager.getIdEntityFetchGroup();
            }
        }
        if (this.idEntityFetchGroup != null) {
            // insert the copied idEntityFetchGroup into the map
            this.entityFetchGroups.put(this.idEntityFetchGroup.getAttributeNames(), this.idEntityFetchGroup);
        } else {
            // currently minimalFetchGroup contains only PrimaryKey - that's what idEntityFetchGroup will consist of.
            this.idEntityFetchGroup = getEntityFetchGroup(this.minimalFetchGroup);
        }
        if(this.descriptor.usesOptimisticLocking()) {
            DatabaseField lockField = this.descriptor.getOptimisticLockingPolicy().getWriteLockField();
            if (lockField != null) {
                DatabaseMapping lockMapping = getDescriptor().getObjectBuilder().getMappingForField(lockField);
                if (lockMapping != null) {
                    String attributeName = lockMapping.getAttributeName();
                    minimalFetchGroup.addAttribute(attributeName);
                }
            }
        }
        // Now minimalFetchGroup contains PrimaryKey plus locking field - getEntityFetchGroup call ensures
        // that corresponding EntityFetchGroup is cached in entityFetchGroups map.
        // Note that the new EntityFetchGroup is not created if there is no locking field.
        getEntityFetchGroup(this.minimalFetchGroup);
    }

    /**
     * INTERNAL:
     * postInitialize called for inheritance children first.
     * That allows to copy defaultFetchGroup from the parent only in case
     * it has been set by user (not automatically generated).
     */
    public void postInitialize(AbstractSession session) throws DescriptorException {
        if (!(Helper.classImplementsInterface(getDescriptor().getJavaClass(), ClassConstants.FetchGroupTracker_class))) {
            // initialize already threw exception here
            return;
        }

        // Create and cache EntityFetchGroups for named fetch groups.
        if(this.fetchGroups != null) {
            Iterator<FetchGroup> it = this.fetchGroups.values().iterator();
            while(it.hasNext()) {
                FetchGroup fetchGroup = it.next();
                prepareAndVerify(fetchGroup);
                getEntityFetchGroup(fetchGroup);
            }
        }

        if(this.defaultFetchGroup == null) {
            // Look up default fetch group set by user on parent descriptors
            if(this.descriptor.isChildDescriptor() && this.shouldUseInheritedDefaultFetchGroup) {
                ClassDescriptor current = this.descriptor;
                while(current.isChildDescriptor()) {
                    ClassDescriptor parent = current.getInheritancePolicy().getParentDescriptor();
                    if (parent.hasFetchGroupManager()) {
                        this.defaultFetchGroup = parent.getFetchGroupManager().getDefaultFetchGroup();
                        if(this.defaultFetchGroup != null) {
                            return;
                        }
                    }
                    current = parent;
                }
            }

            FetchGroup defaultCandidate = new FetchGroup();
            boolean hasLazy = false;
            for (DatabaseMapping mapping : getDescriptor().getMappings()) {
                if (mapping.isForeignReferenceMapping() || (!mapping.isLazy())) {
                    defaultCandidate.addAttribute(mapping.getAttributeName());
                } else {
                    hasLazy = true;
                }
            }
            if(hasLazy) {
                this.defaultFetchGroup = defaultCandidate;
            }
        }
        if(this.defaultFetchGroup != null) {
            prepareAndVerify(this.defaultFetchGroup);
            this.defaultEntityFetchGroup = getEntityFetchGroup(this.defaultFetchGroup);
        }
        initNonReferenceEntityFetchGroup();
    }

    protected void initNonReferenceEntityFetchGroup() {
        FetchGroup nonReferenceFetchGroup = new FetchGroup();
        for (DatabaseMapping mapping : getDescriptor().getMappings()) {
            if(!mapping.isForeignReferenceMapping()) {
                String name = mapping.getAttributeName();
                if(this.defaultEntityFetchGroup == null || this.defaultEntityFetchGroup.containsAttribute(name)) {
                    nonReferenceFetchGroup.addAttribute(name);
                }
            }
        }
        this.addMinimalFetchGroup(nonReferenceFetchGroup);
        this.nonReferenceEntityFetchGroup = getEntityFetchGroup(nonReferenceFetchGroup);
    }

    /**
     * INTERNAL:
     * Clone the fetch group manager.
     */
    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (Exception exception) {
            throw new InternalError(exception.toString());
        }
    }

    /**
     * PUBLIC:
     * Set whether defaultFetchGroup should be copied from the parent if not set.
     */
    public void setShouldUseInheritedDefaultFetchGroup(boolean shouldUseInheritedDefaultFetchGroup) {
        this.shouldUseInheritedDefaultFetchGroup = shouldUseInheritedDefaultFetchGroup;
    }

    /**
     * PUBLIC:
     * Indicates whether defaultFetchGroup should be copied from the parent if not set.
     */
    public boolean shouldUseInheritedDefaultFetchGroup() {
        return this.shouldUseInheritedDefaultFetchGroup;
    }
}
