daeElement.h 20 KB

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