/*
 * Copyright (c) 1998, 2020 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 {@link #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 {@link #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));
    }


}
