/*
 * Copyright (c) 2011, 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:
//     ailitchev - Bug 244124 - Added AttributeGroup base class for nesting
//     09 Jan 2013-2.5 Gordon Yorke
//       - 397772: JPA 2.1 Entity Graph Support
package org.eclipse.persistence.queries;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.queries.AttributeItem;
import org.eclipse.persistence.sessions.CopyGroup;

/**
 * <b>Purpose</b>: An AttributeGroup represents a set of mappings and nested
 * AttributeGroups for relationship mappings for an entity type.
 * <b>Responsibilities</b>:
 * <ul>
 * <li>Defines which attributes should be fetched from the database within a
 * {@link FetchGroup}.
 * <li>Define which relationship attributes should be populated in a resulting
 * entity graph within a {@link LoadGroup}
 * <li>Define which attributes should be copied within a {@link CopyGroup}
 * </ul>
 * <p>
 * To reference nested attributes a dot ('.') notation is used to reference
 * related attributes. All attribute names provided are assumed to be correct
 * until processed against the mappings during usage of the group.
 *
 * @see FetchGroup
 * @see LoadGroup
 * @see CopyGroup
 *
 * @author ailitchev
 * @since EclipseLink 2.1
 */
public class AttributeGroup extends CoreAttributeGroup<AttributeItem, ClassDescriptor> implements Serializable, Cloneable {

    public AttributeGroup(String name) {
        this.name = name;
    }

    /**
     * INTERNAL:
     * This constructer is to only be used by EclipseLink internally
     */
    public AttributeGroup(String name, Class type, boolean isValidated) {
        this(name);
        this.type = type;
        this.isValidated = isValidated;

    }

    /*
     * INTERNAL:
     * Used to create an attribute with a name of the class type.
     */
    public AttributeGroup(String name, String type, boolean isValidated) {
        this(name);
        this.typeName = type;
        this.isValidated = isValidated;

    }

    public AttributeGroup() {
        this("");
    }

    /**
     * Add a basic attribute or nested attribute with each String representing
     * an attribute on the path to what needs to be included in the
     * AttributeGroup.
     * <p>
     * Example: <code>
     *    group.addAttribute("firstName", group1);<br>
     *    group.addAttribute("manager.address", group2);
     * </code>
     *
     * Note that existing group corresponding to attributeNameOrPath
     * will be overridden with the passed group.
     *
     * @param attributeNameOrPath
     *            A simple attribute, array or attributes forming a path
     * @param group - an AttributeGroup to be added.
     */
    public void addAttribute(String attributeNameOrPath, AttributeGroup group) {
        super.addAttribute(attributeNameOrPath, group);
    }

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

    /**
     * Return true if this AttributeGroup is a super-set of the passed in
     * AttributeGroup.
     */
    public boolean isSupersetOf(AttributeGroup anotherGroup) {
        return super.isSupersetOf(anotherGroup);
    }

    /**
     * INTERNAL:
     * Lookup the {@link AttributeItem}for the provided attribute name or path.
     *
     * @return item or null
     * @throws IllegalArgumentException if name is not valid attribute name or path
     */
    @Override
    public AttributeItem getItem(String attributeNameOrPath) {
        return super.getItem(attributeNameOrPath);
    }

    /**
     * Subclass may create different types.
     */
    protected AttributeItem newItem(AttributeGroup group, String attrName) {
        return new AttributeItem(group, attrName);
    }

    @Override
    public AttributeGroup findGroup(ClassDescriptor type){
        return (AttributeGroup)super.findGroup(type);
    }

    /**
     * Convert the group to a FetchGroup for usage with queries.
     */
    public FetchGroup toFetchGroup() {
        if (isFetchGroup()) {
            return (FetchGroup) this;
        }
        return toFetchGroup(new HashMap<AttributeGroup, FetchGroup>());
    }

    /**
     * INTERNAL:
     *    This method is used internally when converting to a copy group.
     */

    public FetchGroup toFetchGroup(Map<AttributeGroup, FetchGroup> cloneMap){
        FetchGroup clone = cloneMap.get(this);
        if (clone != null) {
            return clone;
        }
        clone = new FetchGroup(this.name);

        clone.type = this.type;
        clone.typeName = this.typeName;
        clone.isValidated = this.isValidated;
        cloneMap.put(this,clone);
        if (this.superClassGroup != null){
            clone.superClassGroup = ((AttributeGroup)this.superClassGroup).toFetchGroup(cloneMap);
        }
        if (this.allsubclasses != null){
            for (CoreAttributeGroup group : this.allsubclasses.values()){
                clone.getSubClassGroups().put(group.getType(), ((AttributeGroup)group).toFetchGroup(cloneMap));
            }
        }
        if (this.subClasses != null){
            clone.subClasses = new HashSet<>();
            for (CoreAttributeGroup group : this.subClasses){
                clone.subClasses.add(((AttributeGroup)group).toFetchGroup(cloneMap));
            }
        }
        // all attributes and nested groups should be cloned, too
        clone.items = null;
        if (hasItems()) {
            clone.items = new HashMap<>();
            for (AttributeItem item : this.items.values()){
                clone.items.put(item.getAttributeName(), item.toFetchGroup(cloneMap, clone));
            }
        }
        return clone;
    }

    /**
     * INTERNAL:
     *    This method is used internally when converting to a copy group.
     */

    @Override
    public boolean isCopyGroup() {
        return false;
    }

    /**
     * Convert the group to a CopyGroup for usage with the copy() API.
     */
    public CopyGroup toCopyGroup() {
        if (isCopyGroup()) {
            return (CopyGroup) this;
        }
        Map<AttributeGroup, CopyGroup> cloneMap = new IdentityHashMap<>();
        return toCopyGroup(cloneMap, new HashMap<>());
    }

        /**
         * INTERNAL:
         *    This method is used internally when converting to a copy group.
         */

        public CopyGroup toCopyGroup(Map<AttributeGroup, CopyGroup> cloneMap, Map copies){
            CopyGroup clone = cloneMap.get(this);
            if (clone != null) {
                return clone;
            }
            clone = new CopyGroup(this.name);
            clone.cascadeTree();
            clone.setCopies(copies);

            clone.type = this.type;
            clone.typeName = this.typeName;
            clone.isValidated = this.isValidated;
            cloneMap.put(this,clone);

            if (this.allsubclasses != null){
                for (CoreAttributeGroup group : this.allsubclasses.values()){
                    clone.getSubClassGroups().put(group.getType(), ((AttributeGroup)group).toCopyGroup(cloneMap, copies));
                }
            }
            if (this.superClassGroup != null){
                clone.superClassGroup = ((AttributeGroup)this.superClassGroup).toCopyGroup(cloneMap, copies);
            }
            if (this.subClasses != null){
                clone.subClasses = new HashSet<>();
                for (CoreAttributeGroup group : this.subClasses){
                    clone.subClasses.add(((AttributeGroup)group).toCopyGroup(cloneMap, copies));
                }
            }
            // all attributes and nested groups should be cloned, too
            clone.items = null;
            if (hasItems()) {
                clone.items = new HashMap<>();
                for (AttributeItem item : this.items.values()){
                    clone.items.put(item.getAttributeName(), item.toCopyGroup(cloneMap, clone, copies));
                }
            }
            return clone;
        }


    @Override
    public boolean isLoadGroup() {
        return false;
    }

    /**
     * Convert the group to a LoadGroup for usage with queries.
     */
    public LoadGroup toLoadGroup() {
        if (this.isLoadGroup()) {
            return (LoadGroup) this;
        }
        return toLoadGroup(new HashMap<AttributeGroup, LoadGroup>(), false);
    }

    public LoadGroup toLoadGroup(Map<AttributeGroup, LoadGroup> cloneMap, boolean loadOnly){
        LoadGroup clone = cloneMap.get(this);
        if (clone != null) {
            return clone;
        }
        clone = new LoadGroup(this.name);

        clone.type = this.type;
        clone.typeName = this.typeName;
        clone.isValidated = this.isValidated;
        cloneMap.put(this,clone);
        if (this.allsubclasses != null){
            for (CoreAttributeGroup group : this.allsubclasses.values()){
                clone.getSubClassGroups().put(group.getType(), ((AttributeGroup)group).toLoadGroup(cloneMap, loadOnly));
            }
        }
        if (this.superClassGroup != null){
            clone.superClassGroup = ((AttributeGroup)this.superClassGroup).toLoadGroup(cloneMap, loadOnly);
        }
        if (this.subClasses != null){
            clone.subClasses = new HashSet<>();
            for (CoreAttributeGroup group : this.subClasses){
                clone.subClasses.add(((AttributeGroup)group).toLoadGroup(cloneMap, loadOnly));
            }
        }
        // all attributes and nested groups should be cloned, too
        clone.items = null;
        if (hasItems()) {
            clone.items = new HashMap<>();
            for (AttributeItem item : this.items.values()){
                clone.items.put(item.getAttributeName(), item.toLoadGroup(cloneMap, clone, loadOnly));
            }
        }
        return clone;
    }

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

    /**
     * INTERNAL:
     * Only LoadGroups allow concurrency.
     */
    @Override
    public boolean isConcurrent() {
        return false;
    }
    /**
     * Subclass may create different types.
     */
    @Override
    protected AttributeItem newItem(CoreAttributeGroup group, String attrName) {
        return new AttributeItem((AttributeGroup)group, attrName);
    }

    /**
     * Subclass may create different types.
     */
    @Override
    protected AttributeGroup newGroup(String name, CoreAttributeGroup parent) {
        return new AttributeGroup(name);
    }


}
