Home | History | Annotate | Download | only in dae
      1 /*
      2 * Copyright 2006 Sony Computer Entertainment Inc.
      3 *
      4 * Licensed under the MIT Open Source License, for details please see license.txt or the website
      5 * http://www.opensource.org/licenses/mit-license.php
      6 *
      7 */
      8 
      9 #ifndef __DAE_ELEMENT_H__
     10 #define __DAE_ELEMENT_H__
     11 #include <string>
     12 #include <dae/daeTypes.h>
     13 #include <dae/daeMemorySystem.h>
     14 #include <wchar.h>
     15 #include <dae/daeArray.h>
     16 #include <dae/daeRefCountedObj.h>
     17 #include <dae/daeSmartRef.h>
     18 
     19 //#ifndef NO_MALLOC_HEADER
     20 //#include <malloc.h>
     21 //#endif
     22 
     23 namespace COLLADA_TYPE
     24 {
     25 	typedef int TypeEnum;
     26 }
     27 
     28 class DAE;
     29 class daeMetaElement;
     30 class daeMetaAttribute;
     31 class daeDocument;
     32 class daeURI;
     33 
     34 /**
     35  * The @c daeElement class represents an instance of a COLLADA "Element";
     36  * it is the main base class for the COLLADA Dom.
     37  * Features of this class include:
     38  * - Uses factory concepts defined via daeMetaElement
     39  * - Composed of attributes, content elements and content values
     40  * - Reference counted via daeSmartRef
     41  * - Contains information for XML base URI, and XML containing element
     42  */
     43 class DLLSPEC daeElement : public daeRefCountedObj
     44 {
     45 public:
     46 	/**
     47 	 * Macro that defines new and delete overrides for this class
     48 	 */
     49 	DAE_ALLOC
     50 protected:
     51 	daeElement* _parent;
     52 	daeDocument* _document;
     53 	daeMetaElement* _meta;
     54 	daeString _elementName;
     55 	daeBoolArray _validAttributeArray; // This is now obsolete and can be removed
     56 	void* _userData;
     57 
     58 protected:
     59 	daeElement( const daeElement &cpy ) : daeRefCountedObj() { (void)cpy; };
     60 	virtual daeElement &operator=( const daeElement &cpy ) { (void)cpy; return *this; }
     61 
     62 	void init();
     63 
     64 	// These functions are called internally.
     65 	void setDocument( daeDocument* c, bool notifyDocument );
     66 	daeElement* simpleAdd(daeString name, int index = -1);
     67 
     68 public:
     69 	/**
     70 	 * Element Constructor.
     71 	 * @note This should not be used externally.
     72 	 * Use factories to create elements
     73 	 */
     74 	daeElement();
     75 	/**
     76 	 * Element Constructor.
     77 	 * @note This should not be used externally.
     78 	 * Use factories to create elements
     79 	 */
     80 	daeElement(DAE& dae);
     81 
     82 	/**
     83 	 * Element Destructor.
     84 	 * @note This should not be used externally,
     85 	 * if daeSmartRefs are being used.
     86 	 */
     87 	virtual ~daeElement();
     88 
     89 	/**
     90 	 * Sets up a @c daeElement. Called on all @c daeElements as part of their initialization.
     91 	 * @param meta Meta element to use to configure this element.
     92 	 * @note Should not be called externally.
     93 	 */
     94 	void setup(daeMetaElement* meta);
     95 
     96 	// These functions are for adding child elements. They return null if adding
     97 	// the element failed.
     98 	daeElement* add(daeString name, int index = -1);
     99 	daeElement* add(daeElement* elt, int index = -1);
    100 	daeElement* addBefore(daeElement* elt, daeElement* index);
    101 	daeElement* addAfter(daeElement* elt, daeElement* index);
    102 
    103 	// These functions are deprecated. Use 'add' instead.
    104 	daeElement* createAndPlace(daeString elementName);
    105 	daeElement* createAndPlaceAt(daeInt index, daeString elementName);
    106 	daeBool placeElement(daeElement* element);
    107 	daeBool placeElementAt(daeInt index, daeElement* element);
    108 	daeBool placeElementBefore( daeElement* marker, daeElement *element );
    109 	daeBool placeElementAfter( daeElement* marker, daeElement *element );
    110 
    111 	/**
    112 	 * Finds the last index into the array of children of the name specified.
    113 	 * @param elementName The name to look for.
    114 	 * @return Returns the index into the children array of the last element with name elementName. -1 if
    115 	 *         there are no children of name elementName.
    116 	 */
    117 	daeInt findLastIndexOf( daeString elementName );
    118 
    119 	/**
    120 	 * Removes the specified element from it parent, the @c this element.
    121 	 * This function is the opposite of @c placeElement().  It removes the specified
    122 	 * element from the <tt><i> _contents </i></tt> array, and from wherever else it appears
    123 	 * inside of the @c this element.  Use this function instead of @c clear(), @c remove() or @c delete()
    124 	 * if you want to keep the <tt><i> _contents </i></tt> field up-to-date.
    125 	 *
    126 	 * @param element Element to be removed in the @c this container.
    127 	 * @return Returns true if the element was successfully removed, false otherwise.
    128 	 */
    129 	daeBool removeChildElement(daeElement* element);
    130 
    131 	/**
    132 	 * Removes the specified element from its parent element.
    133 	 * This function is the opposite of @c placeElement().  It removes the specified
    134 	 * element from both the <tt><i> _contents </i></tt> array and from wherever else it appears
    135 	 * inside of its parent. The function itself finds the parent, and is defined as a static method,
    136 	 * since removing the element from its parent may result in the deletion of the element.
    137 	 * If the element has no parent, nothing is done.
    138 	 *
    139 	 * Use this function instead of @c clear(), @c remove() or @c delete()
    140 	 * if you want to keep <tt><i> _contents </i></tt> up-to-date.
    141 	 *
    142 	 * @param element Element to remove from its parent container, the function finds the parent element.
    143 	 * @return Returns true if the element was successfully removed, false otherwise.
    144 	 */
    145 	static daeBool removeFromParent(daeElement* element)
    146 	{
    147 		if(element != NULL && element->_parent != NULL)
    148 			return(element->_parent->removeChildElement(element));
    149 		return false;
    150 	};
    151 
    152 	/**
    153 	 * Returns the number of attributes in this element.
    154 	 * @return The number of attributes this element has.
    155 	 */
    156 	size_t getAttributeCount();
    157 
    158 	/**
    159 	 * Returns the daeMetaAttribute object corresponding to the attribute specified.
    160 	 * @param name The name of the attribute to find.
    161 	 * @return Returns the corresponding daeMetaAttribute object or NULL if this element
    162 	 * doesn't have the specified attribute.
    163 	 */
    164 	daeMetaAttribute* getAttributeObject(daeString name);
    165 
    166 	/**
    167 	 * Returns the daeMetaAttribute object corresponding to attribute i.
    168 	 * @param i The index of the attribute to find.
    169 	 * @return Returns the corresponding daeMetaAttribute object
    170 	 */
    171 	daeMetaAttribute* getAttributeObject(size_t i);
    172 
    173 	/**
    174 	 * Returns the name of the attribute at the specified index.
    175 	 * @param i The index of the attribute whose name should be retrieved.
    176 	 * @return Returns the name of the attribute, or "" if the index is out of range.
    177 	 */
    178 	std::string getAttributeName(size_t i);
    179 
    180 	/**
    181 	 * Checks if this element can have the attribute specified.
    182 	 * @param name The name of the attribute to look for.
    183 	 * @return Returns true is this element can have an attribute with the name specified. False otherwise.
    184 	 */
    185 	daeBool hasAttribute(daeString name);
    186 
    187 	/**
    188 	 * Checks if an attribute has been set either by being loaded from the COLLADA document or set
    189 	 * programmatically.
    190 	 * @param name The name of the attribute to check.
    191 	 * @return Returns true if the attribute has been set. False if the attribute hasn't been set
    192 	 * or doesn't exist for this element.
    193 	 */
    194 	daeBool isAttributeSet(daeString name);
    195 
    196 	/**
    197 	 * Gets an attribute's value as a string.
    198 	 * @param name The name of the attribute.
    199 	 * @return The value of the attribute. Returns an empty string if this element doesn't
    200 	 * have the specified attribute.
    201 	 */
    202 	std::string getAttribute(daeString name);
    203 
    204 	/**
    205 	 * Just like the previous method, this method gets an attribute's value as a string. It
    206 	 * takes the string as a reference parameter instead of returning it, for extra efficiency.
    207 	 * @param name The name of the attribute.
    208 	 * @param A string in which to store the value of the attribute. This will be set to an empty
    209 	 * string if this element doesn't have the specified attribute.
    210 	 */
    211 	void getAttribute(daeString name, std::string& value);
    212 
    213 	/**
    214 	 * Gets an attribute's value as a string.
    215 	 * @param i The index of the attribute to retrieve.
    216 	 * @return The value of the attribute.
    217 	 */
    218 	std::string getAttribute(size_t i);
    219 
    220 	/**
    221 	 * Just like the previous method, this method gets an attribute's value as a string. It
    222 	 * takes the string as a reference parameter instead of returning it, for extra efficiency.
    223 	 * @param i The index of the attribute to retrieve.
    224 	 * @param A string in which to store the value of the attribute.
    225 	 */
    226 	void getAttribute(size_t i, std::string& value);
    227 
    228 	struct DLLSPEC attr {
    229 		attr();
    230 		attr(const std::string& name, const std::string& value);
    231 
    232 		std::string name;
    233 		std::string value;
    234 	};
    235 
    236 	/**
    237 	 * Returns an array containing all the attributes of this element.
    238 	 * @return A daeArray of attr objects.
    239 	 */
    240 	daeTArray<attr> getAttributes();
    241 
    242 	/**
    243 	 * Just like the previous method, this method returns an array containing all the attributes
    244 	 * of this element. It returns the result via a reference parameter for extra efficiency.
    245 	 * @param attrs The array of attr objects to return.
    246 	 */
    247 	void getAttributes(daeTArray<attr>& attrs);
    248 
    249 	/**
    250 	 * Sets the attribute to the specified value.
    251 	 * @param name Attribute to set.
    252 	 * @param value Value to apply to the attribute.
    253 	 * @return Returns true if the attribute was found and the value was set, false otherwise.
    254 	 */
    255 	virtual daeBool setAttribute(daeString name, daeString value);
    256 
    257 	/**
    258 	 * Sets the attribute at the specified index to the given value.
    259 	 * @param i Index of the attribute to set.
    260 	 * @param value Value to apply to the attribute.
    261 	 * @return Returns true if the attribute was found and the value was set, false otherwise.
    262 	 */
    263 	virtual daeBool setAttribute(size_t i, daeString value);
    264 
    265 	/**
    266 	 * Returns the daeMetaAttribute object corresponding to the character data for this element.
    267 	 * @return Returns a daeMetaAttribute object or NULL if this element doesn't have
    268 	 * character data.
    269 	 */
    270 	daeMetaAttribute* getCharDataObject();
    271 
    272 	/**
    273 	 * Checks if this element can have character data.
    274 	 * @return Returns true if this element can have character data, false otherwise.
    275 	 */
    276 	daeBool hasCharData();
    277 
    278 	/**
    279 	 * Returns this element's character data as a string.
    280 	 * @return A string containing this element's character data, or an empty string
    281 	 * if this element can't have character data.
    282 	 */
    283 	std::string getCharData();
    284 
    285 	/**
    286 	 * Similar to the previous method, but fills a string passed in by the user for efficiency.
    287 	 * @param data The string to be filled with this element's character content. The
    288 	 * string is set to an empty string if this element can't have character data.
    289 	 */
    290 	void getCharData(std::string& data);
    291 
    292 	/**
    293 	 * Sets this element's character data.
    294 	 * @param data The new character data of this element.
    295 	 * @return Returns true if this element can have character data and the character data
    296 	 * was successfully changed, false otherwise.
    297 	 */
    298 	daeBool setCharData(const std::string& data);
    299 
    300 	// These functions are deprecated.
    301 	daeMemoryRef getAttributeValue(daeString name); // Use getAttribute or getAttributeObject instead.
    302 	daeBool hasValue(); // Use hasCharData instead.
    303 	daeMemoryRef getValuePointer(); // Use getCharData or getCharDataObject instead.
    304 
    305 	/**
    306 	 * Finds the database document associated with @c this element.
    307 	 * @return Returns the @c daeDocument representing the containing file or database
    308 	 * group.
    309 	 */
    310 	daeDocument* getDocument() const { return _document; }
    311 
    312 	/**
    313 	 * Deprecated.
    314 	 */
    315 	daeDocument* getCollection() const { return _document; }
    316 
    317 	/**
    318 	 * Get the associated DAE object.
    319 	 * @return The associated DAE object.
    320 	 */
    321 	DAE* getDAE();
    322 
    323 	/**
    324 	 * Sets the database document associated with this element.
    325 	 * @param c The daeDocument to associate with this element.
    326 	 */
    327 	void setDocument(daeDocument* c) { setDocument( c, true ); }
    328 	/**
    329 	 * Deprecated.
    330 	 */
    331 	void setCollection(daeDocument* c );
    332 
    333 	/**
    334 	 * Gets the URI of the document containing this element, note that this is NOT the URI of the element.
    335 	 * @return Returns a pointer to the daeURI of the document containing this element.
    336 	 */
    337 	daeURI*	getDocumentURI() const;
    338 
    339 	/**
    340 	 * Creates an element via the element factory system.  This creation
    341 	 * is based @em only on potential child elements of this element.
    342 	 * @param elementName Class name of the subelement to create.
    343 	 * @return Returns the created @c daeElement, if it was successfully created.
    344 	 */
    345 	daeSmartRef<daeElement> createElement(daeString elementName);
    346 
    347 	/**
    348 	 * Gets the container element for @c this element.
    349 	 * If @c createAndPlace() was used to create the element, its parent is the the caller of @c createAndPlace().
    350 	 * @return Returns the parent element, if @c this is not the top level element.
    351 	 */
    352 	daeElement* getParentElement() { return _parent;}
    353 	/**
    354 	 * Deprecated. Use getParentElement()
    355 	 * @deprecated
    356 	 */
    357 	daeElement* getXMLParentElement() { return _parent;}
    358 	/**
    359 	 * Sets the parent element for this element.
    360 	 * @param newParent The element which is the new parent element for this element.
    361 	 * @note This function is called internally and not meant to be called form the client application.
    362 	 */
    363 	void setParentElement( daeElement *parent ) { _parent = parent; }
    364 
    365 	// These are helper structures to let the xml hierarchy search functions know when we've
    366 	// found a match. You can implement a custom matcher by inheriting from this structure,
    367 	// just like matchName and matchType.
    368 	struct DLLSPEC matchElement {
    369 		virtual bool operator()(daeElement* elt) const = 0;
    370 		virtual ~matchElement() { };
    371 	};
    372 
    373 	// Matches an element by name
    374 	struct DLLSPEC matchName : public matchElement {
    375 		matchName(daeString name);
    376 		virtual bool operator()(daeElement* elt) const;
    377 		std::string name;
    378 	};
    379 
    380 	// Matches an element by schema type
    381 	struct DLLSPEC matchType : public matchElement {
    382 		matchType(daeInt typeID);
    383 		virtual bool operator()(daeElement* elt) const;
    384 		daeInt typeID;
    385 	};
    386 
    387 	// Returns a matching child element. By "child", I mean one hierarchy level beneath the
    388 	// current element. This function is basically the same as getDescendant, except that it
    389 	// only goes one level deep.
    390 	daeElement* getChild(const matchElement& matcher);
    391 
    392 	// Performs a breadth-first search and returns a matching descendant element. A "descendant
    393 	// element" is an element beneath the current element in the xml hierarchy.
    394 	daeElement* getDescendant(const matchElement& matcher);
    395 
    396 	// Returns the parent element.
    397 	daeElement* getParent();
    398 
    399 	// Searches up through the xml hiearchy and returns a matching element.
    400 	daeElement* getAncestor(const matchElement& matcher);
    401 
    402 	// These functions perform the same as the functions above, except that they take the element
    403 	// name to match as a string. This makes these functions a little simpler to use if you're
    404 	// matching based on element name, which is assumed to be the most common case. Instead of
    405 	// "getChild(matchName(eltName))", you can just write "getChild(eltName)".
    406 	daeElement* getChild(daeString eltName);
    407 	daeElement* getDescendant(daeString eltName);
    408 	daeElement* getAncestor(daeString eltName);
    409 
    410 	/**
    411 	 * Gets the associated Meta information for this element.  This
    412 	 * Meta also acts as a factory.  See @c daeMetaElement documentation for more
    413 	 * information.
    414 	 * @return Returns the associated meta information.
    415 	 */
    416 	inline daeMetaElement* getMeta() { return _meta; }
    417 
    418 	// These functions are deprecated. Use typeID instead.
    419 	virtual COLLADA_TYPE::TypeEnum getElementType() const { return (COLLADA_TYPE::TypeEnum)0; }
    420 	daeString getTypeName() const;
    421 
    422 	/**
    423 	 * Returns this element's type ID. Every element is an instance of a type specified in
    424 	 * the Collada schema, and every schema type has a unique ID.
    425 	 * @return The element's type ID.
    426 	 */
    427 	virtual daeInt typeID() const = 0;
    428 
    429 	/**
    430 	 * Gets this element's name.
    431 	 * @return Returns the string for the name.
    432 	 * @remarks This function returns NULL if the element's name is identical to it's type's name.
    433 	 */
    434 	daeString getElementName() const;
    435 	/**
    436 	 * Sets this element's name.
    437 	 * @param nm Specifies the string to use as the element's name.
    438 	 * @remarks Use caution when using this function since you can easily create invalid COLLADA documents.
    439 	 */
    440 	void setElementName( daeString nm );
    441 
    442 	/**
    443 	 * Gets the element ID if it exists.
    444 	 * @return Returns the value of the ID attribute, if there is such
    445 	 * an attribute on this element type.
    446 	 * @return the string for the element ID if it exists.
    447 	 */
    448 	daeString getID() const;
    449 
    450 	/**
    451 	 * Gets the children/sub-elements of this element.
    452 	 * This is a helper function used to easily access an element's children without the use of the
    453 	 * _meta objects.  This function adds the convenience of the _contents array to elements that do
    454 	 * not contain a _contents array.
    455 	 * @return The return value.  An elementref array to append this element's children to.
    456 	 */
    457 	daeTArray< daeSmartRef<daeElement> > getChildren();
    458 
    459 	/**
    460 	 * Same as the previous function, but returns the result via a parameter instead
    461 	 * of a return value, for extra efficiency.
    462 	 * @param array The return value.  An elementref array to append this element's children to.
    463 	 */
    464 	//void getChildren( daeElementRefArray &array );
    465 	void getChildren( daeTArray<daeSmartRef<daeElement> > &array );
    466 
    467 	/**
    468 	 * Gets all the children of a particular type.
    469 	 * @return An array containing the matching child elements.
    470 	 */
    471 	template<typename T>
    472 	daeTArray< daeSmartRef<T> > getChildrenByType() {
    473 		daeTArray< daeSmartRef<T> > result;
    474 		getChildrenByType(result);
    475 		return result;
    476 	}
    477 
    478 	/**
    479 	 * Same as the previous function, but returns the result via a parameter instead
    480 	 * of a return value, for extra efficiency.
    481 	 * @return An array containing the matching child elements.
    482 	 */
    483 	template<typename T>
    484 	void getChildrenByType(daeTArray< daeSmartRef<T> >& matchingChildren) {
    485 		matchingChildren.setCount(0);
    486 		daeTArray< daeSmartRef<daeElement> > children;
    487 		getChildren(children);
    488 		for (size_t i = 0; i < children.getCount(); i++)
    489 			if (children[i]->typeID() == T::ID())
    490 				matchingChildren.append((T*)children[i].cast());
    491 	}
    492 
    493 	/**
    494 	 * Clones/deep copies this @c daeElement and all of it's subtree.
    495 	 * @param idSuffix A string to append to the copied element's ID, if one exists.
    496 	 *        Default is no ID mangling.
    497 	 * @param nameSuffix A string to append to the copied element's name, if one exists.
    498 	 *        Default is no name mangling.
    499 	 * @return Returns a @c daeElement smartref of the copy of this element.
    500 	 */
    501 	daeSmartRef<daeElement> clone( daeString idSuffix = NULL, daeString nameSuffix = NULL );
    502 
    503 	// Class for reporting info about element comparisons
    504 	struct DLLSPEC compareResult {
    505 		int compareValue; // > 0 if elt1 > elt2,
    506 		                  // < 0 if elt1 < elt2,
    507 		                  // = 0 if elt1 = elt2
    508 		daeElement* elt1;
    509 		daeElement* elt2;
    510 		bool nameMismatch; // true if the names didn't match
    511 		std::string attrMismatch; // The name of the mismatched attribute, or "" if there was no attr mismatch
    512 		bool charDataMismatch; // true if the char data didn't match
    513 		bool childCountMismatch; // true if the number of children didn't match
    514 
    515 		compareResult();
    516 		std::string format(); // Write to a string
    517 	};
    518 
    519 	// Function for doing a generic, recursive comparison of two xml elements. It
    520 	// also provides a full element ordering, so that you could store elements in
    521 	// a map or a set. Return val is > 0 if elt1 > elt2, < 0 if elt1 < elt2, and 0
    522 	// if elt1 == elt2.
    523 	static int compare(daeElement& elt1, daeElement& elt2);
    524 
    525 	// Same as the previous function, but returns a full compareResult object.
    526 	static compareResult compareWithFullResult(daeElement& elt1, daeElement& elt2);
    527 
    528 	/**
    529 	 * Sets the user data pointer attached to this element.
    530 	 * @param data User's custom data to store.
    531 	 */
    532 	void setUserData(void* data);
    533 
    534 	/**
    535 	 * Gets the user data pointer attached to this element.
    536 	 * @return User data pointer previously set with setUserData.
    537 	 */
    538 	void* getUserData();
    539 
    540 public:
    541 	// This function is called internally
    542 	static void deleteCMDataArray(daeTArray<daeCharArray*>& cmData);
    543 };
    544 
    545 #include <dae/daeSmartRef.h>
    546 typedef daeSmartRef<daeElement> daeElementRef;
    547 typedef daeSmartRef<const daeElement> daeElementConstRef;
    548 //#include <dae/daeArray.h>
    549 typedef daeTArray<daeElementRef> daeElementRefArray;
    550 
    551 #endif //__DAE_ELEMENT_H__
    552