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 #include <iomanip> 10 #include <dae/daeElement.h> 11 #include <dae/daeArray.h> 12 #include <dae/daeMetaAttribute.h> 13 #include <dae/daeMetaElementAttribute.h> 14 #include <dae/daeMetaElement.h> 15 #include <dae/daeDatabase.h> 16 #include <dae/daeErrorHandler.h> 17 #include <dae/daeURI.h> 18 #include <dae/domAny.h> 19 #include <dae/daeUtils.h> 20 21 using namespace std; 22 23 daeElement* daeElement::simpleAdd(daeString name, int index) { 24 if (daeElementRef elt = _meta->create(name)) 25 return add(elt, index); 26 return NULL; 27 } 28 29 daeElement* daeElement::add(daeString names_, int index) { 30 list<string> names; 31 cdom::tokenize(names_, " ", names); 32 cdom::tokenIter iter = names.begin(); 33 daeElement* root = simpleAdd(iter->c_str(), index); 34 if (!root) 35 return NULL; 36 37 iter++; 38 daeElement* elt = root; 39 for (; iter != names.end(); iter++) { 40 elt = elt->simpleAdd(iter->c_str()); 41 if (!elt) { 42 removeChildElement(root); 43 return NULL; 44 } 45 } 46 47 return elt; 48 } 49 50 daeElement* daeElement::add(daeElement* elt, int index) { 51 if (!elt) 52 return NULL; 53 if (elt == this) 54 return this; 55 bool result = (index == -1 ? _meta->place(this, elt) : _meta->placeAt(index, this, elt)); 56 return result ? elt : NULL; 57 } 58 59 daeElement* daeElement::addBefore(daeElement* elt, daeElement* index) { 60 if (!index || !elt || index->getParent() != this) 61 return NULL; 62 return _meta->placeBefore(index, this, elt) ? elt : NULL; 63 } 64 65 daeElement* daeElement::addAfter(daeElement* elt, daeElement* index) { 66 if (!index || !elt || index->getParent() != this) 67 return NULL; 68 return _meta->placeAfter(index, this, elt) ? elt : NULL; 69 } 70 71 daeElementRef 72 daeElement::createElement(daeString className) 73 { 74 daeElementRef elem = _meta->create(className); 75 // Bug #225 work around 76 // if ( elem != NULL) 77 // elem->ref(); // change premature delete into memory leak. 78 return elem; 79 } 80 81 daeElement* daeElement::createAndPlace(daeString className) { 82 return add(className); 83 } 84 85 daeElement* daeElement::createAndPlaceAt(daeInt index, daeString className) { 86 return add(className, index); 87 } 88 89 daeBool daeElement::placeElement(daeElement* e) { 90 return add(e) != NULL; 91 } 92 93 daeBool daeElement::placeElementAt(daeInt index, daeElement* e) { 94 return add(e, index) != NULL; 95 } 96 97 daeBool daeElement::placeElementBefore( daeElement *marker, daeElement *element ) { 98 return addBefore(element, marker) != NULL; 99 } 100 101 daeBool daeElement::placeElementAfter( daeElement *marker, daeElement *element ) { 102 return addAfter(element, marker) != NULL; 103 } 104 105 daeInt daeElement::findLastIndexOf( daeString elementName ) { 106 if ( _meta->getContents() != NULL ) { 107 daeElementRefArray* contents = 108 (daeElementRefArray*)_meta->getContents()->getWritableMemory(this); 109 for ( int i = (int)contents->getCount()-1; i >= 0; --i ) { 110 if ( strcmp( contents->get(i)->getElementName(), elementName ) == 0 ) { 111 return i; 112 } 113 } 114 } 115 return -1; 116 } 117 118 daeBool 119 daeElement::removeChildElement(daeElement* element) 120 { 121 // error traps 122 if(element==NULL) 123 return false; 124 if(element->_parent != this) 125 return false; 126 127 return _meta->remove( this, element ); 128 } 129 130 void daeElement::setDocument( daeDocument *c, bool notifyDocument ) { 131 if( _document == c ) 132 return; 133 134 // Notify our parent document if necessary. 135 if ( _document != NULL && notifyDocument ) 136 _document->removeElement(this); 137 _document = c; 138 if ( _document != NULL && notifyDocument ) 139 _document->insertElement(this); 140 141 // Notify our attributes 142 daeMetaAttributeRefArray& metaAttrs = getMeta()->getMetaAttributes(); 143 for (size_t i = 0; i < metaAttrs.getCount(); i++) 144 metaAttrs[i]->setDocument(this, c); 145 146 // Notify our char data object 147 if (getCharDataObject()) 148 getCharDataObject()->setDocument(this, c); 149 150 // Notify our children 151 daeElementRefArray ea; 152 getChildren( ea ); 153 for ( size_t x = 0; x < ea.getCount(); x++ ) { 154 // Since inserting and removing elements works recursively in the database, 155 // we don't need to notify it about inserts/removals as we process the 156 // children of this element. 157 ea[x]->setDocument( c, false ); 158 } 159 } 160 161 void daeElement::deleteCMDataArray(daeTArray<daeCharArray*>& cmData) { 162 for (unsigned int i = 0; i < cmData.getCount(); i++) 163 delete cmData.get(i); 164 cmData.clear(); 165 } 166 167 size_t daeElement::getAttributeCount() { 168 return getMeta()->getMetaAttributes().getCount(); 169 } 170 171 namespace { 172 // A helper function to get the index of an attribute given the attribute name. 173 size_t getAttributeIndex(daeElement& el, daeString name) { 174 if (el.getMeta()) { 175 daeMetaAttributeRefArray& metaAttrs = el.getMeta()->getMetaAttributes(); 176 for (size_t i = 0; i < metaAttrs.getCount(); i++) 177 if (metaAttrs[i]->getName() && strcmp(metaAttrs[i]->getName(), name) == 0) 178 return i; 179 } 180 return (size_t)-1; 181 } 182 } 183 184 daeMetaAttribute* daeElement::getAttributeObject(size_t i) { 185 daeMetaAttributeRefArray& attrs = getMeta()->getMetaAttributes(); 186 if (i >= attrs.getCount()) 187 return NULL; 188 return attrs[i]; 189 } 190 191 daeMetaAttribute* daeElement::getAttributeObject(daeString name) { 192 return getAttributeObject(getAttributeIndex(*this, name)); 193 } 194 195 std::string daeElement::getAttributeName(size_t i) { 196 if (daeMetaAttribute* attr = getAttributeObject(i)) 197 return (daeString)attr->getName(); 198 return ""; 199 } 200 201 daeBool daeElement::hasAttribute(daeString name) { 202 return getAttributeObject(name) != 0; 203 } 204 205 daeBool daeElement::isAttributeSet(daeString name) { 206 size_t i = getAttributeIndex(*this, name); 207 if (i != (size_t)-1) 208 return _validAttributeArray[i]; 209 return false; 210 } 211 212 std::string daeElement::getAttribute(size_t i) { 213 std::string value; 214 getAttribute(i, value); 215 return value; 216 } 217 218 void daeElement::getAttribute(size_t i, std::string& value) { 219 value = ""; 220 if (daeMetaAttribute* attr = getAttributeObject(i)) { 221 std::ostringstream buffer; 222 attr->memoryToString(this, buffer); 223 value = buffer.str(); 224 } 225 } 226 227 std::string daeElement::getAttribute(daeString name) { 228 std::string value; 229 getAttribute(name, value); 230 return value; 231 } 232 233 void daeElement::getAttribute(daeString name, std::string& value) { 234 getAttribute(getAttributeIndex(*this, name), value); 235 } 236 237 daeElement::attr::attr() { } 238 daeElement::attr::attr(const std::string& name, const std::string& value) 239 : name(name), value(value) { } 240 241 daeTArray<daeElement::attr> daeElement::getAttributes() { 242 daeTArray<daeElement::attr> attrs; 243 getAttributes(attrs); 244 return attrs; 245 } 246 247 void daeElement::getAttributes(daeTArray<attr>& attrs) { 248 attrs.clear(); 249 for (size_t i = 0; i < getAttributeCount(); i++) { 250 std::string value; 251 getAttribute(i, value); 252 attrs.append(attr(getAttributeName(i), value)); 253 } 254 } 255 256 daeBool daeElement::setAttribute(size_t i, daeString value) { 257 if (daeMetaAttribute* attr = getAttributeObject(i)) { 258 if (attr->getType()) { 259 attr->stringToMemory(this, value); 260 _validAttributeArray.set(i, true); 261 return true; 262 } 263 } 264 return false; 265 } 266 267 daeBool daeElement::setAttribute(daeString name, daeString value) { 268 return setAttribute(getAttributeIndex(*this, name), value); 269 } 270 271 // Deprecated 272 daeMemoryRef daeElement::getAttributeValue(daeString name) { 273 if (daeMetaAttribute* attr = getAttributeObject(name)) 274 return attr->get(this); 275 return NULL; 276 } 277 278 daeMetaAttribute* daeElement::getCharDataObject() { 279 if (_meta) 280 return _meta->getValueAttribute(); 281 return NULL; 282 } 283 284 daeBool daeElement::hasCharData() { 285 return getCharDataObject() != NULL; 286 } 287 288 std::string daeElement::getCharData() { 289 std::string result; 290 getCharData(result); 291 return result; 292 } 293 294 void daeElement::getCharData(std::string& data) { 295 data = ""; 296 if (daeMetaAttribute* charDataAttr = getCharDataObject()) { 297 std::ostringstream buffer; 298 charDataAttr->memoryToString(this, buffer); 299 data = buffer.str(); 300 } 301 } 302 303 daeBool daeElement::setCharData(const std::string& data) { 304 if (daeMetaAttribute* charDataAttr = getCharDataObject()) { 305 charDataAttr->stringToMemory(this, data.c_str()); 306 return true; 307 } 308 return false; 309 } 310 311 daeBool daeElement::hasValue() { 312 return hasCharData(); 313 } 314 315 daeMemoryRef daeElement::getValuePointer() { 316 if (daeMetaAttribute* charDataAttr = getCharDataObject()) 317 return charDataAttr->get(this); 318 return NULL; 319 } 320 321 void 322 daeElement::setup(daeMetaElement* meta) 323 { 324 if (_meta) 325 return; 326 _meta = meta; 327 daeMetaAttributeRefArray& attrs = meta->getMetaAttributes(); 328 int macnt = (int)attrs.getCount(); 329 330 _validAttributeArray.setCount(macnt, false); 331 332 for (int i = 0; i < macnt; i++) { 333 if (attrs[i]->getDefaultValue() != NULL) 334 attrs[i]->copyDefault(this); 335 } 336 337 //set up the _CMData array if there is one 338 if ( _meta->getMetaCMData() != NULL ) 339 { 340 daeTArray< daeCharArray *> *CMData = (daeTArray< daeCharArray *>*)_meta->getMetaCMData()->getWritableMemory(this); 341 CMData->setCount( _meta->getNumChoices() ); 342 for ( unsigned int i = 0; i < _meta->getNumChoices(); i++ ) 343 { 344 CMData->set( i, new daeCharArray() ); 345 } 346 } 347 } 348 349 void daeElement::init() { 350 _parent = NULL; 351 _document = NULL; 352 _meta = NULL; 353 _elementName = NULL; 354 _userData = NULL; 355 } 356 357 daeElement::daeElement() { 358 init(); 359 } 360 361 daeElement::daeElement(DAE& dae) { 362 init(); 363 } 364 365 daeElement::~daeElement() 366 { 367 if (_elementName) { 368 delete[] _elementName; 369 _elementName = NULL; 370 } 371 } 372 373 //function used until we clarify what's a type and what's a name for an element 374 daeString daeElement::getTypeName() const 375 { 376 return _meta->getName(); 377 } 378 daeString daeElement::getElementName() const 379 { 380 return _elementName ? _elementName : (daeString)_meta->getName(); 381 } 382 void daeElement::setElementName( daeString nm ) { 383 if ( nm == NULL ) { 384 if ( _elementName ) delete[] _elementName; 385 _elementName = NULL; 386 return; 387 } 388 if ( !_elementName ) _elementName = new daeChar[128]; 389 strcpy( (char*)_elementName, nm ); 390 } 391 392 daeString daeElement::getID() const { 393 daeElement* this_ = const_cast<daeElement*>(this); 394 if (_meta) 395 if (daeMetaAttribute* idAttr = this_->getAttributeObject("id")) 396 return *(daeStringRef*)idAttr->get(this_); 397 return NULL; 398 } 399 400 daeElementRefArray daeElement::getChildren() { 401 daeElementRefArray array; 402 getChildren(array); 403 return array; 404 } 405 406 void daeElement::getChildren( daeElementRefArray &array ) { 407 _meta->getChildren( this, array ); 408 } 409 410 daeSmartRef<daeElement> daeElement::clone(daeString idSuffix, daeString nameSuffix) { 411 // Use the meta object system to create a new instance of this element. We need to 412 // create a new meta if we're cloning a domAny object because domAnys never share meta objects. 413 // Ideally we'd be able to clone the _meta for domAny objects. Then we wouldn't need 414 // any additional special case code for cloning domAny. Unfortunately, we don't have a 415 // daeMetaElement::clone method. 416 bool any = typeID() == domAny::ID(); 417 daeElementRef ret = any ? domAny::registerElement(*getDAE())->create() : _meta->create(); 418 ret->setElementName( _elementName ); 419 420 // Copy the attributes and character data. Requires special care for domAny. 421 if (any) { 422 domAny* thisAny = (domAny*)this; 423 domAny* retAny = (domAny*)ret.cast(); 424 for (daeUInt i = 0; i < (daeUInt)thisAny->getAttributeCount(); i++) 425 retAny->setAttribute(thisAny->getAttributeName(i), thisAny->getAttributeValue(i)); 426 retAny->setValue(thisAny->getValue()); 427 } else { 428 // Use the meta system to copy attributes 429 daeMetaAttributeRefArray &attrs = _meta->getMetaAttributes(); 430 for (unsigned int i = 0; i < attrs.getCount(); i++) { 431 attrs[i]->copy( ret, this ); 432 ret->_validAttributeArray[i] = _validAttributeArray[i]; 433 } 434 if (daeMetaAttribute* valueAttr = getCharDataObject()) 435 valueAttr->copy( ret, this ); 436 } 437 438 daeElementRefArray children; 439 _meta->getChildren( this, children ); 440 for ( size_t x = 0; x < children.getCount(); x++ ) { 441 ret->placeElement( children.get(x)->clone( idSuffix, nameSuffix ) ); 442 } 443 444 // Mangle the id 445 if (idSuffix) { 446 std::string id = ret->getAttribute("id"); 447 if (!id.empty()) 448 ret->setAttribute("id", (id + idSuffix).c_str()); 449 } 450 // Mangle the name 451 if (nameSuffix) { 452 std::string name = ret->getAttribute("name"); 453 if (!name.empty()) 454 ret->setAttribute("name", (name + nameSuffix).c_str()); 455 } 456 return ret; 457 } 458 459 460 // Element comparison 461 462 namespace { // Utility functions 463 int getNecessaryColumnWidth(const vector<string>& tokens) { 464 int result = 0; 465 for (size_t i = 0; i < tokens.size(); i++) { 466 int tokenLength = int(tokens[i].length() > 0 ? tokens[i].length()+2 : 0); 467 result = max(tokenLength, result); 468 } 469 return result; 470 } 471 472 string formatToken(const string& token) { 473 if (token.length() <= 50) 474 return token; 475 return token.substr(0, 47) + "..."; 476 } 477 } // namespace { 478 479 daeElement::compareResult::compareResult() 480 : compareValue(0), 481 elt1(NULL), 482 elt2(NULL), 483 nameMismatch(false), 484 attrMismatch(""), 485 charDataMismatch(false), 486 childCountMismatch(false) { 487 } 488 489 string daeElement::compareResult::format() { 490 if (!elt1 || !elt2) 491 return ""; 492 493 // Gather the data we'll be printing 494 string name1 = formatToken(elt1->getElementName()), 495 name2 = formatToken(elt2->getElementName()), 496 type1 = formatToken(elt1->getTypeName()), 497 type2 = formatToken(elt2->getTypeName()), 498 id1 = formatToken(elt1->getAttribute("id")), 499 id2 = formatToken(elt2->getAttribute("id")), 500 attrName1 = formatToken(attrMismatch), 501 attrName2 = formatToken(attrMismatch), 502 attrValue1 = formatToken(elt1->getAttribute(attrMismatch.c_str())), 503 attrValue2 = formatToken(elt2->getAttribute(attrMismatch.c_str())), 504 charData1 = formatToken(elt1->getCharData()), 505 charData2 = formatToken(elt2->getCharData()), 506 childCount1 = formatToken(cdom::toString(elt1->getChildren().getCount())), 507 childCount2 = formatToken(cdom::toString(elt2->getChildren().getCount())); 508 509 // Compute formatting information 510 vector<string> col1Tokens = cdom::makeStringArray("Name", "Type", "ID", 511 "Attr name", "Attr value", "Char data", "Child count", 0); 512 vector<string> col2Tokens = cdom::makeStringArray("Element 1", name1.c_str(), 513 type1.c_str(), id1.c_str(), attrName1.c_str(), attrValue1.c_str(), 514 charData1.c_str(), childCount1.c_str(), 0); 515 516 int c1w = getNecessaryColumnWidth(col1Tokens), 517 c2w = getNecessaryColumnWidth(col2Tokens); 518 ostringstream msg; 519 msg << setw(c1w) << left << "" << setw(c2w) << left << "Element 1" << "Element 2\n" 520 << setw(c1w) << left << "" << setw(c2w) << left << "---------" << "---------\n" 521 << setw(c1w) << left << "Name" << setw(c2w) << left << name1 << name2 << endl 522 << setw(c1w) << left << "Type" << setw(c2w) << left << type1 << type2 << endl 523 << setw(c1w) << left << "ID" << setw(c2w) << left << id1 << id2 << endl 524 << setw(c1w) << left << "Attr name" << setw(c2w) << left << attrName1 << attrName2 << endl 525 << setw(c1w) << left << "Attr value" << setw(c2w) << left << attrValue1 << attrValue2 << endl 526 << setw(c1w) << left << "Char data" << setw(c2w) << left << charData1 << charData2 << endl 527 << setw(c1w) << left << "Child count" << setw(c2w) << left << childCount1 << childCount2; 528 529 return msg.str(); 530 } 531 532 namespace { 533 daeElement::compareResult compareMatch() { 534 daeElement::compareResult result; 535 result.compareValue = 0; 536 return result; 537 } 538 539 daeElement::compareResult nameMismatch(daeElement& elt1, daeElement& elt2) { 540 daeElement::compareResult result; 541 result.elt1 = &elt1; 542 result.elt2 = &elt2; 543 result.compareValue = strcmp(elt1.getElementName(), elt2.getElementName()); 544 result.nameMismatch = true; 545 return result; 546 } 547 548 daeElement::compareResult attrMismatch(daeElement& elt1, daeElement& elt2, const string& attr) { 549 daeElement::compareResult result; 550 result.elt1 = &elt1; 551 result.elt2 = &elt2; 552 result.compareValue = strcmp(elt1.getAttribute(attr.c_str()).c_str(), 553 elt2.getAttribute(attr.c_str()).c_str()); 554 result.attrMismatch = attr; 555 return result; 556 } 557 558 daeElement::compareResult charDataMismatch(daeElement& elt1, daeElement& elt2) { 559 daeElement::compareResult result; 560 result.elt1 = &elt1; 561 result.elt2 = &elt2; 562 result.compareValue = strcmp(elt1.getCharData().c_str(), 563 elt2.getCharData().c_str()); 564 result.charDataMismatch = true; 565 return result; 566 } 567 568 daeElement::compareResult childCountMismatch(daeElement& elt1, daeElement& elt2) { 569 daeElement::compareResult result; 570 result.elt1 = &elt1; 571 result.elt2 = &elt2; 572 daeElementRefArray children1 = elt1.getChildren(), 573 children2 = elt2.getChildren(); 574 result.compareValue = int(children1.getCount()) - int(children2.getCount()); 575 result.childCountMismatch = true; 576 return result; 577 } 578 579 daeElement::compareResult compareElementsSameType(daeElement& elt1, daeElement& elt2) { 580 // Compare attributes 581 for (size_t i = 0; i < elt1.getAttributeCount(); i++) 582 if (elt1.getAttributeObject(i)->compare(&elt1, &elt2) != 0) 583 return attrMismatch(elt1, elt2, elt1.getAttributeName(i)); 584 585 // Compare character data 586 if (elt1.getCharDataObject()) 587 if (elt1.getCharDataObject()->compare(&elt1, &elt2) != 0) 588 return charDataMismatch(elt1, elt2); 589 590 // Compare children 591 daeElementRefArray children1 = elt1.getChildren(), 592 children2 = elt2.getChildren(); 593 if (children1.getCount() != children2.getCount()) 594 return childCountMismatch(elt1, elt2); 595 for (size_t i = 0; i < children1.getCount(); i++) { 596 daeElement::compareResult result = daeElement::compareWithFullResult(*children1[i], *children2[i]); 597 if (result.compareValue != 0) 598 return result; 599 } 600 601 return compareMatch(); 602 } 603 604 daeElement::compareResult compareElementsDifferentTypes(daeElement& elt1, daeElement& elt2) { 605 string value1, value2; 606 607 // Compare attributes. Be careful because each element could have a 608 // different number of attributes. 609 if (elt1.getAttributeCount() > elt2.getAttributeCount()) 610 return attrMismatch(elt1, elt2, elt1.getAttributeName(elt2.getAttributeCount())); 611 if (elt2.getAttributeCount() > elt1.getAttributeCount()) 612 return attrMismatch(elt1, elt2, elt2.getAttributeName(elt1.getAttributeCount())); 613 for (size_t i = 0; i < elt1.getAttributeCount(); i++) { 614 elt1.getAttribute(i, value1); 615 elt2.getAttribute(elt1.getAttributeName(i).c_str(), value2); 616 if (value1 != value2) 617 return attrMismatch(elt1, elt2, elt1.getAttributeName(i)); 618 } 619 620 // Compare character data 621 elt1.getCharData(value1); 622 elt2.getCharData(value2); 623 if (value1 != value2) 624 return charDataMismatch(elt1, elt2); 625 626 // Compare children 627 daeElementRefArray children1 = elt1.getChildren(), 628 children2 = elt2.getChildren(); 629 if (children1.getCount() != children2.getCount()) 630 return childCountMismatch(elt1, elt2); 631 for (size_t i = 0; i < children1.getCount(); i++) { 632 daeElement::compareResult result = daeElement::compareWithFullResult(*children1[i], *children2[i]); 633 if (result.compareValue != 0) 634 return result; 635 } 636 637 return compareMatch(); 638 } 639 } // namespace { 640 641 int daeElement::compare(daeElement& elt1, daeElement& elt2) { 642 return compareWithFullResult(elt1, elt2).compareValue; 643 } 644 645 daeElement::compareResult daeElement::compareWithFullResult(daeElement& elt1, daeElement& elt2) { 646 // Check the element name 647 if (strcmp(elt1.getElementName(), elt2.getElementName()) != 0) 648 return nameMismatch(elt1, elt2); 649 650 // Dispatch to a specific function based on whether or not the types are the same 651 if ((elt1.typeID() != elt2.typeID()) || elt1.typeID() == domAny::ID()) 652 return compareElementsDifferentTypes(elt1, elt2); 653 else 654 return compareElementsSameType(elt1, elt2); 655 } 656 657 658 daeURI *daeElement::getDocumentURI() const { 659 if ( _document == NULL ) { 660 return NULL; 661 } 662 return _document->getDocumentURI(); 663 } 664 665 666 daeElement::matchName::matchName(daeString name) : name(name) { } 667 668 bool daeElement::matchName::operator()(daeElement* elt) const { 669 return strcmp(elt->getElementName(), name.c_str()) == 0; 670 } 671 672 daeElement::matchType::matchType(daeInt typeID) : typeID(typeID) { } 673 674 bool daeElement::matchType::operator()(daeElement* elt) const { 675 return elt->typeID() == typeID; 676 } 677 678 daeElement* daeElement::getChild(const matchElement& matcher) { 679 daeElementRefArray children; 680 getChildren(children); 681 for (size_t i = 0; i < children.getCount(); i++) 682 if (matcher(children[i])) 683 return children[i]; 684 685 return NULL; 686 } 687 688 daeElement* daeElement::getDescendant(const matchElement& matcher) { 689 daeElementRefArray elts; 690 getChildren(elts); 691 692 for (size_t i = 0; i < elts.getCount(); i++) { 693 // Check the current element for a match 694 if (matcher(elts[i])) 695 return elts[i]; 696 697 // Append the element's children to the queue 698 daeElementRefArray children; 699 elts[i]->getChildren(children); 700 size_t oldCount = elts.getCount(); 701 elts.setCount(elts.getCount() + children.getCount()); 702 for (size_t j = 0; j < children.getCount(); j++) 703 elts[oldCount + j] = children[j]; 704 } 705 706 return NULL; 707 } 708 709 daeElement* daeElement::getAncestor(const matchElement& matcher) { 710 daeElement* elt = getParent(); 711 while (elt) { 712 if (matcher(elt)) 713 return elt; 714 elt = elt->getParent(); 715 } 716 717 return NULL; 718 } 719 720 daeElement* daeElement::getParent() { 721 return _parent; 722 } 723 724 daeElement* daeElement::getChild(daeString eltName) { 725 if (!eltName) 726 return NULL; 727 matchName test(eltName); 728 return getChild(matchName(eltName)); 729 } 730 731 daeElement* daeElement::getDescendant(daeString eltName) { 732 if (!eltName) 733 return NULL; 734 return getDescendant(matchName(eltName)); 735 } 736 737 daeElement* daeElement::getAncestor(daeString eltName) { 738 if (!eltName) 739 return NULL; 740 return getAncestor(matchName(eltName)); 741 } 742 743 DAE* daeElement::getDAE() { 744 return _meta->getDAE(); 745 } 746 747 void daeElement::setUserData(void* data) { 748 _userData = data; 749 } 750 751 void* daeElement::getUserData() { 752 return _userData; 753 } 754