/*
 * 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:
//     Matt MacIvor - 2.5 - initial implementation
package org.eclipse.persistence.core.queries;

import java.io.Serializable;
import java.io.StringWriter;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.persistence.core.descriptors.CoreDescriptor;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.core.queries.CoreAttributeConverter;
import org.eclipse.persistence.internal.helper.StringHelper;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;

/**
 * INTERNAL
 * <b>Purpose</b>: A generic super class for AttributeGroup and other subclasses
 *
 * @see org.eclipse.persistence.queries.AttributeGroup

 * @author Matt MacIvor
 * @since EclipseLink 2.5
 */
public class CoreAttributeGroup<
    ATTRIBUTE_ITEM extends CoreAttributeItem,
    DESCRIPTOR extends CoreDescriptor> implements Serializable, Cloneable {

    /**
     *  Name parts separator. Used in {@link #toStringItems()} method to build output string.
     */
    private static final String FIELD_SEP = ", ";

    private int toStringLoopCount = 0;

    /**
     * Name of the group. This is used in subclasses where the groups are stored
     * and can be used within a query by name as with FetchGroup. For dynamic
     * groups the name has no functional value.
     */
    protected String name;

    /**
     * The name of the class represented by this AttrbuteGroup.  Used to specify overriding
     * groups for subclasses.
     */
    protected String typeName;
    /**
     * The class represented by this AttrbuteGroup.  Used to specify overriding
     * groups for subclasses.
     */
    protected Class type;

    /**
     * To add inheritance support the two following attrbutes are used to create a model of the inheritance tree
     * This attribute points to the parent AttributeGroup of this attribute group.
     */
    protected CoreAttributeGroup superClassGroup;

    /**
     * This attribute references the immediate subclass groups for this attributeGroup.  This is not required but acts
     * as a means to support adding inheritance branches into the an established tree.
     */
    protected transient Set<CoreAttributeGroup> subClasses;

    /**
     * This attribute is used to store all of the classes in this hierarchy keyed by type.  It is used to find the correct graph
     * for polymorphic groups.
     */
    protected Map<Object, CoreAttributeGroup> allsubclasses;

    /**
     * Specified attributes in the group mapped to their AttributeItems
     */
    protected Map<String, ATTRIBUTE_ITEM> items;

    /**
     * Marks this AttributeGroup as having been validated by the builder and does not require further validation
     */
    protected boolean isValidated;

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

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

    }

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

    }

    public CoreAttributeGroup() {
        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");<br>
     *    group.addAttribute("manager.address");
     * </code>
     *
     * @param attributeNameOrPath
     *            A simple attribute, array or attributes forming a path
     */
    public void addAttribute(String attributeNameOrPath) {
        addAttribute(attributeNameOrPath, (CoreAttributeGroup)null);
    }

    /**
     * Add an attribute and the corresponding list of AttributeGroups.
     * Multiple groups are added in the case of inheritance
     *
     * @param attributeNameOrPath
     *            A simple attribute, array or attributes forming a path
     * @param groups - a collection of AttributeGroups to be added.
     */
    public void addAttribute(String attributeNameOrPath, Collection<? extends CoreAttributeGroup> groups) {
        CoreAttributeItem item = getItem(CoreAttributeConverter.convert(attributeNameOrPath), true);
        item.addGroups(groups);
    }

    /**
     * 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, CoreAttributeGroup group) {
        CoreAttributeItem item = getItem(CoreAttributeConverter.convert(attributeNameOrPath), true);
        item.addSubGroup(group);
    }

    /**
     * Add a basic attribute or nested attribute with each String representing
     * the key of an attribute of type Map 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 to a
     *            Map key
     * @param group
     *            - an AttributeGroup to be added.
     */
    public void addAttributeKey(String attributeNameOrPath, CoreAttributeGroup group) {
        CoreAttributeItem item = getItem(CoreAttributeConverter.convert(attributeNameOrPath), true);
        item.addKeyGroup(group);
    }

    /**
     * Add a set of attributes to the group.
     */
    public void addAttributes(Collection<String> attrOrPaths) {
        for (String attr : attrOrPaths) {
            addAttribute(attr);
        }
    }

    @Override
    public CoreAttributeGroup clone() {
       Map<CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>, CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>> cloneMap = new IdentityHashMap<>();
       return clone(cloneMap);
    }

    /**
     * INTERNAL:
     *    This method is used internally in the clone processing.
     */
    public CoreAttributeGroup clone(Map<CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>, CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>> cloneMap){
        CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> clone = cloneMap.get(this);
        if (clone != null) {
            return clone;
        }
        try {
            clone = (CoreAttributeGroup) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);
        }
        clone.name = 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(), group.clone(cloneMap));
            }
        }
        if (this.superClassGroup != null){
            clone.superClassGroup = this.superClassGroup.clone(cloneMap);
        }
        if (this.subClasses != null){
            clone.subClasses = new HashSet<>();
            for (CoreAttributeGroup group : this.subClasses){
                clone.subClasses.add(group.clone(cloneMap));
            }
        }
        // all attributes and nested groups should be cloned, too
        clone.items = null;
        if (hasItems()) {
            clone.items = new HashMap<>();
            for (ATTRIBUTE_ITEM item : this.items.values()){
                clone.items.put(item.getAttributeName(), (ATTRIBUTE_ITEM) item.clone(cloneMap, clone));
            }
        }
        return clone;
    }

    /**
     * Return if the attribute is defined in the group.
     */
    public boolean containsAttribute(String attributeNameOrPath) {
        String[] path = CoreAttributeConverter.convert(attributeNameOrPath);

        if (getItem(path, false) != null){
            return true;
        }
        if (this.hasInheritance() && this.superClassGroup != null){
            return this.superClassGroup.containsAttribute(attributeNameOrPath);
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return if the attribute is defined in the group.
     * Only local attribute names are checked.
     */
    public boolean containsAttributeInternal(String attributeName) {
        if (this.items != null && this.items.containsKey(attributeName)){
            return true;
        }
        if (this.hasInheritance() && this.superClassGroup != null){
            return this.superClassGroup.containsAttributeInternal(attributeName);
        }
        return false;
    }

    /**
     * Convert a provided name or path which could be a single attributeName, a
     * single string with dot separated attribute names, or an array of
     * attribute names defining the path.
     * @throws IllegalArgumentException if name is not valid attribute name or path.
     */
    // Old prototype to keep 2.5 API. Use CoreAttributeConverter.convert internally.
    protected String[] convert(String... nameOrPath) {
        return CoreAttributeConverter.convert(nameOrPath);
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this Descriptor to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    public void convertClassNamesToClasses(ClassLoader classLoader){
        if (this.type == null){
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        this.type = AccessController.doPrivileged(new PrivilegedClassForName<>(this.typeName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(this.typeName, exception.getException());
                    }
                } else {
                    this.type = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(this.typeName, true, classLoader);
                }
            } catch (ClassNotFoundException exc){
                throw ValidationException.classNotFoundWhileConvertingClassNames(this.typeName, exc);
            }
            if (this.items != null){
                for (ATTRIBUTE_ITEM item : this.items.values()){
                    item.convertClassNamesToClasses(classLoader);
                }
            }
            if (this.allsubclasses != null){
                Map<Object, CoreAttributeGroup> allGroups = new HashMap<>();
                this.subClasses = new HashSet<>();
                for (CoreAttributeGroup subClass : allsubclasses.values()){
                    subClass.convertClassNamesToClasses(classLoader);
                    allGroups.put(subClass.getType(), subClass);
                }
                this.allsubclasses = allGroups;
                for (CoreAttributeGroup subClass : allsubclasses.values()){
                    if (CoreAttributeItem.orderInheritance(subClass, allGroups)){
                        this.insertSubClass(subClass);
                    }
                }
            }
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this != obj) {
            if (obj == null) {
                return false;
            }
            CoreAttributeGroup anotherGroup = null;
            try {
                anotherGroup = (CoreAttributeGroup) obj;
            } catch (ClassCastException cce) {
                return false;
            }
            if (hasItems()) {
                if (anotherGroup.hasItems()) {
                    if (!getItems().equals(anotherGroup.getItems())){
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                if (anotherGroup.hasItems()) {
                    return false;
                }
            }
            if (this.superClassGroup != null){
                if (anotherGroup.superClassGroup != null){
                    return this.superClassGroup.equals(anotherGroup.superClassGroup);
                }else{
                    return false;
                }
            }else{
                if (anotherGroup.superClassGroup != null){
                    return false;
                }
                return true;
            }
        } else {
            return true;
        }
    }

    @Override
    public int hashCode() {
        int result = superClassGroup != null ? superClassGroup.hashCode() : 0;
        for (String attribute : getItems().keySet()) {
            // avoid processing values in getItems map to avoid infinite recursion
            // as ATTRIBUTE_ITEM.hashCode() calls group.hashCode()
            result = 31 * result + attribute.hashCode();
        }
        return 31 * result;
    }

    public CoreAttributeGroup findGroup(DESCRIPTOR type){
        if (this.type == null || this.type.equals(type.getJavaClass())){
            return this;
        }
        if (this.hasInheritance()){
            CoreAttributeGroup result = getSubClassGroups().get(type.getJavaClass());
            while (result == null && type.getInheritancePolicy().getParentDescriptor() != null){
                type = (DESCRIPTOR) type.getInheritancePolicy().getParentDescriptor();
                result = getSubClassGroups().get(type.getJavaClass());
            }
            if (result != null){
                return result;
            }
        }
        return this;
    }

    /**
     * INTERNAL:
     */
    public Map<String, ATTRIBUTE_ITEM> getAllItems() {
        Map<String, ATTRIBUTE_ITEM> allItems = new HashMap<>();
        if (this.superClassGroup != null){
            allItems.putAll(this.superClassGroup.getAllItems());
        }
        allItems.putAll(getItems());
        return allItems;
    }

    public Set<String> getAttributeNames() {
        Set<String> attributes = new HashSet<>();

        if (this.superClassGroup != null && this.superClassGroup != this){
            attributes.addAll(this.superClassGroup.getAttributeNames());
        }
        attributes.addAll(getItems().keySet());
        return attributes;
    }

    /**
     * Returns AttributeGroup corresponding to the passed (possibly nested)
     * attribute.
     */
    public CoreAttributeGroup getGroup(String attributeNameOrPath) {
        CoreAttributeItem item = getItem(CoreAttributeConverter.convert(attributeNameOrPath), false);
        if (item != null) {
            return item.getGroup();
        }
        if (hasInheritance()){
            return this.superClassGroup.getGroup(attributeNameOrPath);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Lookup the {@link org.eclipse.persistence.internal.queries.AttributeItem AttributeItem} for the provided attribute name or path.
     *
     * @return item or null
     * @throws IllegalArgumentException if name is not valid attribute name or path
     */
    public ATTRIBUTE_ITEM getItem(String attributeNameOrPath) {
        return getItem(CoreAttributeConverter.convert(attributeNameOrPath), false);
    }

    /**
     * Locate the AttributeGroup where the leaf attribute in the path should be
     * applied to.
     *
     * @param create
     *            indicates if intermediate AttributeGroup required within the
     *            specified path should be created as needed. When checking the
     *            state of the map callers should set this to false to avoid
     *            changing the state unexpectedly
     */
    protected ATTRIBUTE_ITEM getItem(String[] attributePath, boolean create) {
        ATTRIBUTE_ITEM item = null;
        CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> currentGroup = this;

        for (int index = 0; index < attributePath.length; index++) {
            String attrName = attributePath[index];

            item = currentGroup.getItems().get(attrName);

            // Add missing AttributeGroup
            if (item == null) {
                // If not creating missing AttributeGroups then return null
                if (!create) {
                    if (this.superClassGroup != null){
                        return (ATTRIBUTE_ITEM)this.superClassGroup.getItem(attributePath, create);
                    }
                    return null;
                }

                item = (ATTRIBUTE_ITEM)newItem(currentGroup, attrName);
                currentGroup.getItems().put(attrName, item);
            }

            // Add a AttributeGroup if not at the end of the attributes path
            if (item.getGroup() == null && index < (attributePath.length - 1)) {
                if (!create) {
                    return null;
                }
                //XXX-dclarke: Converting the attribute[] into a string and then re-parsing it seems odd
                CoreAttributeGroup newGroup = newGroup(attrName, currentGroup);
                item.setRootGroup(newGroup);
            }

            currentGroup = item.getGroup();
        }

        return item;
    }

    /**
     * INTERNAL:
     * @return Non-null Map of attributes in the group mapped to their AttributeItems
     */
    public Map<String, ATTRIBUTE_ITEM> getItems() {
        if (this.items == null) {
            this.items = new HashMap();
        }
        return this.items;
    }

    public String getName() {
        return this.name;
    }

    /**
     * INTERNAL:
     */
    public Map<Object, CoreAttributeGroup> getSubClassGroups(){
        if (this.allsubclasses == null){
            this.allsubclasses = new HashMap<>();
        }
        return this.allsubclasses;
    }

    public Class getType() {
        return type;
    }

    /**
     * INTERNAL:
     * Returns the name of the type this group represents
     */
    public String getTypeName() {
        return typeName;
    }

    /**
     * Indicates whether this group is part of an inheritance hierarchy
     */
    public boolean hasInheritance(){
        return (this.subClasses != null && !this.subClasses.isEmpty()) || (this.superClassGroup != null);
    }

    /**
     * Indicates whether the group has at least one attribute.
     */
    public boolean hasItems() {
        return this.items != null && !this.items.isEmpty();
    }

    /**
     * INTERNAL:
     * This method will insert the group into the entity hierarchy just below this AttributeGroup.
     */
    public void insertSubClass(CoreAttributeGroup group){
        if (this == group){
            return;
        }
        group.superClassGroup = this;
        if (subClasses != null){
            for (Iterator<CoreAttributeGroup> subClasses = this.subClasses.iterator(); subClasses.hasNext();){
                CoreAttributeGroup subClass = subClasses.next();
                if (group != subClass && group.getType().isAssignableFrom(subClass.getType())){
                    group.subClasses.add(subClass);
                    subClass.superClassGroup = group;
                    subClasses.remove();
                }
            }
        }else{
            this.subClasses = new HashSet<>();
        }
        this.subClasses.add(group);
    }

    /**
     * INTERNAL:
     * Only LoadGroups allow concurrency.
     */
    public boolean isConcurrent() {
        return false;
    }

    /**
     * INTERNAL:
     *    This method is used internally when converting to a copy group.
     */
    public boolean isCopyGroup() {
        return false;
    }

    public boolean isFetchGroup() {
        return false;
    }

    public boolean isLoadGroup() {
        return false;
    }

    /**
     * Return true if this AttributeGroup is a super-set of the passed in
     * AttributeGroup.
     */
    public boolean isSupersetOf(CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> anotherGroup) {
        // TODO: should handle the case when the current group has all
        // attributes - then its equivalent to null
        if (anotherGroup == null) {
            return false;
        }
        if (anotherGroup != this) {
            if (hasItems()) {
                if (anotherGroup.hasItems()) {
                    Iterator<Map.Entry<String, ATTRIBUTE_ITEM>> otherItemEntries = anotherGroup.getItems().entrySet().iterator();
                    while (otherItemEntries.hasNext()) {
                        Map.Entry<String, ATTRIBUTE_ITEM> otherItemEntry = otherItemEntries.next();
                        String otherAttributeName = otherItemEntry.getKey();
                        CoreAttributeItem item = this.items.get(otherAttributeName);
                        if (item == null) {
                            return false;
                        }
                        CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> group = item.getGroup();
                        CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> otherGroup = otherItemEntry.getValue().getGroup();
                        if (group != null) {
                            if (!group.isSupersetOf(otherGroup)) {
                                return false;
                            }
                        } else {
                            if (otherGroup != null) {
                                return true;
                            }
                        }
                        group = item.getKeyGroup();
                        otherGroup = otherItemEntry.getValue().getKeyGroup();
                        if (group != null) {
                            if (!group.isSupersetOf(otherGroup)) {
                                return false;
                            }
                        } else {
                            if (otherGroup != null) {
                                return true;
                            }
                        }
                        if (item.getGroups() != null){
                            if (otherItemEntry.getValue().getGroups() == null){
                                return true;
                            }
                            for (Object next : item.getGroups().values()){
                                CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> element = (CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>)next;
                                CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR> otherElement = (CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>)otherItemEntry.getValue().getGroups().get(element.getType());
                                if (!element.isSupersetOf(otherElement)) {
                                    return false;
                                }
                            }
                        }
                        if (item.getKeyGroups() != null){
                            if (otherItemEntry.getValue().getKeyGroups() == null){
                                return true;
                            }
                            for (Object next : item.getKeyGroups().values()){
                                CoreAttributeGroup element = (CoreAttributeGroup)next;
                                CoreAttributeGroup otherElement = (CoreAttributeGroup)otherItemEntry.getValue().getKeyGroups().get(element.getType());
                                if (!element.isSupersetOf(otherElement)) {
                                    return false;
                                }
                            }
                        }
                    }
                    return true;
                } else {
                    return true;
                }
            } else {
                if (anotherGroup.hasItems()) {
                    return false;
                } else {
                    return true;
                }
            }
        } else {
            return true;
        }
    }

    /**
     * INTERNAL:
     * @return the isValidated
     */
    public boolean isValidated() {
        return isValidated;
    }

    /**
     * Subclass may create different types.
     */
    protected CoreAttributeGroup newGroup(String name, CoreAttributeGroup parent) {
        return new CoreAttributeGroup<ATTRIBUTE_ITEM, DESCRIPTOR>(name);
    }

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

    /**
     * Remove an attribute from the group.
     */
    public void removeAttribute(String attributeNameOrPath) {
        CoreAttributeItem item = getItem(attributeNameOrPath);
        if (item != null) {
            item.getParent().getItems().remove(item.getAttributeName());
        }
    }

    /**
     * INTERNAL:
     *
     */
    public void setAllSubclasses(Map<Object, CoreAttributeGroup> subclasses){
        this.allsubclasses = subclasses;
    }

    // XXX-dclarke: Should this be public?
    public void setAttributeNames(Set attributeNames) {
        Iterator it = attributeNames.iterator();
        while (it.hasNext()) {
            this.addAttribute((String) it.next());
        }
    }

    public void setName(String name) {
        this.name = name;
    }

    //changed for EclipseLink 415779 to avoid stack overflows when using graphs with circular references
    @Override
    public String toString() {
        String className = StringHelper.nonNullString(getClass().getSimpleName());
        String name = StringHelper.nonNullString(getName());
        if (toStringLoopCount >1) {
            return className+StringHelper.LEFT_BRACKET+name+ " Loop detected "+ StringHelper.RIGHT_BRACKET;
        }
        try {
            toStringLoopCount++;
            String items = StringHelper.nonNullString(toStringItems());
            String additionalInfo = StringHelper.nonNullString(toStringAdditionalInfo());
            StringBuilder str = new StringBuilder(className.length() + name.length()
                    + additionalInfo.length() + items.length() + 4);
            str.append(className);
            str.append(StringHelper.LEFT_BRACKET).append(name).append(StringHelper.RIGHT_BRACKET);
            str.append(additionalInfo);
            str.append(StringHelper.LEFT_BRACE).append(items).append(StringHelper.RIGHT_BRACE);
            return str.toString();
        } finally {
            toStringLoopCount--;
        }
    }

    /**
     * Used by toString to print additional info for derived classes.
     */
    protected String toStringAdditionalInfo() {
        return "";
    }

    /**
     * Used by toString to print attribute items.
     */
    protected String toStringItems() {
        // Calculate name length to avoid StringBuilder resizing
        int length = 0;
        String superClassGroupItems;
        if (this.superClassGroup != null) {
            superClassGroupItems = this.superClassGroup.toStringItems();
            length += FIELD_SEP.length();
            length += superClassGroupItems.length();
        } else {
            superClassGroupItems = null;
        }
        Collection<ATTRIBUTE_ITEM> values = null;
        if (this.items != null) {
            values = this.items.values();
            length += (values != null && values.size() > 0
                    ?  (values.size() - 1) * FIELD_SEP.length() : 0);
            if (values != null) {
                for (Iterator<ATTRIBUTE_ITEM> it = values.iterator(); it.hasNext();) {
                    length += it.next().toStringNoClassName().length();
                }
            }
        }
        // Build string to be returned
        StringBuilder str = new StringBuilder(length > 0 ? length : 0);
        if (values != null) {
            for (Iterator<ATTRIBUTE_ITEM> it = values.iterator(); it.hasNext();) {
                str.append(it.next().toStringNoClassName());
                if (it.hasNext()) {
                    str.append(FIELD_SEP);
                }
            }
        }
        if (this.superClassGroup != null) {
            str.append(FIELD_SEP);
            str.append(superClassGroupItems);
        }
        return str.toString();
    }

    static protected String toStringPath(String[] attributePath, int position) {
        StringWriter writer = new StringWriter();
        for (int index = 0; index <= position; index++) {
            writer.write(attributePath[index]);
            if (index < position) {
                writer.write(".");
            }
        }
        return writer.toString();
    }
}
