/*
* Copyright 2006 Sony Computer Entertainment Inc.
*
* Licensed under the MIT Open Source License, for details please see license.txt or the website
* http://www.opensource.org/licenses/mit-license.php
*
*/ 

#ifndef __DAE_META_ELEMENT_ATTRIBUTE_H__
#define __DAE_META_ELEMENT_ATTRIBUTE_H__

#include <dae/daeTypes.h>
#include <dae/daeMetaAttribute.h>
#include <dae/daeMetaCMPolicy.h>

class daeMetaElement;
class daeElement;
class daeDocument;

/**
* The @c daeMetaElementAttribute class represents a content model object that is an element.
*/
class daeMetaElementAttribute : public daeMetaAttribute, public daeMetaCMPolicy
{
public:
	/** The metaElement that describes the element type of this attribute */
	daeMetaElement* 		_elementType;

public:
	/**
	 * Constructor.
	 * @param container The daeMetaElement that this policy object belongs to.
	 * @param parent The daeMetaCMPolicy parent of this policy object.
	 * @param odinal The ordinal value offset of this specific policy object. Used for maintaining the 
	 * correct order of child elements.
	 * @param minO The minimum number of times this CMPolicy object must appear. This value comes from the COLLADA schema.
	 * @param maxO The maximum number of times this CMPolicy object may appear. This value comes from the COLLADA schema.
	 */
	daeMetaElementAttribute( daeMetaElement *container, daeMetaCMPolicy *parent = NULL, daeUInt ordinal = 0, daeInt minO = 1, daeInt maxO = 1);
	/**
	 * Destructor
	 */
	virtual ~daeMetaElementAttribute();

public:

	virtual daeElement *placeElement(daeElement* parent, daeElement* child, daeUInt &ordinal, daeInt offset = 0, daeElement* before = NULL, daeElement *after = NULL);
	virtual daeBool removeElement(daeElement* parent, daeElement* child);

	daeMetaElement *findChild( daeString elementName );

	virtual void getChildren( daeElement* parent, daeElementRefArray &array );

public:
	/**
	 * Sets the element type for the element that this attribute points to.
	 * @param elementType @c daeMetaElement representing the type.
	 */
	void setElementType(daeMetaElement *elementType) {
		_elementType = elementType; }

	/**
	 * Gets the element type for the element that this attribute points to.
	 * @return Returns the @c daeMetaElement representing the type.
	 */
	daeMetaElement* getElementType() { return _elementType; }
	
	/**
	 * Sets the database document associated with this element.
	 * @param parent The daeElement to set the document.
	 * @param c The @c daeDocument to associate with this element.
	 */
	virtual void setDocument(daeElement *parent, daeDocument* c );
	inline void setCollection(daeElement *parent, daeDocument* c ) {
		setDocument( parent, c );
	}

	/**
	 * Gets the number of elements associated with this attribute in instance <tt><i>e.</i></tt> 
	 * @param e Containing element to run the operation on.
	 * @return Returns the number of elements associated with this attribute
	 * in instance <tt><i>e.</i></tt> 
	 */
	virtual daeInt getCount(daeElement* e);

    /// single-arg get() inherited from base class
    using daeMetaAttribute::get;

	/**
	 * Gets an element from containing element <tt><i>e</i></tt> based on <tt><i>index.</i></tt> 
	 * @param e Containing element from which to get the element.
	 * @param index Index of the element to retrieve if indeed
	 * there is an array of elements rather than a singleton.
	 * @return Returns the associated element out of parent element e, based on index, if necessary.
	 */
	virtual daeMemoryRef get(daeElement* e, daeInt index);

	/**
	 * Defines the override version of base method.
	 * @param element Element on which to set this attribute.
	 * @param s String containing the value to be converted via the
	 * atomic type system.
	 */
	virtual void set(daeElement* element, daeString s);
	/**
	 * Defines the override version of base method.
	 * @param toElement Pointer to a @c daeElement to copy this attribute to.
	 * @param fromElement Pointer to a @c daeElement to copy this attribute from.
	 */
	virtual void copy(daeElement* toElement, daeElement* fromElement);

	/**
	 * Gets if this attribute is an array attribute.
	 * @return Returns true if this attribute is an array type.
	 */
	virtual daeBool isArrayAttribute()		{ return false; }
};
typedef daeSmartRef<daeMetaElementAttribute> daeMetaElementAttributeRef;
typedef daeTArray<daeMetaElementAttributeRef> daeMetaElementAttributeArray;


/**
 * The @c daeMetaElementArrayAttribute class is similar to daeMetaElementAttribute 
 * except that this meta attribute describes an array of elements rather than a singleton.
 */
class daeMetaElementArrayAttribute : public daeMetaElementAttribute
{
public:
	/**
	 * Constructor.
	 * @param container The daeMetaElement that this policy object belongs to.
	 * @param parent The daeMetaCMPolicy parent of this policy object.
	 * @param odinal The ordinal value offset of this specific policy object. Used for maintaining the 
	 * correct order of child elements.
	 * @param minO The minimum number of times this CMPolicy object must appear. This value comes from the COLLADA schema.
	 * @param maxO The maximum number of times this CMPolicy object may appear. This value comes from the COLLADA schema.
	 */
	daeMetaElementArrayAttribute(daeMetaElement *container, daeMetaCMPolicy *parent = NULL, daeUInt ordinal = 0, daeInt minO = 1, daeInt maxO = 1);
	~daeMetaElementArrayAttribute();
public:
	virtual daeElement *placeElement(daeElement* parent, daeElement* child, daeUInt &ordinal, daeInt offset = 0, daeElement* before = NULL, daeElement *after = NULL);
	virtual daeBool removeElement(daeElement* parent, daeElement* child);

	void getChildren( daeElement* parent, daeElementRefArray &array );

	/**
	 * Sets the database document associated with this element.
	 * @param c The @c daeDocument to associate with this element.
	 */
	virtual void setDocument(daeElement *parent, daeDocument* c );
	inline void setCollection(daeElement *parent, daeDocument* c ) {
		setDocument( parent, c );
	}

	/**
	 * Defines the override version of this method from @c daeMetaElement.
	 * @param e Containing element to run the operation on.
	 * @return Returns the number of particles associated with this attribute
	 * in instance <tt><i>e.</i></tt> 
	 */
	virtual daeInt getCount(daeElement* e);
	/**
	 * Defines the override version of this method from @c daeMetaElement.
	 * @param e Containing element from which to get the element.
	 * @param index Index of the particle to retrieve if indeed
	 * there is an array of elements rather than a singleton.
	 * @return Returns the associated particle out of parent element e, based on index, if necessary.
	 */
	virtual daeMemoryRef get(daeElement* e, daeInt index);
	/**
	 * Defines the override version of this method from @c daeMetaElement.
	 * @param toElement Pointer to a @c daeElement to copy this attribute to.
	 * @param fromElement Pointer to a @c daeElement to copy this attribute from.
	 */
	virtual void copy(daeElement* toElement, daeElement* fromElement);

	/**
	 * Gets if this attribute is an array attribute.
	 * @return Returns true if this attribute is an array type.
	 */
	virtual daeBool isArrayAttribute()		{ return true; }
};
typedef daeSmartRef<daeMetaElementArrayAttribute> daeMetaElementArrayAttributeRef;
typedef daeTArray<daeMetaElementArrayAttributeRef> daeMetaElementArrayAttributeArray;

#endif

