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
simpleAdd(daeString name,int index)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
add(daeString names_,int index)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
add(daeElement * elt,int index)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
addBefore(daeElement * elt,daeElement * index)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
addAfter(daeElement * elt,daeElement * index)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
createElement(daeString className)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
createAndPlace(daeString className)81 daeElement* daeElement::createAndPlace(daeString className) {
82 return add(className);
83 }
84
createAndPlaceAt(daeInt index,daeString className)85 daeElement* daeElement::createAndPlaceAt(daeInt index, daeString className) {
86 return add(className, index);
87 }
88
placeElement(daeElement * e)89 daeBool daeElement::placeElement(daeElement* e) {
90 return add(e) != NULL;
91 }
92
placeElementAt(daeInt index,daeElement * e)93 daeBool daeElement::placeElementAt(daeInt index, daeElement* e) {
94 return add(e, index) != NULL;
95 }
96
placeElementBefore(daeElement * marker,daeElement * element)97 daeBool daeElement::placeElementBefore( daeElement *marker, daeElement *element ) {
98 return addBefore(element, marker) != NULL;
99 }
100
placeElementAfter(daeElement * marker,daeElement * element)101 daeBool daeElement::placeElementAfter( daeElement *marker, daeElement *element ) {
102 return addAfter(element, marker) != NULL;
103 }
104
findLastIndexOf(daeString elementName)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
removeChildElement(daeElement * element)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
setDocument(daeDocument * c,bool notifyDocument)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
deleteCMDataArray(daeTArray<daeCharArray * > & cmData)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
getAttributeCount()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.
getAttributeIndex(daeElement & el,daeString 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
getAttributeObject(size_t i)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
getAttributeObject(daeString name)191 daeMetaAttribute* daeElement::getAttributeObject(daeString name) {
192 return getAttributeObject(getAttributeIndex(*this, name));
193 }
194
getAttributeName(size_t i)195 std::string daeElement::getAttributeName(size_t i) {
196 if (daeMetaAttribute* attr = getAttributeObject(i))
197 return (daeString)attr->getName();
198 return "";
199 }
200
hasAttribute(daeString name)201 daeBool daeElement::hasAttribute(daeString name) {
202 return getAttributeObject(name) != 0;
203 }
204
isAttributeSet(daeString name)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
getAttribute(size_t i)212 std::string daeElement::getAttribute(size_t i) {
213 std::string value;
214 getAttribute(i, value);
215 return value;
216 }
217
getAttribute(size_t i,std::string & value)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
getAttribute(daeString name)227 std::string daeElement::getAttribute(daeString name) {
228 std::string value;
229 getAttribute(name, value);
230 return value;
231 }
232
getAttribute(daeString name,std::string & value)233 void daeElement::getAttribute(daeString name, std::string& value) {
234 getAttribute(getAttributeIndex(*this, name), value);
235 }
236
attr()237 daeElement::attr::attr() { }
attr(const std::string & name,const std::string & value)238 daeElement::attr::attr(const std::string& name, const std::string& value)
239 : name(name), value(value) { }
240
getAttributes()241 daeTArray<daeElement::attr> daeElement::getAttributes() {
242 daeTArray<daeElement::attr> attrs;
243 getAttributes(attrs);
244 return attrs;
245 }
246
getAttributes(daeTArray<attr> & attrs)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
setAttribute(size_t i,daeString value)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
setAttribute(daeString name,daeString value)267 daeBool daeElement::setAttribute(daeString name, daeString value) {
268 return setAttribute(getAttributeIndex(*this, name), value);
269 }
270
271 // Deprecated
getAttributeValue(daeString name)272 daeMemoryRef daeElement::getAttributeValue(daeString name) {
273 if (daeMetaAttribute* attr = getAttributeObject(name))
274 return attr->get(this);
275 return NULL;
276 }
277
getCharDataObject()278 daeMetaAttribute* daeElement::getCharDataObject() {
279 if (_meta)
280 return _meta->getValueAttribute();
281 return NULL;
282 }
283
hasCharData()284 daeBool daeElement::hasCharData() {
285 return getCharDataObject() != NULL;
286 }
287
getCharData()288 std::string daeElement::getCharData() {
289 std::string result;
290 getCharData(result);
291 return result;
292 }
293
getCharData(std::string & data)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
setCharData(const std::string & data)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
hasValue()311 daeBool daeElement::hasValue() {
312 return hasCharData();
313 }
314
getValuePointer()315 daeMemoryRef daeElement::getValuePointer() {
316 if (daeMetaAttribute* charDataAttr = getCharDataObject())
317 return charDataAttr->get(this);
318 return NULL;
319 }
320
321 void
setup(daeMetaElement * meta)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
init()349 void daeElement::init() {
350 _parent = NULL;
351 _document = NULL;
352 _meta = NULL;
353 _elementName = NULL;
354 _userData = NULL;
355 }
356
daeElement()357 daeElement::daeElement() {
358 init();
359 }
360
daeElement(DAE & dae)361 daeElement::daeElement(DAE& dae) {
362 init();
363 }
364
~daeElement()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
getTypeName() const374 daeString daeElement::getTypeName() const
375 {
376 return _meta->getName();
377 }
getElementName() const378 daeString daeElement::getElementName() const
379 {
380 return _elementName ? _elementName : (daeString)_meta->getName();
381 }
setElementName(daeString nm)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
getID() const392 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
getChildren()400 daeElementRefArray daeElement::getChildren() {
401 daeElementRefArray array;
402 getChildren(array);
403 return array;
404 }
405
getChildren(daeElementRefArray & array)406 void daeElement::getChildren( daeElementRefArray &array ) {
407 _meta->getChildren( this, array );
408 }
409
clone(daeString idSuffix,daeString nameSuffix)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
getNecessaryColumnWidth(const vector<string> & tokens)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
formatToken(const string & token)472 string formatToken(const string& token) {
473 if (token.length() <= 50)
474 return token;
475 return token.substr(0, 47) + "...";
476 }
477 } // namespace {
478
compareResult()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
format()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 {
compareMatch()533 daeElement::compareResult compareMatch() {
534 daeElement::compareResult result;
535 result.compareValue = 0;
536 return result;
537 }
538
nameMismatch(daeElement & elt1,daeElement & elt2)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
attrMismatch(daeElement & elt1,daeElement & elt2,const string & attr)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
charDataMismatch(daeElement & elt1,daeElement & elt2)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
childCountMismatch(daeElement & elt1,daeElement & elt2)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
compareElementsSameType(daeElement & elt1,daeElement & elt2)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
compareElementsDifferentTypes(daeElement & elt1,daeElement & elt2)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
compare(daeElement & elt1,daeElement & elt2)641 int daeElement::compare(daeElement& elt1, daeElement& elt2) {
642 return compareWithFullResult(elt1, elt2).compareValue;
643 }
644
compareWithFullResult(daeElement & elt1,daeElement & elt2)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
getDocumentURI() const658 daeURI *daeElement::getDocumentURI() const {
659 if ( _document == NULL ) {
660 return NULL;
661 }
662 return _document->getDocumentURI();
663 }
664
665
matchName(daeString name)666 daeElement::matchName::matchName(daeString name) : name(name) { }
667
operator ()(daeElement * elt) const668 bool daeElement::matchName::operator()(daeElement* elt) const {
669 return strcmp(elt->getElementName(), name.c_str()) == 0;
670 }
671
matchType(daeInt typeID)672 daeElement::matchType::matchType(daeInt typeID) : typeID(typeID) { }
673
operator ()(daeElement * elt) const674 bool daeElement::matchType::operator()(daeElement* elt) const {
675 return elt->typeID() == typeID;
676 }
677
getChild(const matchElement & matcher)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
getDescendant(const matchElement & matcher)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
getAncestor(const matchElement & matcher)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
getParent()720 daeElement* daeElement::getParent() {
721 return _parent;
722 }
723
getChild(daeString eltName)724 daeElement* daeElement::getChild(daeString eltName) {
725 if (!eltName)
726 return NULL;
727 matchName test(eltName);
728 return getChild(matchName(eltName));
729 }
730
getDescendant(daeString eltName)731 daeElement* daeElement::getDescendant(daeString eltName) {
732 if (!eltName)
733 return NULL;
734 return getDescendant(matchName(eltName));
735 }
736
getAncestor(daeString eltName)737 daeElement* daeElement::getAncestor(daeString eltName) {
738 if (!eltName)
739 return NULL;
740 return getAncestor(matchName(eltName));
741 }
742
getDAE()743 DAE* daeElement::getDAE() {
744 return _meta->getDAE();
745 }
746
setUserData(void * data)747 void daeElement::setUserData(void* data) {
748 _userData = data;
749 }
750
getUserData()751 void* daeElement::getUserData() {
752 return _userData;
753 }
754