/*
 * 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
//     ailitchev - Bug 244124 in 2.1 - Add AttributeGroup for nesting and LoadGroup support
package org.eclipse.persistence.queries;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.queries.AttributeItem;
import org.eclipse.persistence.internal.queries.EntityFetchGroup;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.UnitOfWork;

/**
 * A FetchGroup is a performance enhancement that allows a group of attributes
 * of an object to be loaded on demand, which means that the data for an
 * attribute might not loaded from the underlying data source until an explicit
 * access call for the attribute first occurs. It avoids loading all data of the
 * object's attributes, in which the user is interested in only a subset of
 * them. A great deal of caution and careful system use case analysis should be
 * use when using the fetch group feature, as the extra round-trip would well
 * offset the gain from the deferred loading in many cases.
 * <p>
 * FetchGroup usage is only possible when an entity class implements the
 * {@link FetchGroupTracker} interface so that the FetchGroup can be stored in
 * the entity. The entity must also use the provided check methods to ensure the
 * attributes are loaded prior to use. In general this support is enabled
 * through weaving of the entity classes. If an entity class does not implement
 * {@link FetchGroupTracker} no FetchGroup functionality will be supported and
 * attempted use of a FetchGroup in a query will not result in the expected
 * behavior.
 * <p>
 * FetchGroups are defined in 3 ways:
 * <ul>
 * <li>A {@link FetchGroupManager#getDefaultFetchGroup()} is created and stored
 * on the {@link FetchGroupManager} during metadata processing if any of the
 * basic ({@link org.eclipse.persistence.mappings.DirectToFieldMapping
 * DirectToFieldMapping}) are configured to be loaded directly.
 * <li>A named FetchGroup can be defined and added to the
 * {@link FetchGroupManager}. For JPA users this can be accomplished using
 * annotation (@FetchGroup) or in an eclipselink-orm.xml. For JPA and native
 * users named groups can be defined in code and added to the
 * {@link FetchGroupManager#addFetchGroup(FetchGroup)}. Adding named groups in
 * code is typically done in a {@link
 * org.eclipse.persistence.config.DescriptorCustomizer}and should be done
 * before the session is initialized at login. To use a named FetchGroup on a
 * query the native {@link ObjectLevelReadQuery#setFetchGroupName(String)} can
 * be used of for JPA users the {@link
 * org.eclipse.persistence.config.QueryHints#FETCH_GROUP_NAME} an be used.
 * <li>A dynamic FetchGroup can be created within the application and used on a
 * query. For native API usage this is done using
 * {@link ObjectLevelReadQuery#setFetchGroup(FetchGroup)} while JPA users
 * generally use the {@link org.eclipse.persistence.config.QueryHints#FETCH_GROUP}.
 * </ul>
 * <p>
 * When a query is executed only one FetchGroup will be used. The order of
 * precedence is:
 * <ol>
 * <li>If a FetchGroup is specified on a query it will be used.
 * <li>If no FetchGroup is specified but a FetchGroup name is specified and the
 * FetchGroupManager has a group by this name it will be used.
 * <li>If neither a FetchGroup nor a FetchGroup name is specified on the query
 * an the FetchGroupManager has a default group then it will be used.
 * <li>If none of these conditions are met then no FetchGroup will be used when
 * executing a query.
 * </ol><br>
 * <i>Note: This includes the execution of queries to populate lazy and eager
 * relationships.</i>
 * <p>
 * <b>Loading:</b> A FetchGroup can optionally specify that it needs its
 * included relationships loaded. This can be done using
 * {@link #setShouldLoad(boolean)} and {@link #setShouldLoadAll(boolean)} as
 * well as the corresponding configurations in the @FetchGroup annotation and
 * the {@literal <fetch-group>} element in the eclipselink-orm.xml. When this
 * is configured the FetchGroup will also function as a {@link LoadGroup}
 * causing all of its specified relationships to be populated prior to returning
 * the results from the query execution.
 *
 * @see FetchGroupManager
 * @see org.eclipse.persistence.config.QueryHints#FETCH_GROUP QueryHints.FETCH_GROUP
 * @see LoadGroup
 *
 * @author King Wang, dclarke, ailitchev
 * @since TopLink 10.1.3
 */
public class FetchGroup extends AttributeGroup {

    /**
     * Indicates whether this group should be also used as a {@link LoadGroup}
     * when processing the query result.
     */
    private boolean shouldLoad;

    /**
     * Caches the EntityFetch group for this FetchGroup
     */
    protected EntityFetchGroup entityFetchGroup;

    /**
     * Stores a reference to the root entity for an Aggregate Object relationship.
     * This ensures that partially loaded aggregates can be triggered.
     */
    protected FetchGroupTracker rootEntity;

    public FetchGroup() {
        super();
    }

    public FetchGroup(String name) {
        super(name);
    }

    /**
     * INTERNAL:
     * Called on attempt to get value of an attribute that hasn't been fetched yet.
     * Returns an error message in case jakarta.persistence.EntityNotFoundException
     * should be thrown by the calling method,
     * null otherwise.
     * <p>
     * This method is typically only invoked through woven code in the
     * persistence object introduced when {@link FetchGroupTracker} is woven
     * into the entity.
     */
    public String onUnfetchedAttribute(FetchGroupTracker entity, String attributeName) {
        if (rootEntity != null){
            return rootEntity._persistence_getFetchGroup().onUnfetchedAttribute(rootEntity, attributeName);
        }
        ReadObjectQuery query = new ReadObjectQuery(entity);
        query.setShouldUseDefaultFetchGroup(false);
        Session session = entity._persistence_getSession();
        boolean shouldLoadResultIntoSelectionObject = false;
        if (session.isUnitOfWork()) {
            shouldLoadResultIntoSelectionObject = !((UnitOfWork)session).isObjectRegistered(entity);
        } else {
            shouldLoadResultIntoSelectionObject = !session.getIdentityMapAccessor().containsObjectInIdentityMap(entity);
        }
        if (shouldLoadResultIntoSelectionObject) {
            // entity is not in the cache.
            // instead of updating object in the cache update entity directly.
            query.setShouldLoadResultIntoSelectionObject(true);
            // and ignore cache
            query.dontCheckCache();
            query.setShouldMaintainCache(false);
            // To avoid infinite loop clear the fetch group right away.
            entity._persistence_setFetchGroup(null);
            entity._persistence_setSession(null);
        }
        Object result = session.executeQuery(query);
        if (result == null) {
            // the object was not found in the db end exception will be thrown - restore the fetch group back.
            if (shouldLoadResultIntoSelectionObject) {
                entity._persistence_setFetchGroup(this);
                entity._persistence_setSession(session);
            }
            Object[] args = { query.getSelectionId() };
            return ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_reference", args);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Called on attempt to assign value to an attribute that hasn't been fetched yet.
     * Returns an error message in case jakarta.persistence.EntityNotFoundException
     * should be thrown by the calling method,
     * null otherwise.
     * <p>
     * This method is typically only invoked through woven code in the
     * persistence object introduced when {@link FetchGroupTracker} is woven
     * into the entity.
     */
    public String onUnfetchedAttributeForSet(FetchGroupTracker entity, String attributeName) {
        return onUnfetchedAttribute(entity, attributeName);
    }

    /**
     * INTERNAL:
     * @return the rootEntity
     */
    public FetchGroupTracker getRootEntity() {
        return rootEntity;
    }

    /**
     * INTERNAL:
     * @param rootEntity the rootEntity to set
     */
    public void setRootEntity(FetchGroupTracker rootEntity) {
        this.rootEntity = rootEntity;
    }

    /**
     * Configure this group to also act as a {@link LoadGroup} when set to true
     * and load all of the specified relationships so that the entities returned
     * from the query where this group was used have the requested relationships
     * populated. All subsequent attributes added to this group that create a
     * nested group will have this value applied to them.
     *
     * @see #setShouldLoadAll(boolean) to configure #shouldLoad() on
     *      nested groups
     */
    public void setShouldLoad(boolean shouldLoad) {
        this.shouldLoad = shouldLoad;
        if (this.superClassGroup != null){
            ((FetchGroup)this.superClassGroup).setShouldLoad(shouldLoad);
        }else{
            setSubclassShouldLoad(shouldLoad);
        }
    }

    /**
     * passes should load to subclasses.
     *
     * @see #setShouldLoadAll(boolean) to configure #shouldLoad() on
     *      nested groups
     */
    protected void setSubclassShouldLoad(boolean shouldLoad) {
        if (this.subClasses != null){
            for (CoreAttributeGroup group : this.subClasses){
                ((FetchGroup)group).shouldLoad = shouldLoad;
                ((FetchGroup)group).setSubclassShouldLoad(shouldLoad);
            }
        }
    }

    /**
     * Configure this group to also act as a {@link LoadGroup} the same as
     * {@link #setShouldLoad(boolean)}. Additionally this method will apply the
     * provided boolean value to all nested groups already added.
     *
     * @see #setShouldLoad(boolean) to only configure this grup without
     *      effecting existing nested groups.
     */
    public void setShouldLoadAll(boolean shouldLoad) {
        this.setShouldLoad(shouldLoad);
        if(this.hasItems()) {
            Iterator<Map.Entry<String, AttributeItem>> it = getItems().entrySet().iterator();
            while(it.hasNext()) {
                Map.Entry<String, AttributeItem> entry = it.next();
                FetchGroup group = (FetchGroup)entry.getValue().getGroup();
                if(group != null) {
                    group.setShouldLoadAll(shouldLoad);
                }
            }
        }
    }

    /**
     * @return true if this group will be used as a {@link LoadGroup}when
     *         processing the results of a query to force the specified
     *         relationships to be loaded.
     */
    public boolean shouldLoad() {
        return this.shouldLoad;
    }

    @Override
    protected FetchGroup newGroup(String name, CoreAttributeGroup parent) {
        FetchGroup fetchGroup = new FetchGroup(name);
        if(parent != null) {
            fetchGroup.setShouldLoad(((FetchGroup)parent).shouldLoad());
        }
        return fetchGroup;
    }

    @Override
    public boolean isFetchGroup() {
        return true;
    }

    public boolean isEntityFetchGroup() {
        return false;
    }

    /*
     * LoadGroup created with all member groups with shouldLoad set to false dropped.
     */
    public LoadGroup toLoadGroupLoadOnly() {
        return this.toLoadGroup(new HashMap<AttributeGroup, LoadGroup>(), true);
    }

    @Override
    public FetchGroup clone() {
        return (FetchGroup)super.clone();
    }

    @Override
    public LoadGroup toLoadGroup(Map<AttributeGroup, LoadGroup> cloneMap, boolean loadOnly){
        if (loadOnly && !this.shouldLoad){
            return null;
        }
        return super.toLoadGroup(cloneMap, loadOnly);
    }
    /**
     * INTERNAL:
     * Used to retrieve the EntityFetchGroup for this FetchGroup
     * @return the entityFetchGroup
     */
    public EntityFetchGroup getEntityFetchGroup(FetchGroupManager fetchGroupManager) {
        if (this.entityFetchGroup == null){
            this.entityFetchGroup = fetchGroupManager.getEntityFetchGroup(this.getAttributeNames());
        }
        return entityFetchGroup;
    }

    /**
     * Returns FetchGroup corresponding to the passed (possibly nested) attribute.
     */
    @Override
    public FetchGroup getGroup(String attributeNameOrPath) {
        return (FetchGroup)super.getGroup(attributeNameOrPath);
    }

    @Override
    public void addAttribute(String attributeNameOrPath, CoreAttributeGroup group) {
        this.entityFetchGroup = null;
        super.addAttribute(attributeNameOrPath, (group != null ? ((AttributeGroup)group).toFetchGroup() : null));
    }

    @Override
    public void addAttribute(String attributeNameOrPath, Collection<? extends CoreAttributeGroup> groups) {
        this.entityFetchGroup = null;
        super.addAttribute(attributeNameOrPath, groups);
    }

    @Override
    public void addAttributeKey(String attributeNameOrPath, CoreAttributeGroup group) {
        this.entityFetchGroup = null;
        super.addAttributeKey(attributeNameOrPath, (group != null ? ((AttributeGroup)group).toFetchGroup() : null));
    }


}
