/*
Tiamat - a role-playing game framework
AttributeCollection.java - used to store a collection of attributes
 
 Copyright  (C) 2004 Hugues Johnson
 
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package com.huguesjohnson.tiamat;

import java.util.ArrayList;

/** AttributeCollection - used to store a collection of attributes
 * @author Hugues Johnson
 */
public class AttributeCollection{

/* begin private members */
    private NamedObjectTreeNode rootNode;
/* end private members */

/* begin private constants */
    private final static String ROOT_NAME="ATTRIBUTES";
    private final static String ROOT_DESCRIPTION="Root node for AttributeCollection";
/* end private constants */
    
/* begin constructors */
    /** Default constructor, uses default pathDelimiter.
     */
    public AttributeCollection(){
        this.rootNode=new NamedObjectTreeNode(new Attribute(AttributeCollection.ROOT_NAME,AttributeCollection.ROOT_DESCRIPTION,0));
    }
    /** Create a new AttributeCollection with a custom path delimiter.
     * @param pathDelimiter The new path delimiter to use.
     */
    public AttributeCollection(String pathDelimiter){
        this.rootNode=new NamedObjectTreeNode(new Attribute(AttributeCollection.ROOT_NAME,AttributeCollection.ROOT_DESCRIPTION,0),pathDelimiter);
    }
    /** Create a new AttributeCollection based off an array of Attributes with a the default path delimiter.
     * @param attributes The initial set of attributes to add to the collection.
     */
    public AttributeCollection(Attribute[] attributes){
        this.rootNode=new NamedObjectTreeNode(new Attribute(AttributeCollection.ROOT_NAME,AttributeCollection.ROOT_DESCRIPTION,0));
        int length=attributes.length;
        for(int index=0;index<length;index++){
            NamedObjectTreeNode node=new NamedObjectTreeNode(attributes[index],this.rootNode);
        }
    }
    /** Create a new AttributeCollection based off an array of Attributes with a custom path delimiter.
     * @param attributes The initial set of attributes to add to the collections.
     * @param pathDelimiter The new path delimiter to use.
     */
    public AttributeCollection(Attribute[] attributes,String pathDelimiter){
        this.rootNode=new NamedObjectTreeNode(new Attribute(AttributeCollection.ROOT_NAME,AttributeCollection.ROOT_DESCRIPTION,0),pathDelimiter);
        int length=attributes.length;
        for(int index=0;index<length;index++){
            NamedObjectTreeNode node=new NamedObjectTreeNode(attributes[index],pathDelimiter,this.rootNode);
        }
    }
/* end constructors */
    
/* begin public methods */
    /** Sets the Attribute with the given path, adds it if it doesn’t exist. 
     * @param path The path to this Attribute.
     * @param attribute The Attribute to store.
     */
    public void setAttribute(String path,Attribute attribute){
        TreeNode node=this.rootNode.getChildNode(path+attribute.getName(),true);
        if(node==null){
            NamedObjectTreeNode newNode=new NamedObjectTreeNode(attribute,this.rootNode.getPathDelimiter());
            this.rootNode.insertChildNode(path,newNode);
        } else{
            node.setObject(attribute);
        }
    }
    /** Remove the Attribute with the specified path.
     * @param path The path to the Attribute to remove.
     * @return The success of this operation. 
     */
    public boolean removeAttribute(String path){
        return(this.rootNode.removeChildNode(path,true));
    }
    /** Return the Attribute with the specified path if it exists, otherwise null. 
     * @param path The path to the Attribute to get.
     * @return The Attribute if it's found otherwise null. 
     */
    public Attribute getAttribute(String path){
        Object object=this.rootNode.getChildNode(path,true);
        if(object==null){
            return(null);
        } else if(object instanceof NamedObjectTreeNode){
            Object namedObject=((NamedObjectTreeNode)object).getObject();
            if(namedObject==null){
                return(null);
            } else if(namedObject instanceof Attribute){
                return((Attribute)object);
            } else{ //found something that's not an Attribute, shouldn't happen
                return(null);
            }
        } else{
            return(null);
        }
    }
    /** Returns the total number of Attributes in the collection.
     * @return The total number of Attributes in the collection.
     */
    public int getCount(){
        return(this.rootNode.getChildLeafCount(true));
    }
    /** Returns an array representing all Attributes in the collection.
     * @return An array representing all Attributes in the collection.
     */
    public Attribute[] getAll(){
        TreeNode[] nodes=this.rootNode.getChildLeaves(true);
        int length=nodes.length;
        ArrayList<Attribute> attributeList=new ArrayList<Attribute>(length);
        for(int index=0;index<length;index++){
            Object object=nodes[index].getObject();
            if(object!=null){
                if(object instanceof Attribute){
                    attributeList.add((Attribute)object);
                }
            }
        }
        return(attributeList.toArray(new Attribute[0]));
    }
    /** Returns a string representation of the object.
     * @return A string representation of the object.
     */
    public String toString(){
        StringBuffer tostring=new StringBuffer(this.getClass().getName());
        //tostring.append("\n  member="+this.member);
        return(tostring.toString());
    }
/* end public methods */
}