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