CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/DetectorDescription/Parser/src/DDXMLElement.cc

Go to the documentation of this file.
00001 /***************************************************************************
00002                           DDXMLElement.cc  -  description
00003                              -------------------
00004     begin                : Fri Mar 15 2002
00005     email                : case@ucdhep.ucdavis.edu
00006  ***************************************************************************/
00007 
00008 #include "DetectorDescription/Parser/src/DDXMLElement.h"
00009 #include "DetectorDescription/Base/interface/DDdebug.h"
00010 
00011 #include <algorithm>
00012 #include <iostream>
00013 #include <sstream>
00014 
00015 DDXMLElement::DDXMLElement( DDLElementRegistry* myreg )
00016   : myRegistry_( myreg ),
00017     attributes_(),
00018     text_(),
00019     autoClear_( false )
00020 {}
00021 
00022 DDXMLElement::DDXMLElement( DDLElementRegistry* myreg, const bool& clearme )
00023   : myRegistry_( myreg ),
00024     attributes_(),
00025     text_(),
00026     autoClear_( clearme )
00027 {}
00028 
00029 DDXMLElement::~DDXMLElement( void )
00030 {}
00031 
00032 // For pre-processing, after attributes are loaded.  Default, do nothing!
00033 void
00034 DDXMLElement::preProcessElement( const std::string& name, const std::string& nmspace, DDCompactView& cpv )
00035 {
00036   DCOUT_V('P', "DDXMLElement::preProcessElementBase default, do nothing) started-completed.");
00037 }
00038 
00039 // This loads the attributes into the attributes_ std::vector.
00040 void
00041 DDXMLElement::loadAttributes( const std::string& elemName,
00042                               const std::vector<std::string> & names,
00043                               const std::vector<std::string> & values,
00044                               const std::string& nmspace, DDCompactView& cpv )
00045 {
00046   attributes_.resize(attributes_.size()+1);
00047   DDXMLAttribute & tAttributes =  attributes_.back();
00048   
00049   // adds attributes
00050   for (size_t i = 0; i < names.size(); ++i)
00051   {
00052     tAttributes.insert(std::make_pair(names[i], values[i]));
00053   }
00054 
00055   preProcessElement( elemName, nmspace, cpv );
00056   DCOUT_V('P', "DDXMLElement::loadAttributes completed. " << *this);
00057 }
00058 
00059 // clear data.
00060 void
00061 DDXMLElement::clear( void )
00062 {
00063   text_.clear();
00064   attributes_.clear();
00065   attributeAccumulator_.clear();
00066 }
00067 
00068 // Access to current attributes by name.
00069 const std::string &
00070 DDXMLElement::getAttribute( const std::string& name ) const
00071 {
00072   static const std::string ldef;
00073   if (attributes_.size())
00074     return get(name, attributes_.size() - 1);
00075   return ldef;
00076 }
00077 
00078 const DDXMLAttribute&
00079 DDXMLElement::getAttributeSet( size_t aIndex ) const 
00080 {
00081   return attributes_[aIndex];  
00082 }
00083 
00084 
00085 const DDName
00086 DDXMLElement::getDDName( const std::string& defaultNS, const std::string& attname, size_t aIndex )
00087 {
00088   if (aIndex < attributes_.size()
00089       && attributes_[aIndex].find(attname) != attributes_[aIndex].end()) { 
00090     std::string ns = defaultNS;
00091     // For the user to fully control namespaces they must provide for 
00092     // all name attributes something of the form, for example:
00093     //        <Solid name="ns:name" ...
00094     // If defaultNS is "!" (magic I don't like) then find and set
00095     // the namespace properly.
00096     if ( defaultNS == "!" ) {
00097       ns = "";
00098     } 
00099     const std::string & name = attributes_[aIndex].find(attname)->second;
00100     std::string rn = name;
00101     size_t foundColon= name.find(':');
00102     if (foundColon != std::string::npos) {
00103       ns = name.substr(0,foundColon);
00104       rn = name.substr(foundColon+1);
00105 
00106     }
00107     return DDName(rn, ns);
00108   }
00109   std::string msg = "DDXMLElement:getDDName failed.  It was asked to make ";
00110   msg += "a DDName using attribute: " + attname;
00111   msg += " in position: " + itostr(int(aIndex)) + ".  There are ";
00112   msg += itostr(int(attributes_.size())) + " entries in the element.";
00113   throwError(msg);
00114   return DDName("justToCompile", "justToCompile"); // used to make sure it compiles
00115 } 
00116 
00117 // Returns a specific value from the aIndex set of attributes.
00118 const std::string &
00119 DDXMLElement::get( const std::string& name, const size_t aIndex ) const
00120 {
00121   static const std::string sts;
00122   if (aIndex < attributes_.size())
00123   {
00124     DDXMLAttribute::const_iterator it = attributes_[aIndex].find(name);
00125     if (attributes_[aIndex].end() == it)
00126     {
00127       DCOUT_V('P', "WARNING: DDXMLElement::get did not find the requested attribute: "  << name << std::endl << *this);
00128       return sts;
00129     }
00130     else
00131       return (it->second);
00132   }
00133   std::string msg = "DDXMLElement:get failed.  It was asked for attribute " + name;
00134   msg += " in position " + itostr(int(aIndex)) + " when there are only ";
00135   msg += itostr(int(attributes_.size())) + " in the element storage.\n";
00136   throwError(msg);
00137   // meaningless...
00138   return sts;
00139 }
00140 
00141 // Returns a specific set of values as a std::vector of std::strings,
00142 // given the attribute name.
00143 std::vector<std::string>
00144 DDXMLElement::getVectorAttribute( const std::string& name )
00145 {
00146   //  The idea here is that the attributeAccumulator_ is a cache of
00147   //  on-the-fly generation from the std::vector<DDXMLAttribute> and the 
00148   //  reason is simply to speed things up if it is requested more than once.
00149   std::vector<std::string> tv;
00150   AttrAccumType::const_iterator ita = attributeAccumulator_.find(name);
00151   if (ita != attributeAccumulator_.end())
00152   {
00153     tv = attributeAccumulator_[name];
00154     if (tv.size() < attributes_.size())
00155     {
00156       appendAttributes(tv, name);
00157     }
00158     DCOUT_V('P', "DDXMLElement::getAttribute found attribute named " << name << " in a map of size " << size());
00159   }
00160   else
00161   {
00162     if (attributes_.size())
00163     {
00164       appendAttributes(tv, name);
00165     }
00166     else
00167     {
00168       DCOUT_V('P', "DDXMLAttributeAccumulator::getAttribute was asked to provide a std::vector of values for an attribute named " << name << " but there was no such attribute.");
00169       //      throw cms::Exception("DDException") << msg;
00170     }
00171   } 
00172   return tv;
00173 }
00174 
00175 // Default do-nothing processElementBases.
00176 void
00177 DDXMLElement::processElement( const std::string& name, const std::string& nmspace, DDCompactView& cpv )
00178 {
00179   DCOUT_V('P', "DDXMLElement::processElementBase (default, do nothing) started-completed");
00180   loadText(std::string());
00181   if ( autoClear_ ) clear(); 
00182   
00183 }
00184 
00185 void
00186 DDXMLElement::loadText( const std::string& inText )
00187 {
00188   text_.push_back(inText);
00189 }
00190 
00191 void
00192 DDXMLElement::appendText( const std::string& inText )
00193 {
00194   static const std::string cr("\n");
00195   if (text_.size() > 0) {
00196     text_[text_.size() - 1] += cr;
00197     text_[text_.size() - 1] += inText ;
00198   } else
00199   {
00200     std::string msg = "DDXMLElement::appendText could not append to non-existent text.";
00201     throwError(msg);
00202   }
00203 }
00204 
00205 const std::string
00206 DDXMLElement::getText( size_t tindex ) const
00207 {
00208   if (tindex > text_.size()) {
00209     std::string msg = "DDXMLElement::getText tindex is greater than text_.size()).";
00210     throwError(msg);
00211   }
00212   return text_[tindex];
00213 }
00214 
00215 bool
00216 DDXMLElement::gotText( void ) const
00217 {
00218   if (text_.size() != 0)
00219     return true;
00220   return false;
00221 }
00222 
00223 std::ostream & operator<<( std::ostream & os, const DDXMLElement & element )
00224 {
00225   element.stream(os);
00226   return os;
00227 }
00228 
00229 void
00230 DDXMLElement::stream( std::ostream & os ) const
00231 {
00232   os << "Output of current element attributes:" << std::endl;
00233   for (std::vector<DDXMLAttribute>::const_iterator itv = attributes_.begin();
00234        itv != attributes_.end(); ++itv)
00235   {
00236     for (DDXMLAttribute::const_iterator it = itv->begin(); 
00237          it != itv->end(); ++it)
00238       os << it->first <<  " = " << it->second << "\t";
00239     os << std::endl;
00240   }
00241 }                        
00242 
00243 void
00244 DDXMLElement::appendAttributes( std::vector<std::string> & tv,
00245                                 const std::string& name )
00246 {
00247   for (size_t i = tv.size(); i < attributes_.size(); ++i)
00248   {
00249     DDXMLAttribute::const_iterator itnv = attributes_[i].find(name);
00250     if (itnv != attributes_[i].end())
00251       tv.push_back(itnv->second);
00252     else
00253       tv.push_back("");
00254   }  
00255 }
00256 
00257 // Number of elements accumulated.
00258 size_t
00259 DDXMLElement::size( void ) const
00260 {
00261   return attributes_.size();
00262 }
00263 
00264 std::vector<DDXMLAttribute>::const_iterator
00265 DDXMLElement::begin( void )
00266 {
00267   myIter_ = attributes_.begin();
00268   return attributes_.begin();
00269 }
00270 
00271 std::vector<DDXMLAttribute>::const_iterator
00272 DDXMLElement::end( void )
00273 {
00274   myIter_ = attributes_.end();
00275   return attributes_.end();
00276 }
00277 
00278 std::vector<DDXMLAttribute>::const_iterator&
00279 DDXMLElement::operator++( int inc )
00280 {
00281   myIter_ = myIter_ + inc;
00282   return myIter_;
00283 }
00284 
00285 const std::string&
00286 DDXMLElement::parent( void ) const
00287 {
00288   return parentElement_;
00289 }
00290 
00291 void
00292 DDXMLElement::setParent( const std::string& pename )
00293 {
00294   parentElement_ = pename;
00295 }
00296 
00297 void
00298 DDXMLElement::setSelf( const std::string& sename )
00299 {
00300   myElement_ = sename;
00301 }
00302 
00303 // yet another :-)
00304 std::string
00305 DDXMLElement::itostr( int in )
00306 {
00307   std::ostringstream ostr;
00308   ostr << in;
00309   return ostr.str();
00310 }
00311 
00312 bool
00313 DDXMLElement::isEmpty( void ) const
00314 {
00315   return (attributes_.size() == 0 ? true : false);
00316 }
00317 
00318 void
00319 DDXMLElement::throwError( const std::string& keyMessage ) const 
00320 {
00321   std::string msg = keyMessage + "\n";
00322   msg += " Element " + myElement_ +"\n";
00323 
00324   throw cms::Exception("DDException") << msg;
00325 }