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