/* * * * INTEL CONFIDENTIAL * Copyright © 2011 Intel * Corporation All Rights Reserved. * * The source code contained or described herein and all documents related to * the source code ("Material") are owned by Intel Corporation or its suppliers * or licensors. Title to the Material remains with Intel Corporation or its * suppliers and licensors. The Material contains trade secrets and proprietary * and confidential information of Intel or its suppliers and licensors. The * Material is protected by worldwide copyright and trade secret laws and * treaty provisions. No part of the Material may be used, copied, reproduced, * modified, published, uploaded, posted, transmitted, distributed, or * disclosed in any way without Intel’s prior express written permission. * * No license under any patent, copyright, trade secret or other intellectual * property right is granted to or conferred upon you by disclosure or delivery * of the Materials, either expressly, by implication, inducement, estoppel or * otherwise. Any license under such intellectual property rights must be * express and approved by Intel in writing. * * AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com) * CREATED: 2011-06-01 * UPDATED: 2011-07-27 * * * */ #include "Element.h" #include #include #include #include "XmlElementSerializingContext.h" #include "ElementLibrary.h" #include "ErrorContext.h" CElement::CElement(const string& strName) : _strName(strName), _pParent(NULL) { } CElement::~CElement() { removeChildren(); } // Logging void CElement::log(const string& strMessage, ...) const { char acBuffer[512]; va_list listPointer; va_start(listPointer, strMessage); vsnprintf(acBuffer, sizeof(acBuffer), strMessage.c_str(), listPointer); va_end(listPointer); doLog(acBuffer); } void CElement::doLog(const string& strLog) const { assert(_pParent); // Propagate till root _pParent->doLog(strLog); } void CElement::nestLog() const { assert(_pParent); // Propagate till root _pParent->nestLog(); } void CElement::unnestLog() const { assert(_pParent); // Propagate till root _pParent->unnestLog(); } void CElement::setDescription(const string& strDescription) { _strDescription = strDescription; } const string& CElement::getDescription() const { return _strDescription; } bool CElement::childrenAreDynamic() const { // By default, children are searched and not created during xml parsing return false; } bool CElement::init(string& strError) { uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { CElement* pElement = _childArray[uiIndex];; if (!pElement->init(strError)) { return false; } } return true; } void CElement::dumpContent(string& strContent, CErrorContext& errorContext, const uint32_t uiDepth) const { string strIndent; // Level uint32_t uiNbIndents = uiDepth; while (uiNbIndents--) { strIndent += " "; } // Type strContent += strIndent + "- " + getKind(); // Name if (!_strName.empty()) { strContent += ": " + getName(); } // Value string strValue; logValue(strValue, errorContext); if (!strValue.empty()) { strContent += " = " + strValue; } strContent += "\n"; uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { _childArray[uiIndex]->dumpContent(strContent, errorContext, uiDepth + 1); } } void CElement::logValue(string& strValue, CErrorContext& errorContext) const { (void)strValue; (void)errorContext; } // From IXmlSink bool CElement::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) { // Propagate through children CXmlElement::CChildIterator childIterator(xmlElement); // Context CXmlElementSerializingContext& elementSerializingContext = static_cast(serializingContext); CXmlElement childElement; while (childIterator.next(childElement)) { CElement* pChild; if (!childrenAreDynamic()) { pChild = findChildOfKind(childElement.getType()); if (!pChild) { elementSerializingContext.setError("XML Path not found: " + xmlElement.getPath()); return false; } } else { // Child needs creation pChild = elementSerializingContext.getElementLibrary()->createElement(childElement); if (pChild) { // Store created child! addChild(pChild); } else { elementSerializingContext.setError("Unable to create XML element " + childElement.getPath()); return false; } } // Dig if (!pChild->fromXml(childElement, elementSerializingContext)) { return false; } } return true; } // From IXmlSource void CElement::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const { // Browse children and propagate uint32_t uiNbChildren = getNbChildren(); uint32_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { const CElement* pChild = _childArray[uiChild]; // Create corresponding child element CXmlElement xmlChildElement; xmlElement.createChild(xmlChildElement, pChild->getKind()); // Set attributes pChild->setXmlNameAttribute(xmlChildElement); // Propagate pChild->toXml(xmlChildElement, serializingContext); } } void CElement::setXmlNameAttribute(CXmlElement& xmlElement) const { // By default, set Name attribute if any string strName = getName(); if (!strName.empty()) { xmlElement.setNameAttribute(strName); } } // Name void CElement::setName(const string& strName) { _strName = strName; } const string& CElement::getName() const { return _strName; } bool CElement::rename(const string& strName, string& strError) { // Check for conflict with brotherhood if relevant if (_pParent && _pParent->childrenAreDynamic()) { uint32_t uiParentChild; uint32_t uiParentNbChildren = _pParent->getNbChildren(); for (uiParentChild = 0; uiParentChild < uiParentNbChildren; uiParentChild++) { const CElement* pParentChild = _pParent->getChild(uiParentChild); if (pParentChild != this && pParentChild->getName() == strName) { // Conflict strError = "Name conflicts with brother element"; return false; } } } // Change name setName(strName); return true; } string CElement::getPathName() const { if (!_strName.empty()) { return _strName; } else { return getKind(); } } // Hierarchy void CElement::addChild(CElement* pChild) { _childArray.push_back(pChild); pChild->_pParent = this; } CElement* CElement::getChild(uint32_t uiIndex) { assert(uiIndex <= _childArray.size()); return _childArray[uiIndex]; } const CElement* CElement::getChild(uint32_t uiIndex) const { assert(uiIndex <= _childArray.size()); return _childArray[uiIndex]; } CElement* CElement::getLastChild() { uint32_t uiNbChildren = getNbChildren(); assert(uiNbChildren); return _childArray[uiNbChildren - 1]; } bool CElement::removeChild(CElement* pChild) { ChildArrayIterator it; for (it = _childArray.begin(); it != _childArray.end(); ++it) { CElement* pElement = *it; if (pElement == pChild) { _childArray.erase(it); return true; } } return false; } void CElement::listChildren(string& strChildList) const { strChildList = "\n"; // Get list of children names uint32_t uiNbChildren = getNbChildren(); uint32_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { const CElement* pChild = _childArray[uiChild]; strChildList += pChild->getName() + "\n"; } } string CElement::listQualifiedPaths(bool bDive, uint32_t uiLevel) const { uint32_t uiNbChildren = getNbChildren(); string strResult; // Dive Will cause only leaf nodes to be printed if (!bDive || !uiNbChildren) { strResult = getQualifiedPath() + "\n"; } if (bDive || !uiLevel) { // Get list of children paths uint32_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { const CElement* pChild = _childArray[uiChild]; strResult += pChild->listQualifiedPaths(bDive, uiLevel + 1); } } return strResult; } void CElement::listChildrenPaths(string& strChildList) const { // Get list of children paths uint32_t uiNbChildren = getNbChildren(); uint32_t uiChild; for (uiChild = 0; uiChild < uiNbChildren; uiChild++) { const CElement* pChild = _childArray[uiChild]; strChildList += pChild->getPath() + "\n"; } } uint32_t CElement::getNbChildren() const { return _childArray.size(); } const CElement* CElement::getParent() const { return _pParent; } CElement* CElement::getParent() { return _pParent; } void CElement::clean() { if (childrenAreDynamic()) { removeChildren(); } else { // Just propagate uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { _childArray[uiIndex]->clean(); } } } void CElement::removeChildren() { // Delete in reverse order ChildArrayReverseIterator it; for (it = _childArray.rbegin(); it != _childArray.rend(); ++it) { delete *it; } _childArray.clear(); } const CElement* CElement::findDescendant(CPathNavigator& pathNavigator) const { string* pStrChildName = pathNavigator.next(); if (!pStrChildName) { return this; } const CElement* pChild = findChild(*pStrChildName); if (!pChild) { return NULL; } return pChild->findDescendant(pathNavigator); } CElement* CElement::findDescendant(CPathNavigator& pathNavigator) { string* pStrChildName = pathNavigator.next(); if (!pStrChildName) { return this; } CElement* pChild = findChild(*pStrChildName); if (!pChild) { return NULL; } return pChild->findDescendant(pathNavigator); } bool CElement::isDescendantOf(const CElement* pCandidateAscendant) const { if (!_pParent) { return false; } if (_pParent == pCandidateAscendant) { return true; } return _pParent->isDescendantOf(pCandidateAscendant); } CElement* CElement::findAscendantOfKind(const string& strKind) { if (!_pParent) { return NULL; } if (_pParent->getKind() == strKind) { return _pParent; } return _pParent->findAscendantOfKind(strKind); } CElement* CElement::findChild(const string& strName) { uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { CElement* pElement = _childArray[uiIndex]; if (pElement->getPathName() == strName) { return pElement; } } return NULL; } const CElement* CElement::findChild(const string& strName) const { uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { const CElement* pElement = _childArray[uiIndex]; if (pElement->getPathName() == strName) { return pElement; } } return NULL; } CElement* CElement::findChildOfKind(const string& strKind) { uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { CElement* pElement = _childArray[uiIndex]; if (pElement->getKind() == strKind) { return pElement; } } return NULL; } const CElement* CElement::findChildOfKind(const string& strKind) const { uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { const CElement* pElement = _childArray[uiIndex];; if (pElement->getKind() == strKind) { return pElement; } } return NULL; } CElement* CElement::getRoot() { if (!_pParent) { return this; } return _pParent->getRoot(); } const CElement* CElement::getRoot() const { if (!_pParent) { return this; } return _pParent->getRoot(); } string CElement::getPath() const { // Take out root element from the path if (_pParent && _pParent->_pParent) { return _pParent->getPath() + "/" + getPathName(); } return "/" + getPathName(); } string CElement::getQualifiedPath() const { return getPath() + " [" + getKind() + "]"; } uint32_t CElement::getDepth() const { if (_pParent) { return _pParent->getDepth() + 1; } return 0; } // Checksum for integrity checks uint8_t CElement::computeStructureChecksum() const { // Base checksum computation on element kind string strKind = getKind(); // Get element kind const char* pcData = strKind.c_str(); // Cumulate uint8_t uiChecksum = 0; while (*pcData) { uiChecksum += *pcData++; } // Propagate uint32_t uiIndex; for (uiIndex = 0; uiIndex < _childArray.size(); uiIndex++) { const CElement* pChild = _childArray[uiIndex]; uiChecksum += pChild->computeStructureChecksum(); } return uiChecksum; } // Utility to underline void CElement::appendTitle(string& strTo, const string& strTitle) { strTo += "\n" + strTitle + "\n"; uint32_t uiLength = strTitle.size(); while (uiLength--) { strTo += "─"; } strTo += "\n"; }