Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:55:08

0001 #include "DetectorDescription/Parser/src/DDXMLElement.h"
0002 
0003 #include <iostream>
0004 #include <memory>
0005 #include <utility>
0006 #include <string>
0007 
0008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0009 #include "FWCore/Utilities/interface/Exception.h"
0010 
0011 class DDCompactView;
0012 class DDLElementRegistry;
0013 
0014 DDXMLElement::DDXMLElement(DDLElementRegistry* myreg) : myRegistry_(myreg), attributes_(), text_(), autoClear_(false) {}
0015 
0016 DDXMLElement::DDXMLElement(DDLElementRegistry* myreg, const bool& clearme)
0017     : myRegistry_(myreg), attributes_(), text_(), autoClear_(clearme) {}
0018 
0019 // For pre-processing, after attributes are loaded.  Default, do nothing!
0020 void DDXMLElement::preProcessElement(const std::string& name, const std::string& nmspace, DDCompactView& cpv) {}
0021 
0022 // This loads the attributes into the attributes_ std::vector.
0023 void DDXMLElement::loadAttributes(const std::string& elemName,
0024                                   const std::vector<std::string>& names,
0025                                   const std::vector<std::string>& values,
0026                                   const std::string& nmspace,
0027                                   DDCompactView& cpv) {
0028   attributes_.resize(attributes_.size() + 1);
0029   DDXMLAttribute& tAttributes = attributes_.back();
0030 
0031   // adds attributes
0032   for (size_t i = 0; i < names.size(); ++i) {
0033     tAttributes.insert(std::make_pair(names[i], values[i]));
0034   }
0035 
0036   preProcessElement(elemName, nmspace, cpv);
0037 }
0038 
0039 // clear data.
0040 void DDXMLElement::clear(void) {
0041   text_.clear();
0042   attributes_.clear();
0043   attributeAccumulator_.clear();
0044 }
0045 
0046 // Access to current attributes by name.
0047 const std::string& DDXMLElement::getAttribute(const std::string& name) const {
0048   static const std::string ldef;
0049   if (!attributes_.empty())
0050     return get(name, attributes_.size() - 1);
0051   return ldef;
0052 }
0053 
0054 const DDXMLAttribute& DDXMLElement::getAttributeSet(size_t aIndex) const { return attributes_[aIndex]; }
0055 
0056 const DDName DDXMLElement::getDDName(const std::string& defaultNS, const std::string& attname, size_t aIndex) {
0057   if (aIndex < attributes_.size() && attributes_[aIndex].find(attname) != attributes_[aIndex].end()) {
0058     std::string ns = defaultNS;
0059     // For the user to fully control namespaces they must provide for
0060     // all name attributes something of the form, for example:
0061     //        <Solid name="ns:name" ...
0062     // If defaultNS is "!" (magic I don't like) then find and set
0063     // the namespace properly.
0064     if (defaultNS == "!") {
0065       ns = "";
0066     }
0067     const std::string& name = attributes_[aIndex].find(attname)->second;
0068     std::string rn = name;
0069     size_t foundColon = name.find(':');
0070     if (foundColon != std::string::npos) {
0071       ns = name.substr(0, foundColon);
0072       rn = name.substr(foundColon + 1);
0073     }
0074     return DDName(rn, ns);
0075   }
0076   std::string msg = "DDXMLElement:getDDName failed.  It was asked to make ";
0077   msg += "a DDName using attribute: " + attname;
0078   msg += " in position: " + std::to_string(aIndex) + ".  There are ";
0079   msg += std::to_string(attributes_.size()) + " entries in the element.";
0080   throwError(msg);
0081   return DDName("justToCompile", "justToCompile");  // used to make sure it compiles
0082 }
0083 
0084 // Returns a specific value from the aIndex set of attributes.
0085 const std::string& DDXMLElement::get(const std::string& name, const size_t aIndex) const {
0086   static const std::string sts;
0087   if (aIndex < attributes_.size()) {
0088     DDXMLAttribute::const_iterator it = attributes_[aIndex].find(name);
0089     if (attributes_[aIndex].end() == it) {
0090       return sts;
0091     } else
0092       return (it->second);
0093   }
0094   std::string msg = "DDXMLElement:get failed.  It was asked for attribute " + name;
0095   msg += " in position " + std::to_string(aIndex) + " when there are only ";
0096   msg += std::to_string(attributes_.size()) + " in the element storage.\n";
0097   throwError(msg);
0098   // meaningless...
0099   return sts;
0100 }
0101 
0102 // Returns a specific set of values as a std::vector of std::strings,
0103 // given the attribute name.
0104 std::vector<std::string> DDXMLElement::getVectorAttribute(const std::string& name) {
0105   //  The idea here is that the attributeAccumulator_ is a cache of
0106   //  on-the-fly generation from the std::vector<DDXMLAttribute> and the
0107   //  reason is simply to speed things up if it is requested more than once.
0108   std::vector<std::string> tv;
0109   AttrAccumType::const_iterator ita = attributeAccumulator_.find(name);
0110   if (ita != attributeAccumulator_.end()) {
0111     tv = attributeAccumulator_[name];
0112     if (tv.size() < attributes_.size()) {
0113       appendAttributes(tv, name);
0114     }
0115   } else {
0116     if (!attributes_.empty()) {
0117       appendAttributes(tv, name);
0118     } else {
0119       //      throw cms::Exception("DDException") << msg;
0120     }
0121   }
0122   return tv;
0123 }
0124 
0125 // Default do-nothing processElementBases.
0126 void DDXMLElement::processElement(const std::string& name, const std::string& nmspace, DDCompactView& cpv) {
0127   loadText(std::string());
0128   if (autoClear_)
0129     clear();
0130 }
0131 
0132 void DDXMLElement::loadText(const std::string& inText) { text_.emplace_back(inText); }
0133 
0134 void DDXMLElement::appendText(const std::string& inText) {
0135   static const std::string cr("\n");
0136   if (!text_.empty()) {
0137     text_[text_.size() - 1] += cr;
0138     text_[text_.size() - 1] += inText;
0139   } else {
0140     std::string msg = "DDXMLElement::appendText could not append to non-existent text.";
0141     throwError(msg);
0142   }
0143 }
0144 
0145 const std::string DDXMLElement::getText(size_t tindex) const {
0146   if (tindex > text_.size()) {
0147     std::string msg = "DDXMLElement::getText tindex is greater than text_.size()).";
0148     throwError(msg);
0149   }
0150   return text_[tindex];
0151 }
0152 
0153 bool DDXMLElement::gotText(void) const {
0154   if (!text_.empty())
0155     return true;
0156   return false;
0157 }
0158 
0159 std::ostream& operator<<(std::ostream& os, const DDXMLElement& element) {
0160   element.stream(os);
0161   return os;
0162 }
0163 
0164 void DDXMLElement::stream(std::ostream& os) const {
0165   os << "Output of current element attributes:" << std::endl;
0166   for (const auto& attribute : attributes_) {
0167     for (DDXMLAttribute::const_iterator it = attribute.begin(); it != attribute.end(); ++it)
0168       os << it->first << " = " << it->second << "\t";
0169     os << std::endl;
0170   }
0171 }
0172 
0173 void DDXMLElement::appendAttributes(std::vector<std::string>& tv, const std::string& name) {
0174   for (size_t i = tv.size(); i < attributes_.size(); ++i) {
0175     DDXMLAttribute::const_iterator itnv = attributes_[i].find(name);
0176     if (itnv != attributes_[i].end())
0177       tv.emplace_back(itnv->second);
0178     else
0179       tv.emplace_back("");
0180   }
0181 }
0182 
0183 // Number of elements accumulated.
0184 size_t DDXMLElement::size(void) const { return attributes_.size(); }
0185 
0186 std::vector<DDXMLAttribute>::const_iterator DDXMLElement::begin(void) {
0187   myIter_ = attributes_.begin();
0188   return attributes_.begin();
0189 }
0190 
0191 std::vector<DDXMLAttribute>::const_iterator DDXMLElement::end(void) {
0192   myIter_ = attributes_.end();
0193   return attributes_.end();
0194 }
0195 
0196 std::vector<DDXMLAttribute>::const_iterator& DDXMLElement::operator++(int inc) {
0197   myIter_ = myIter_ + inc;
0198   return myIter_;
0199 }
0200 
0201 const std::string& DDXMLElement::parent(void) const { return parentElement_; }
0202 
0203 void DDXMLElement::setParent(const std::string& pename) { parentElement_ = pename; }
0204 
0205 void DDXMLElement::setSelf(const std::string& sename) { myElement_ = sename; }
0206 
0207 bool DDXMLElement::isEmpty(void) const { return (attributes_.empty() ? true : false); }
0208 
0209 void DDXMLElement::throwError(const std::string& keyMessage) const {
0210   std::string msg = keyMessage + "\n";
0211   msg += " Element " + myElement_ + "\n";
0212 
0213   throw cms::Exception("DDException") << msg;
0214 }