blob: 7b892b0902ca693615ca3bc4c4714b142fbaaadb [file] [log] [blame]
Patrick Benavoli68a91282011-08-31 11:23:23 +02001/* <auto_header>
2 * <FILENAME>
3 *
4 * INTEL CONFIDENTIAL
5 * Copyright © 2011 Intel
6 * Corporation All Rights Reserved.
7 *
8 * The source code contained or described herein and all documents related to
9 * the source code ("Material") are owned by Intel Corporation or its suppliers
10 * or licensors. Title to the Material remains with Intel Corporation or its
11 * suppliers and licensors. The Material contains trade secrets and proprietary
12 * and confidential information of Intel or its suppliers and licensors. The
13 * Material is protected by worldwide copyright and trade secret laws and
14 * treaty provisions. No part of the Material may be used, copied, reproduced,
15 * modified, published, uploaded, posted, transmitted, distributed, or
16 * disclosed in any way without Intel’s prior express written permission.
17 *
18 * No license under any patent, copyright, trade secret or other intellectual
19 * property right is granted to or conferred upon you by disclosure or delivery
20 * of the Materials, either expressly, by implication, inducement, estoppel or
21 * otherwise. Any license under such intellectual property rights must be
22 * express and approved by Intel in writing.
23 *
24 * AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
25 * CREATED: 2011-06-01
26 * UPDATED: 2011-07-27
27 *
28 *
29 * </auto_header>
30 */
31#include "Element.h"
32#include <assert.h>
33#include <stdio.h>
34#include <stdarg.h>
35#include "XmlElementSerializingContext.h"
36#include "ElementLibrary.h"
37#include "ErrorContext.h"
38
39CElement::CElement(const string& strName) : _strName(strName), _pParent(NULL)
40{
41}
42
43CElement::~CElement()
44{
45 removeChildren();
46}
47
48// Logging
49void CElement::log(const string& strMessage, ...) const
50{
51 char acBuffer[512];
52 va_list listPointer;
53
54 va_start(listPointer, strMessage);
55
56 vsnprintf(acBuffer, sizeof(acBuffer), strMessage.c_str(), listPointer);
57
58 va_end(listPointer);
59
60 doLog(acBuffer);
61}
62
63void CElement::doLog(const string& strLog) const
64{
65 assert(_pParent);
66
67 // Propagate till root
68 _pParent->doLog(strLog);
69}
70
71void CElement::nestLog() const
72{
73 assert(_pParent);
74
75 // Propagate till root
76 _pParent->nestLog();
77}
78
79void CElement::unnestLog() const
80{
81 assert(_pParent);
82
83 // Propagate till root
84 _pParent->unnestLog();
85}
86
87
88void CElement::setDescription(const string& strDescription)
89{
90 _strDescription = strDescription;
91}
92
93const string& CElement::getDescription() const
94{
95 return _strDescription;
96}
97
98bool CElement::childrenAreDynamic() const
99{
100 // By default, children are searched and not created during xml parsing
101 return false;
102}
103
104bool CElement::init(string& strError)
105{
106 uint32_t uiIndex;
107
108 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
109
110 CElement* pElement = _childArray[uiIndex];;
111
112 if (!pElement->init(strError)) {
113
114 return false;
115 }
116 }
117
118 return true;
119}
120
121void CElement::dumpContent(string& strContent, CErrorContext& errorContext, const uint32_t uiDepth) const
122{
123 string strIndent;
124
125 // Level
126 uint32_t uiNbIndents = uiDepth;
127
128 while (uiNbIndents--) {
129
130 strIndent += " ";
131 }
132 // Type
133 strContent += strIndent + "- " + getKind();
134
135 // Name
136 if (!_strName.empty()) {
137
138 strContent += ": " + getName();
139 }
140
141 // Value
142 string strValue;
143 logValue(strValue, errorContext);
144
145 if (!strValue.empty()) {
146
147 strContent += " = " + strValue;
148 }
149
150 strContent += "\n";
151
152 uint32_t uiIndex;
153
154 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
155
156 _childArray[uiIndex]->dumpContent(strContent, errorContext, uiDepth + 1);
157 }
158}
159
160void CElement::logValue(string& strValue, CErrorContext& errorContext) const
161{
162 (void)strValue;
163 (void)errorContext;
164}
165
166// From IXmlSink
167bool CElement::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
168{
169 // Propagate through children
170 CXmlElement::CChildIterator childIterator(xmlElement);
171
172 // Context
173 CXmlElementSerializingContext& elementSerializingContext = static_cast<CXmlElementSerializingContext&>(serializingContext);
174
175 CXmlElement childElement;
176
177 while (childIterator.next(childElement)) {
178
179 CElement* pChild;
180
181 if (!childrenAreDynamic()) {
182
183 pChild = findChildOfKind(childElement.getType());
184
185 if (!pChild) {
186
187 elementSerializingContext.setError("XML Path not found: " + xmlElement.getPath());
188
189 return false;
190 }
191
192 } else {
193 // Child needs creation
194 pChild = elementSerializingContext.getElementLibrary()->createElement(childElement);
195
196 if (pChild) {
197
198 // Store created child!
199 addChild(pChild);
200 } else {
201
202 elementSerializingContext.setError("Unable to create XML element " + childElement.getPath());
203
204 return false;
205 }
206 }
207
208 // Dig
209 if (!pChild->fromXml(childElement, elementSerializingContext)) {
210
211 return false;
212 }
213 }
214
215 return true;
216}
217
218// From IXmlSource
219void CElement::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
220{
221 // Browse children and propagate
222 uint32_t uiNbChildren = getNbChildren();
223 uint32_t uiChild;
224
225 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
226
227 const CElement* pChild = _childArray[uiChild];
228
229 // Create corresponding child element
230 CXmlElement xmlChildElement;
231
232 xmlElement.createChild(xmlChildElement, pChild->getKind());
233
234 // Set attributes
235 pChild->setXmlNameAttribute(xmlChildElement);
236
237
238 // Propagate
239 pChild->toXml(xmlChildElement, serializingContext);
240 }
241}
242
243void CElement::setXmlNameAttribute(CXmlElement& xmlElement) const
244{
245 // By default, set Name attribute if any
246 string strName = getName();
247
248 if (!strName.empty()) {
249
250 xmlElement.setNameAttribute(strName);
251 }
252}
253
254// Name
255void CElement::setName(const string& strName)
256{
257 _strName = strName;
258}
259
260const string& CElement::getName() const
261{
262 return _strName;
263}
264
265bool CElement::rename(const string& strName, string& strError)
266{
267 // Check for conflict with brotherhood if relevant
268 if (_pParent && _pParent->childrenAreDynamic()) {
269
270 uint32_t uiParentChild;
271 uint32_t uiParentNbChildren = _pParent->getNbChildren();
272
273 for (uiParentChild = 0; uiParentChild < uiParentNbChildren; uiParentChild++) {
274
275 const CElement* pParentChild = _pParent->getChild(uiParentChild);
276
277 if (pParentChild != this && pParentChild->getName() == strName) {
278
279 // Conflict
280 strError = "Name conflicts with brother element";
281
282 return false;
283 }
284 }
285 }
286 // Change name
287 setName(strName);
288
289 return true;
290}
291
292string CElement::getPathName() const
293{
294 if (!_strName.empty()) {
295
296 return _strName;
297 } else {
298
299 return getKind();
300 }
301}
302
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200303// Hierarchy
Patrick Benavoli68a91282011-08-31 11:23:23 +0200304void CElement::addChild(CElement* pChild)
305{
306 _childArray.push_back(pChild);
307
308 pChild->_pParent = this;
309}
310
311CElement* CElement::getChild(uint32_t uiIndex)
312{
313 assert(uiIndex <= _childArray.size());
314
315 return _childArray[uiIndex];
316}
317
318const CElement* CElement::getChild(uint32_t uiIndex) const
319{
320 assert(uiIndex <= _childArray.size());
321
322 return _childArray[uiIndex];
323}
324
325CElement* CElement::getLastChild()
326{
327 uint32_t uiNbChildren = getNbChildren();
328
329 assert(uiNbChildren);
330
331 return _childArray[uiNbChildren - 1];
332}
333
334bool CElement::removeChild(CElement* pChild)
335{
336 ChildArrayIterator it;
337
338 for (it = _childArray.begin(); it != _childArray.end(); ++it) {
339
340 CElement* pElement = *it;
341
342 if (pElement == pChild) {
343
344 _childArray.erase(it);
345
346 return true;
347 }
348 }
349 return false;
350}
351
352void CElement::listChildren(string& strChildList) const
353{
354 strChildList = "\n";
355
356 // Get list of children names
357 uint32_t uiNbChildren = getNbChildren();
358 uint32_t uiChild;
359
360 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
361
362 const CElement* pChild = _childArray[uiChild];
363
364 strChildList += pChild->getName() + "\n";
365 }
366}
367
368string CElement::listQualifiedPaths(bool bDive, uint32_t uiLevel) const
369{
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200370 uint32_t uiNbChildren = getNbChildren();
371 string strResult;
372
373 // Dive Will cause only leaf nodes to be printed
374 if (!bDive || !uiNbChildren) {
375
376 strResult = getQualifiedPath() + "\n";
377 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200378
379 if (bDive || !uiLevel) {
380 // Get list of children paths
Patrick Benavoli68a91282011-08-31 11:23:23 +0200381 uint32_t uiChild;
382
383 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
384
385 const CElement* pChild = _childArray[uiChild];
386
387 strResult += pChild->listQualifiedPaths(bDive, uiLevel + 1);
388 }
389 }
390 return strResult;
391}
392
393void CElement::listChildrenPaths(string& strChildList) const
394{
Patrick Benavoli68a91282011-08-31 11:23:23 +0200395 // Get list of children paths
396 uint32_t uiNbChildren = getNbChildren();
397 uint32_t uiChild;
398
399 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
400
401 const CElement* pChild = _childArray[uiChild];
402
403 strChildList += pChild->getPath() + "\n";
404 }
405}
406
407uint32_t CElement::getNbChildren() const
408{
409 return _childArray.size();
410}
411
412const CElement* CElement::getParent() const
413{
414 return _pParent;
415}
416
417CElement* CElement::getParent()
418{
419 return _pParent;
420}
421
422void CElement::clean()
423{
424 if (childrenAreDynamic()) {
425
426 removeChildren();
427 } else {
428 // Just propagate
429 uint32_t uiIndex;
430
431 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
432
433 _childArray[uiIndex]->clean();
434 }
435 }
436}
437
438void CElement::removeChildren()
439{
440 // Delete in reverse order
441 ChildArrayReverseIterator it;
442
443 for (it = _childArray.rbegin(); it != _childArray.rend(); ++it) {
444
445 delete *it;
446 }
447 _childArray.clear();
448}
449
450const CElement* CElement::findDescendant(CPathNavigator& pathNavigator) const
451{
452 string* pStrChildName = pathNavigator.next();
453
454 if (!pStrChildName) {
455
456 return this;
457 }
458
459 const CElement* pChild = findChild(*pStrChildName);
460
461 if (!pChild) {
462
463 return NULL;
464 }
465
466 return pChild->findDescendant(pathNavigator);
467}
468
469CElement* CElement::findDescendant(CPathNavigator& pathNavigator)
470{
471 string* pStrChildName = pathNavigator.next();
472
473 if (!pStrChildName) {
474
475 return this;
476 }
477
478 CElement* pChild = findChild(*pStrChildName);
479
480 if (!pChild) {
481
482 return NULL;
483 }
484
485 return pChild->findDescendant(pathNavigator);
486}
487
488bool CElement::isDescendantOf(const CElement* pCandidateAscendant) const
489{
490 if (!_pParent) {
491
492 return false;
493 }
494 if (_pParent == pCandidateAscendant) {
495
496 return true;
497 }
498 return _pParent->isDescendantOf(pCandidateAscendant);
499}
500
501CElement* CElement::findAscendantOfKind(const string& strKind)
502{
503 if (!_pParent) {
504
505 return NULL;
506 }
507
508 if (_pParent->getKind() == strKind) {
509
510 return _pParent;
511 }
512 return _pParent->findAscendantOfKind(strKind);
513}
514
515CElement* CElement::findChild(const string& strName)
516{
517 uint32_t uiIndex;
518
519 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
520
521 CElement* pElement = _childArray[uiIndex];
522
523 if (pElement->getPathName() == strName) {
524
525 return pElement;
526 }
527 }
528
529 return NULL;
530}
531
532const CElement* CElement::findChild(const string& strName) const
533{
534 uint32_t uiIndex;
535
536 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
537
538 const CElement* pElement = _childArray[uiIndex];
539
540 if (pElement->getPathName() == strName) {
541
542 return pElement;
543 }
544 }
545
546 return NULL;
547}
548
549CElement* CElement::findChildOfKind(const string& strKind)
550{
551 uint32_t uiIndex;
552
553 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
554
555 CElement* pElement = _childArray[uiIndex];
556
557 if (pElement->getKind() == strKind) {
558
559 return pElement;
560 }
561 }
562
563 return NULL;
564}
565
566const CElement* CElement::findChildOfKind(const string& strKind) const
567{
568 uint32_t uiIndex;
569
570 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
571
572 const CElement* pElement = _childArray[uiIndex];;
573
574 if (pElement->getKind() == strKind) {
575
576 return pElement;
577 }
578 }
579
580 return NULL;
581}
582
583CElement* CElement::getRoot()
584{
585 if (!_pParent) {
586
587 return this;
588 }
589 return _pParent->getRoot();
590}
591
592const CElement* CElement::getRoot() const
593{
594 if (!_pParent) {
595
596 return this;
597 }
598 return _pParent->getRoot();
599}
600
601string CElement::getPath() const
602{
603 // Take out root element from the path
604 if (_pParent && _pParent->_pParent) {
605
606 return _pParent->getPath() + "/" + getPathName();
607 }
608 return "/" + getPathName();
609}
610
611string CElement::getQualifiedPath() const
612{
613 return getPath() + " [" + getKind() + "]";
614}
615
616uint32_t CElement::getDepth() const
617{
618 if (_pParent) {
619
620 return _pParent->getDepth() + 1;
621 }
622
623 return 0;
624}
625
626// Checksum for integrity checks
627uint8_t CElement::computeStructureChecksum() const
628{
629 // Base checksum computation on element kind
630 string strKind = getKind();
631
632 // Get element kind
633 const char* pcData = strKind.c_str();
634
635 // Cumulate
636 uint8_t uiChecksum = 0;
637
638 while (*pcData) {
639
640 uiChecksum += *pcData++;
641 }
642
643 // Propagate
644 uint32_t uiIndex;
645 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
646
647 const CElement* pChild = _childArray[uiIndex];
648
649 uiChecksum += pChild->computeStructureChecksum();
650 }
651
652 return uiChecksum;
653}
654
Patrick Benavoli6ba361d2011-08-31 11:23:24 +0200655// Utility to underline
656void CElement::appendTitle(string& strTo, const string& strTitle)
657{
658 strTo += "\n" + strTitle + "\n";
659
660 uint32_t uiLength = strTitle.size();
661
662 while (uiLength--) {
663
664 strTo += "─";
665 }
666 strTo += "\n";
667}