blob: 8cc6783a10e6490f8593223462c9ab4153d32a93 [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
303void CElement::addChild(CElement* pChild)
304{
305 _childArray.push_back(pChild);
306
307 pChild->_pParent = this;
308}
309
310CElement* CElement::getChild(uint32_t uiIndex)
311{
312 assert(uiIndex <= _childArray.size());
313
314 return _childArray[uiIndex];
315}
316
317const CElement* CElement::getChild(uint32_t uiIndex) const
318{
319 assert(uiIndex <= _childArray.size());
320
321 return _childArray[uiIndex];
322}
323
324CElement* CElement::getLastChild()
325{
326 uint32_t uiNbChildren = getNbChildren();
327
328 assert(uiNbChildren);
329
330 return _childArray[uiNbChildren - 1];
331}
332
333bool CElement::removeChild(CElement* pChild)
334{
335 ChildArrayIterator it;
336
337 for (it = _childArray.begin(); it != _childArray.end(); ++it) {
338
339 CElement* pElement = *it;
340
341 if (pElement == pChild) {
342
343 _childArray.erase(it);
344
345 return true;
346 }
347 }
348 return false;
349}
350
351void CElement::listChildren(string& strChildList) const
352{
353 strChildList = "\n";
354
355 // Get list of children names
356 uint32_t uiNbChildren = getNbChildren();
357 uint32_t uiChild;
358
359 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
360
361 const CElement* pChild = _childArray[uiChild];
362
363 strChildList += pChild->getName() + "\n";
364 }
365}
366
367string CElement::listQualifiedPaths(bool bDive, uint32_t uiLevel) const
368{
369 string strResult = getQualifiedPath() + "\n";
370
371 if (bDive || !uiLevel) {
372 // Get list of children paths
373 uint32_t uiNbChildren = getNbChildren();
374 uint32_t uiChild;
375
376 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
377
378 const CElement* pChild = _childArray[uiChild];
379
380 strResult += pChild->listQualifiedPaths(bDive, uiLevel + 1);
381 }
382 }
383 return strResult;
384}
385
386void CElement::listChildrenPaths(string& strChildList) const
387{
388 strChildList = "\n";
389
390 // Get list of children paths
391 uint32_t uiNbChildren = getNbChildren();
392 uint32_t uiChild;
393
394 for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
395
396 const CElement* pChild = _childArray[uiChild];
397
398 strChildList += pChild->getPath() + "\n";
399 }
400}
401
402uint32_t CElement::getNbChildren() const
403{
404 return _childArray.size();
405}
406
407const CElement* CElement::getParent() const
408{
409 return _pParent;
410}
411
412CElement* CElement::getParent()
413{
414 return _pParent;
415}
416
417void CElement::clean()
418{
419 if (childrenAreDynamic()) {
420
421 removeChildren();
422 } else {
423 // Just propagate
424 uint32_t uiIndex;
425
426 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
427
428 _childArray[uiIndex]->clean();
429 }
430 }
431}
432
433void CElement::removeChildren()
434{
435 // Delete in reverse order
436 ChildArrayReverseIterator it;
437
438 for (it = _childArray.rbegin(); it != _childArray.rend(); ++it) {
439
440 delete *it;
441 }
442 _childArray.clear();
443}
444
445const CElement* CElement::findDescendant(CPathNavigator& pathNavigator) const
446{
447 string* pStrChildName = pathNavigator.next();
448
449 if (!pStrChildName) {
450
451 return this;
452 }
453
454 const CElement* pChild = findChild(*pStrChildName);
455
456 if (!pChild) {
457
458 return NULL;
459 }
460
461 return pChild->findDescendant(pathNavigator);
462}
463
464CElement* CElement::findDescendant(CPathNavigator& pathNavigator)
465{
466 string* pStrChildName = pathNavigator.next();
467
468 if (!pStrChildName) {
469
470 return this;
471 }
472
473 CElement* pChild = findChild(*pStrChildName);
474
475 if (!pChild) {
476
477 return NULL;
478 }
479
480 return pChild->findDescendant(pathNavigator);
481}
482
483bool CElement::isDescendantOf(const CElement* pCandidateAscendant) const
484{
485 if (!_pParent) {
486
487 return false;
488 }
489 if (_pParent == pCandidateAscendant) {
490
491 return true;
492 }
493 return _pParent->isDescendantOf(pCandidateAscendant);
494}
495
496CElement* CElement::findAscendantOfKind(const string& strKind)
497{
498 if (!_pParent) {
499
500 return NULL;
501 }
502
503 if (_pParent->getKind() == strKind) {
504
505 return _pParent;
506 }
507 return _pParent->findAscendantOfKind(strKind);
508}
509
510CElement* CElement::findChild(const string& strName)
511{
512 uint32_t uiIndex;
513
514 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
515
516 CElement* pElement = _childArray[uiIndex];
517
518 if (pElement->getPathName() == strName) {
519
520 return pElement;
521 }
522 }
523
524 return NULL;
525}
526
527const CElement* CElement::findChild(const string& strName) const
528{
529 uint32_t uiIndex;
530
531 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
532
533 const CElement* pElement = _childArray[uiIndex];
534
535 if (pElement->getPathName() == strName) {
536
537 return pElement;
538 }
539 }
540
541 return NULL;
542}
543
544CElement* CElement::findChildOfKind(const string& strKind)
545{
546 uint32_t uiIndex;
547
548 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
549
550 CElement* pElement = _childArray[uiIndex];
551
552 if (pElement->getKind() == strKind) {
553
554 return pElement;
555 }
556 }
557
558 return NULL;
559}
560
561const CElement* CElement::findChildOfKind(const string& strKind) const
562{
563 uint32_t uiIndex;
564
565 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
566
567 const CElement* pElement = _childArray[uiIndex];;
568
569 if (pElement->getKind() == strKind) {
570
571 return pElement;
572 }
573 }
574
575 return NULL;
576}
577
578CElement* CElement::getRoot()
579{
580 if (!_pParent) {
581
582 return this;
583 }
584 return _pParent->getRoot();
585}
586
587const CElement* CElement::getRoot() const
588{
589 if (!_pParent) {
590
591 return this;
592 }
593 return _pParent->getRoot();
594}
595
596string CElement::getPath() const
597{
598 // Take out root element from the path
599 if (_pParent && _pParent->_pParent) {
600
601 return _pParent->getPath() + "/" + getPathName();
602 }
603 return "/" + getPathName();
604}
605
606string CElement::getQualifiedPath() const
607{
608 return getPath() + " [" + getKind() + "]";
609}
610
611uint32_t CElement::getDepth() const
612{
613 if (_pParent) {
614
615 return _pParent->getDepth() + 1;
616 }
617
618 return 0;
619}
620
621// Checksum for integrity checks
622uint8_t CElement::computeStructureChecksum() const
623{
624 // Base checksum computation on element kind
625 string strKind = getKind();
626
627 // Get element kind
628 const char* pcData = strKind.c_str();
629
630 // Cumulate
631 uint8_t uiChecksum = 0;
632
633 while (*pcData) {
634
635 uiChecksum += *pcData++;
636 }
637
638 // Propagate
639 uint32_t uiIndex;
640 for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) {
641
642 const CElement* pChild = _childArray[uiIndex];
643
644 uiChecksum += pChild->computeStructureChecksum();
645 }
646
647 return uiChecksum;
648}
649