/*
 * 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<>());
    }

    /**
     * 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<>(), 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);
    }


}
