/* * 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_ELEMENT_H__ #define __DAE_ELEMENT_H__ #include #include #include #include #include #include #include //#ifndef NO_MALLOC_HEADER //#include //#endif namespace COLLADA_TYPE { typedef int TypeEnum; } class DAE; class daeMetaElement; class daeMetaAttribute; class daeDocument; class daeURI; /** * The @c daeElement class represents an instance of a COLLADA "Element"; * it is the main base class for the COLLADA Dom. * Features of this class include: * - Uses factory concepts defined via daeMetaElement * - Composed of attributes, content elements and content values * - Reference counted via daeSmartRef * - Contains information for XML base URI, and XML containing element */ class DLLSPEC daeElement : public daeRefCountedObj { public: /** * Macro that defines new and delete overrides for this class */ DAE_ALLOC protected: daeElement* _parent; daeDocument* _document; daeMetaElement* _meta; daeString _elementName; daeBoolArray _validAttributeArray; // This is now obsolete and can be removed void* _userData; protected: daeElement( const daeElement &cpy ) : daeRefCountedObj() { (void)cpy; }; virtual daeElement &operator=( const daeElement &cpy ) { (void)cpy; return *this; } void init(); // These functions are called internally. void setDocument( daeDocument* c, bool notifyDocument ); daeElement* simpleAdd(daeString name, int index = -1); public: /** * Element Constructor. * @note This should not be used externally. * Use factories to create elements */ daeElement(); /** * Element Constructor. * @note This should not be used externally. * Use factories to create elements */ daeElement(DAE& dae); /** * Element Destructor. * @note This should not be used externally, * if daeSmartRefs are being used. */ virtual ~daeElement(); /** * Sets up a @c daeElement. Called on all @c daeElements as part of their initialization. * @param meta Meta element to use to configure this element. * @note Should not be called externally. */ void setup(daeMetaElement* meta); // These functions are for adding child elements. They return null if adding // the element failed. daeElement* add(daeString name, int index = -1); daeElement* add(daeElement* elt, int index = -1); daeElement* addBefore(daeElement* elt, daeElement* index); daeElement* addAfter(daeElement* elt, daeElement* index); // These functions are deprecated. Use 'add' instead. daeElement* createAndPlace(daeString elementName); daeElement* createAndPlaceAt(daeInt index, daeString elementName); daeBool placeElement(daeElement* element); daeBool placeElementAt(daeInt index, daeElement* element); daeBool placeElementBefore( daeElement* marker, daeElement *element ); daeBool placeElementAfter( daeElement* marker, daeElement *element ); /** * Finds the last index into the array of children of the name specified. * @param elementName The name to look for. * @return Returns the index into the children array of the last element with name elementName. -1 if * there are no children of name elementName. */ daeInt findLastIndexOf( daeString elementName ); /** * Removes the specified element from it parent, the @c this element. * This function is the opposite of @c placeElement(). It removes the specified * element from the _contents array, and from wherever else it appears * inside of the @c this element. Use this function instead of @c clear(), @c remove() or @c delete() * if you want to keep the _contents field up-to-date. * * @param element Element to be removed in the @c this container. * @return Returns true if the element was successfully removed, false otherwise. */ daeBool removeChildElement(daeElement* element); /** * Removes the specified element from its parent element. * This function is the opposite of @c placeElement(). It removes the specified * element from both the _contents array and from wherever else it appears * inside of its parent. The function itself finds the parent, and is defined as a static method, * since removing the element from its parent may result in the deletion of the element. * If the element has no parent, nothing is done. * * Use this function instead of @c clear(), @c remove() or @c delete() * if you want to keep _contents up-to-date. * * @param element Element to remove from its parent container, the function finds the parent element. * @return Returns true if the element was successfully removed, false otherwise. */ static daeBool removeFromParent(daeElement* element) { if(element != NULL && element->_parent != NULL) return(element->_parent->removeChildElement(element)); return false; }; /** * Returns the number of attributes in this element. * @return The number of attributes this element has. */ size_t getAttributeCount(); /** * Returns the daeMetaAttribute object corresponding to the attribute specified. * @param name The name of the attribute to find. * @return Returns the corresponding daeMetaAttribute object or NULL if this element * doesn't have the specified attribute. */ daeMetaAttribute* getAttributeObject(daeString name); /** * Returns the daeMetaAttribute object corresponding to attribute i. * @param i The index of the attribute to find. * @return Returns the corresponding daeMetaAttribute object */ daeMetaAttribute* getAttributeObject(size_t i); /** * Returns the name of the attribute at the specified index. * @param i The index of the attribute whose name should be retrieved. * @return Returns the name of the attribute, or "" if the index is out of range. */ std::string getAttributeName(size_t i); /** * Checks if this element can have the attribute specified. * @param name The name of the attribute to look for. * @return Returns true is this element can have an attribute with the name specified. False otherwise. */ daeBool hasAttribute(daeString name); /** * Checks if an attribute has been set either by being loaded from the COLLADA document or set * programmatically. * @param name The name of the attribute to check. * @return Returns true if the attribute has been set. False if the attribute hasn't been set * or doesn't exist for this element. */ daeBool isAttributeSet(daeString name); /** * Gets an attribute's value as a string. * @param name The name of the attribute. * @return The value of the attribute. Returns an empty string if this element doesn't * have the specified attribute. */ std::string getAttribute(daeString name); /** * Just like the previous method, this method gets an attribute's value as a string. It * takes the string as a reference parameter instead of returning it, for extra efficiency. * @param name The name of the attribute. * @param A string in which to store the value of the attribute. This will be set to an empty * string if this element doesn't have the specified attribute. */ void getAttribute(daeString name, std::string& value); /** * Gets an attribute's value as a string. * @param i The index of the attribute to retrieve. * @return The value of the attribute. */ std::string getAttribute(size_t i); /** * Just like the previous method, this method gets an attribute's value as a string. It * takes the string as a reference parameter instead of returning it, for extra efficiency. * @param i The index of the attribute to retrieve. * @param A string in which to store the value of the attribute. */ void getAttribute(size_t i, std::string& value); struct DLLSPEC attr { attr(); attr(const std::string& name, const std::string& value); std::string name; std::string value; }; /** * Returns an array containing all the attributes of this element. * @return A daeArray of attr objects. */ daeTArray getAttributes(); /** * Just like the previous method, this method returns an array containing all the attributes * of this element. It returns the result via a reference parameter for extra efficiency. * @param attrs The array of attr objects to return. */ void getAttributes(daeTArray& attrs); /** * Sets the attribute to the specified value. * @param name Attribute to set. * @param value Value to apply to the attribute. * @return Returns true if the attribute was found and the value was set, false otherwise. */ virtual daeBool setAttribute(daeString name, daeString value); /** * Sets the attribute at the specified index to the given value. * @param i Index of the attribute to set. * @param value Value to apply to the attribute. * @return Returns true if the attribute was found and the value was set, false otherwise. */ virtual daeBool setAttribute(size_t i, daeString value); /** * Returns the daeMetaAttribute object corresponding to the character data for this element. * @return Returns a daeMetaAttribute object or NULL if this element doesn't have * character data. */ daeMetaAttribute* getCharDataObject(); /** * Checks if this element can have character data. * @return Returns true if this element can have character data, false otherwise. */ daeBool hasCharData(); /** * Returns this element's character data as a string. * @return A string containing this element's character data, or an empty string * if this element can't have character data. */ std::string getCharData(); /** * Similar to the previous method, but fills a string passed in by the user for efficiency. * @param data The string to be filled with this element's character content. The * string is set to an empty string if this element can't have character data. */ void getCharData(std::string& data); /** * Sets this element's character data. * @param data The new character data of this element. * @return Returns true if this element can have character data and the character data * was successfully changed, false otherwise. */ daeBool setCharData(const std::string& data); // These functions are deprecated. daeMemoryRef getAttributeValue(daeString name); // Use getAttribute or getAttributeObject instead. daeBool hasValue(); // Use hasCharData instead. daeMemoryRef getValuePointer(); // Use getCharData or getCharDataObject instead. /** * Finds the database document associated with @c this element. * @return Returns the @c daeDocument representing the containing file or database * group. */ daeDocument* getDocument() const { return _document; } /** * Deprecated. */ daeDocument* getCollection() const { return _document; } /** * Get the associated DAE object. * @return The associated DAE object. */ DAE* getDAE(); /** * Sets the database document associated with this element. * @param c The daeDocument to associate with this element. */ void setDocument(daeDocument* c) { setDocument( c, true ); } /** * Deprecated. */ void setCollection(daeDocument* c ); /** * Gets the URI of the document containing this element, note that this is NOT the URI of the element. * @return Returns a pointer to the daeURI of the document containing this element. */ daeURI* getDocumentURI() const; /** * Creates an element via the element factory system. This creation * is based @em only on potential child elements of this element. * @param elementName Class name of the subelement to create. * @return Returns the created @c daeElement, if it was successfully created. */ daeSmartRef createElement(daeString elementName); /** * Gets the container element for @c this element. * If @c createAndPlace() was used to create the element, its parent is the the caller of @c createAndPlace(). * @return Returns the parent element, if @c this is not the top level element. */ daeElement* getParentElement() { return _parent;} /** * Deprecated. Use getParentElement() * @deprecated */ daeElement* getXMLParentElement() { return _parent;} /** * Sets the parent element for this element. * @param newParent The element which is the new parent element for this element. * @note This function is called internally and not meant to be called form the client application. */ void setParentElement( daeElement *parent ) { _parent = parent; } // These are helper structures to let the xml hierarchy search functions know when we've // found a match. You can implement a custom matcher by inheriting from this structure, // just like matchName and matchType. struct DLLSPEC matchElement { virtual bool operator()(daeElement* elt) const = 0; virtual ~matchElement() { }; }; // Matches an element by name struct DLLSPEC matchName : public matchElement { matchName(daeString name); virtual bool operator()(daeElement* elt) const; std::string name; }; // Matches an element by schema type struct DLLSPEC matchType : public matchElement { matchType(daeInt typeID); virtual bool operator()(daeElement* elt) const; daeInt typeID; }; // Returns a matching child element. By "child", I mean one hierarchy level beneath the // current element. This function is basically the same as getDescendant, except that it // only goes one level deep. daeElement* getChild(const matchElement& matcher); // Performs a breadth-first search and returns a matching descendant element. A "descendant // element" is an element beneath the current element in the xml hierarchy. daeElement* getDescendant(const matchElement& matcher); // Returns the parent element. daeElement* getParent(); // Searches up through the xml hiearchy and returns a matching element. daeElement* getAncestor(const matchElement& matcher); // These functions perform the same as the functions above, except that they take the element // name to match as a string. This makes these functions a little simpler to use if you're // matching based on element name, which is assumed to be the most common case. Instead of // "getChild(matchName(eltName))", you can just write "getChild(eltName)". daeElement* getChild(daeString eltName); daeElement* getDescendant(daeString eltName); daeElement* getAncestor(daeString eltName); /** * Gets the associated Meta information for this element. This * Meta also acts as a factory. See @c daeMetaElement documentation for more * information. * @return Returns the associated meta information. */ inline daeMetaElement* getMeta() { return _meta; } // These functions are deprecated. Use typeID instead. virtual COLLADA_TYPE::TypeEnum getElementType() const { return (COLLADA_TYPE::TypeEnum)0; } daeString getTypeName() const; /** * Returns this element's type ID. Every element is an instance of a type specified in * the Collada schema, and every schema type has a unique ID. * @return The element's type ID. */ virtual daeInt typeID() const = 0; /** * Gets this element's name. * @return Returns the string for the name. * @remarks This function returns NULL if the element's name is identical to it's type's name. */ daeString getElementName() const; /** * Sets this element's name. * @param nm Specifies the string to use as the element's name. * @remarks Use caution when using this function since you can easily create invalid COLLADA documents. */ void setElementName( daeString nm ); /** * Gets the element ID if it exists. * @return Returns the value of the ID attribute, if there is such * an attribute on this element type. * @return the string for the element ID if it exists. */ daeString getID() const; /** * Gets the children/sub-elements of this element. * This is a helper function used to easily access an element's children without the use of the * _meta objects. This function adds the convenience of the _contents array to elements that do * not contain a _contents array. * @return The return value. An elementref array to append this element's children to. */ daeTArray< daeSmartRef > getChildren(); /** * Same as the previous function, but returns the result via a parameter instead * of a return value, for extra efficiency. * @param array The return value. An elementref array to append this element's children to. */ //void getChildren( daeElementRefArray &array ); void getChildren( daeTArray > &array ); /** * Gets all the children of a particular type. * @return An array containing the matching child elements. */ template daeTArray< daeSmartRef > getChildrenByType() { daeTArray< daeSmartRef > result; getChildrenByType(result); return result; } /** * Same as the previous function, but returns the result via a parameter instead * of a return value, for extra efficiency. * @return An array containing the matching child elements. */ template void getChildrenByType(daeTArray< daeSmartRef >& matchingChildren) { matchingChildren.setCount(0); daeTArray< daeSmartRef > children; getChildren(children); for (size_t i = 0; i < children.getCount(); i++) if (children[i]->typeID() == T::ID()) matchingChildren.append((T*)children[i].cast()); } /** * Clones/deep copies this @c daeElement and all of it's subtree. * @param idSuffix A string to append to the copied element's ID, if one exists. * Default is no ID mangling. * @param nameSuffix A string to append to the copied element's name, if one exists. * Default is no name mangling. * @return Returns a @c daeElement smartref of the copy of this element. */ daeSmartRef clone( daeString idSuffix = NULL, daeString nameSuffix = NULL ); // Class for reporting info about element comparisons struct DLLSPEC compareResult { int compareValue; // > 0 if elt1 > elt2, // < 0 if elt1 < elt2, // = 0 if elt1 = elt2 daeElement* elt1; daeElement* elt2; bool nameMismatch; // true if the names didn't match std::string attrMismatch; // The name of the mismatched attribute, or "" if there was no attr mismatch bool charDataMismatch; // true if the char data didn't match bool childCountMismatch; // true if the number of children didn't match compareResult(); std::string format(); // Write to a string }; // Function for doing a generic, recursive comparison of two xml elements. It // also provides a full element ordering, so that you could store elements in // a map or a set. Return val is > 0 if elt1 > elt2, < 0 if elt1 < elt2, and 0 // if elt1 == elt2. static int compare(daeElement& elt1, daeElement& elt2); // Same as the previous function, but returns a full compareResult object. static compareResult compareWithFullResult(daeElement& elt1, daeElement& elt2); /** * Sets the user data pointer attached to this element. * @param data User's custom data to store. */ void setUserData(void* data); /** * Gets the user data pointer attached to this element. * @return User data pointer previously set with setUserData. */ void* getUserData(); public: // This function is called internally static void deleteCMDataArray(daeTArray& cmData); }; #include typedef daeSmartRef daeElementRef; typedef daeSmartRef daeElementConstRef; //#include typedef daeTArray daeElementRefArray; #endif //__DAE_ELEMENT_H__