/*
 * 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
//     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<DatabaseMapping> 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 = 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<String> 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;
    }
}
