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