CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/DetectorDescription/Parser/src/DDLParser.cc

Go to the documentation of this file.
00001 /***************************************************************************
00002                           DDLParser.cc  -  description
00003                              -------------------
00004     begin                : Mon Oct 22 2001
00005     email                : case@ucdhep.ucdavis.edu
00006 ***************************************************************************/
00007 
00008 /***************************************************************************
00009  *                                                                         *
00010  *           DDDParser sub-component of DDD                                *
00011  *                                                                         *
00012  ***************************************************************************/
00013 
00014 #include "DetectorDescription/Parser/interface/DDLParser.h"
00015 #include "DetectorDescription/Parser/interface/DDLDocumentProvider.h"
00016 
00017 #include "DetectorDescription/Base/interface/DDdebug.h"
00018 #include "DetectorDescription/Algorithm/src/AlgoInit.h"
00019 
00020 #include <xercesc/framework/MemBufInputSource.hpp>
00021 #include "FWCore/ParameterSet/interface/FileInPath.h"
00022 
00023 #include <iostream>
00024 
00025 using namespace std;
00026 
00027 using namespace XERCES_CPP_NAMESPACE;
00028 
00030 DDLParser::DDLParser( DDCompactView& cpv )
00031   : cpv_( cpv ),
00032     nFiles_( 0 )
00033 {
00034   XMLPlatformUtils::Initialize();
00035   AlgoInit();
00036   SAX2Parser_  = XMLReaderFactory::createXMLReader();
00037   
00038   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, false);   // optional
00039   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);   // optional
00040   // Specify other parser features, e.g.
00041   //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
00042   
00043   expHandler_  = new DDLSAX2ExpressionHandler(cpv);
00044   fileHandler_ = new DDLSAX2FileHandler(cpv);
00045   errHandler_  = new DDLSAX2Handler();
00046   SAX2Parser_->setErrorHandler(errHandler_); 
00047   SAX2Parser_->setContentHandler(fileHandler_); 
00048   
00049   DCOUT_V('P', "DDLParser::DDLParser(): new (and only) DDLParser"); 
00050 }
00051 
00053 DDLParser::~DDLParser( void )
00054 { 
00055   // clean up and leave
00056   delete expHandler_;
00057   delete fileHandler_;
00058   delete errHandler_;
00059   XMLPlatformUtils::Terminate();
00060   DCOUT_V('P', "DDLParser::~DDLParser(): destruct DDLParser"); 
00061 }
00062 
00067 SAX2XMLReader*
00068 DDLParser::getXMLParser( void )
00069 {
00070   return SAX2Parser_;
00071 }
00072 
00073 DDLSAX2FileHandler*
00074 DDLParser::getDDLSAX2FileHandler( void )
00075 { 
00076   return fileHandler_; 
00077 }
00078 
00079 size_t
00080 DDLParser::isFound( const std::string& filename )
00081 {
00082   FileNameHolder::const_iterator it = fileNames_.begin();
00083   size_t i = 1;
00084   bool foundFile = false;
00085   while( it != fileNames_.end() && !foundFile )
00086   {
00087     if( it->second.first == filename )
00088     {
00089       foundFile = true;
00090     }
00091     else ++i;
00092     ++it;
00093   }
00094   if( foundFile )
00095     return i;
00096   return 0;
00097 }
00098 
00099 bool
00100 DDLParser::isParsed( const std::string& filename )
00101 {
00102   size_t found = isFound(filename);
00103   if (found)
00104     return parsed_[found];
00105   return false;
00106 }
00107 
00108 // Must receive a filename and path relative to the src directory of a CMSSW release
00109 // e.g. DetectorDescription/test/myfile.xml
00110 bool
00111 DDLParser::parseOneFile( const std::string& fullname ) //, const std::string& url)
00112 {
00113   //  std::string filename = expHandler_->extractFileName(fullname);
00114   std::string filename = extractFileName(fullname);
00115   //  std::cout << "parseOneFile - fullname = " << fullname << std::endl;
00116   //  std::cout << "parseOneFile - filename = " << filename << std::endl;
00117   edm::FileInPath fp(fullname);
00118   std::string absoluteFileName = fp.fullPath();
00119   size_t foundFile = isFound(filename);
00120   if (!foundFile)
00121   {
00122     int fIndex = foundFile;
00123     pair <std::string, std::string> pss;
00124     pss.first = filename;
00125     pss.second = absoluteFileName; //url+filename;
00126     fIndex = nFiles_;
00127     fileNames_[nFiles_] = pss;
00128     ++nFiles_;
00129     parsed_[fIndex]=false;
00130 
00131     currFileName_ = fileNames_[fIndex].second;
00132 
00133     // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00134     // this because of CMSSW rules. but keep the commented way I used to
00135     // do it...
00136     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00137     //         {
00138     SAX2Parser_->setContentHandler(expHandler_);
00139     expHandler_->setNameSpace( getNameSpace(filename) );
00140     //    std::cout << "0) namespace = " << getNameSpace(filename) << std::endl;
00141     LogDebug ("DDLParser") << "ParseOneFile() Parsing: " << fileNames_[fIndex].second << std::endl;
00142     parseFile ( fIndex );
00143 
00144     //         }
00145     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00146     //         edm::LogError ("DDLParser") << "\nDDLParser::ParseOneFile, PASS1: XMLException while processing files... \n"
00147     //              << "Exception message is: \n"
00148     //              << StrX(toCatch.getMessage()) << "\n" ;
00149     //         XMLPlatformUtils::Terminate();
00150     //         throw (DDException("  See XMLException above. "));
00151     //       }
00152 
00153     // PASS 2:
00154 
00155     DCOUT_V('P', "DDLParser::ParseOneFile(): PASS2: Just before setting Xerces content and error handlers... ");
00156 
00157     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00158     //         {
00159 
00160     SAX2Parser_->setContentHandler(fileHandler_);
00161     //      std::cout << "currFileName = " << currFileName_ << std::endl;
00162     fileHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
00163     //      std::cout << "1)  namespace = " << getNameSpace(currFileName_) << std::endl;
00164     parseFile ( fIndex );
00165     parsed_[fIndex] = true;
00166 
00167     //         }
00168     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00169     //         edm::LogError ("DDLParser") << "\nDDLParser::ParseOneFile, PASS2: XMLException while processing files... \n"
00170     //              << "Exception message is: \n"
00171     //              << StrX(toCatch.getMessage()) << "\n" ;
00172     //         XMLPlatformUtils::Terminate();
00173     //         throw (DDException("  See XMLException above."));
00174     //       }
00175   }
00176   else // was found and is parsed...
00177   {
00178     DCOUT('P', " WARNING: DDLParser::ParseOneFile() file " + filename
00179           + " was already parsed as " + fileNames_[foundFile].second);
00180     return true;
00181   }
00182   return false;
00183 }
00184 
00185 //  This is for parsing the content of a blob stored in the conditions system of CMS.
00186 void
00187 DDLParser::parse( const std::vector<unsigned char>& ablob, unsigned int bsize )
00188 {
00189   char* dummy(0);
00190   MemBufInputSource  mbis( &*ablob.begin(), bsize, dummy );
00191   SAX2Parser_->parse(mbis);
00192 }
00193 
00194 std::vector < std::string >
00195 DDLParser::getFileList( void ) 
00196 {
00197   std::vector<std::string> flist;
00198   for (FileNameHolder::const_iterator fit = fileNames_.begin(); fit != fileNames_.end(); ++fit)
00199   {
00200     flist.push_back(fit->second.first); // was .second (mec: 2003:02:19
00201   }
00202   return flist;
00203 }
00204 
00205 void
00206 DDLParser::dumpFileList( void )
00207 {
00208   edm::LogInfo ("DDLParser") << "File List:" << std::endl;
00209   for (FileNameHolder::const_iterator it = fileNames_.begin(); it != fileNames_.end(); ++it)
00210     edm::LogInfo ("DDLParser") << it->second.second << std::endl;
00211 }
00212 
00213 void
00214 DDLParser::dumpFileList( ostream& co )
00215 {
00216   co << "File List:" << std::endl;
00217   for (FileNameHolder::const_iterator it = fileNames_.begin(); it != fileNames_.end(); ++it)
00218     co << it->second.second << std::endl;
00219 }
00220 
00221 int
00222 DDLParser::parse( const DDLDocumentProvider& dp )
00223 {
00224   //  edm::LogInfo ("DDLParser") << "Start Parsing.  Validation is set to " << dp.doValidation() << "." << std::endl;
00225   edm::LogInfo ("DDLParser") << "Start Parsing.  Validation is set off for the time being." << std::endl;
00226   // prep for pass 1 through DDD XML
00227   //   // Since this block does nothing for CMSSW right now, I have taken it all out
00228   //   This clean-up involves interface changes such as the removal of doValidation() everywhere (OR NOT 
00229   //   if I decide to keep it for other testing reasons.)
00230   //    if (dp.doValidation())
00231   //      { 
00232   // //       DCOUT_V('P', "WARNING:  PARSER VALIDATION IS TURNED OFF REGARDLESS OF <Schema... ELEMENT");
00233   //   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, true);
00234   //   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
00235   // //       //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
00236   //      }
00237   //    else
00238   //     {
00239   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, false);
00240   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);
00241   //       //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
00242 
00243   //     }
00244 
00245   //  This need be only done once, so might as well to it here.
00246   size_t fileIndex = 0;
00247   std::vector<std::string> fullFileName;
00248 
00249   for (; fileIndex < (dp.getFileList()).size(); ++fileIndex)
00250   { 
00251     std::string ts = dp.getURLList()[fileIndex];
00252     std::string tf = dp.getFileList()[fileIndex];
00253     if ( ts.size() > 0 ) {
00254       if ( ts[ts.size() - 1] == '/') {
00255         fullFileName.push_back( ts + tf );
00256       } else {
00257         fullFileName.push_back( ts + "/" + tf );
00258       }
00259     } else {
00260       fullFileName.push_back( tf );
00261     }
00262   }
00263 
00264   for (std::vector<std::string>::const_iterator fnit = fullFileName.begin(); 
00265        fnit != fullFileName.end();
00266        ++fnit)
00267   {
00268     size_t foundFile = isFound(extractFileName( *fnit )); 
00269         
00270     if (!foundFile)
00271     {
00272       pair <std::string, std::string> pss;
00273       pss.first = extractFileName( *fnit );
00274       pss.second = *fnit;
00275       fileNames_[nFiles_++] = pss;
00276       parsed_[nFiles_ - 1]=false;
00277     }
00278   }
00279     
00280   // Start processing the files found in the config file.
00281   
00282   // PASS 1:  This was added later (historically) to implement the DDD
00283   // requirement for Expressions.
00284   DCOUT('P', "DDLParser::parse(): PASS1: Just before setting Xerces content and error handlers... ");
00285   
00286   
00287   // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00288   // this because of CMSSW rules. but keep the commented way I used to
00289   // do it...
00290   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00291   //     {
00292   SAX2Parser_->setContentHandler(expHandler_);
00293   for (size_t i = 0; i < fileNames_.size(); ++i)
00294   {
00295     //    seal::SealTimer t("DDLParser: parsing expressions of file " +fileNames_[i].first);
00296     if (!parsed_[i])
00297     {
00298       currFileName_ = fileNames_[i].second;
00299       //              std::cout << "currFileName = " << currFileName_ << std::endl;
00300       expHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
00301       //              std::cout << "2)  namespace = " << getNameSpace(extractFileName(currFileName_)) << std::endl;
00302       parseFile(i);
00303     }
00304   }
00305   expHandler_->dumpElementTypeCounter();
00306   //     }
00307   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00308   //     edm::LogInfo ("DDLParser") << "\nPASS1: XMLException while processing files... \n"
00309   //     << "Exception message is: \n"
00310   //     << StrX(toCatch.getMessage()) << "\n" ;
00311   //     XMLPlatformUtils::Terminate();
00312   //     // FIX use this after DEPRECATED stuff removed:    throw(DDException("See XML Exception above"));
00313   //     return -1;
00314   //   }
00315   // PASS 2:
00316 
00317   DCOUT('P', "DDLParser::parse(): PASS2: Just before setting Xerces content and error handlers... ");
00318 
00319   // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00320   // this because of CMSSW rules. but keep the commented way I used to
00321   // do it...
00322   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00323   //     {
00324   SAX2Parser_->setContentHandler(fileHandler_);
00325 
00326   // No need to validate (regardless of user's doValidation
00327   // because the files have already been validated on the first pass.
00328   // This optimization suggested by Martin Liendl.
00329   //       SAX2Parser_->setFeature(StrX("https://xml.org/sax/features/validation"), false);   // optional
00330   //       SAX2Parser_->setFeature(StrX("https://xml.org/sax/features/namespaces"), false);   // optional
00331   //       SAX2Parser_->setFeature(StrX("https://apache.org/xml/features/validation/dynamic"), false);
00332 
00333 
00334   // Process files again.
00335   for (size_t i = 0; i < fileNames_.size(); ++i)
00336   {
00337     //    seal::SealTimer t("DDLParser: parsing all elements of file " +fileNames_[i].first);
00338     if (!parsed_[i]) {
00339       currFileName_ = fileNames_[i].second;
00340       //            std::cout << "currFileName = " << currFileName_ << std::endl;
00341       fileHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
00342       //            std::cout << "3)  namespace = " << getNameSpace(extractFileName(currFileName_)) << std::endl;
00343       parseFile(i);
00344       parsed_[i] = true;
00345       pair<std::string, std::string> namePair = fileNames_[i];
00346       LogDebug ("DDLParser") << "Completed parsing file " << namePair.second << std::endl;
00347     }
00348   }
00349   //     }
00350   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00351   //     edm::LogError ("DDLParser") << "\nPASS2: XMLException while processing files... \n"
00352   //     << "Exception message is: \n"
00353   //     << StrX(toCatch.getMessage()) << "\n" ;
00354   //     XMLPlatformUtils::Terminate();
00355   //     return -1;
00356   //   }
00357   return 0;
00358 }
00359 
00360 void
00361 DDLParser::parseFile( const int& numtoproc ) 
00362 {
00363   if (!parsed_[numtoproc])
00364   {
00365     const std::string & fname = fileNames_[numtoproc].second;
00366 
00367     // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00368     // this because of CMSSW rules. but keep the commented way I used to
00369     // do it...
00370     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00371     //  {
00372     currFileName_ = fname;
00373     SAX2Parser_->parse(currFileName_.c_str());
00374     //  }
00375     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch)
00376     //  {
00377     //    std::string e("\nWARNING: DDLParser::parseFile, File: '");
00378     //    e += currFileName_ + "'\n"
00379     //      + "Exception message is: \n"
00380     //      + std::string(StrX(toCatch.getMessage()).localForm()) + "\n";
00381     //    throw(DDException(e));
00382     //  }
00383   }
00384   else
00385   {
00386     DCOUT('P', "\nWARNING: File " + fileNames_[numtoproc].first 
00387           + " has already been processed as " + fileNames_[numtoproc].second);
00388   }
00389 }
00390 
00391 // Return the name of the Current file being processed by the parser.
00392 std::string
00393 DDLParser::getCurrFileName( void )
00394 {
00395   return currFileName_;
00396 }
00397 
00398 void
00399 DDLParser::clearFiles( void )
00400 {
00401   fileNames_.clear();
00402   parsed_.clear();
00403 }
00404 
00405 std::string
00406 DDLParser::extractFileName( std::string fullname )
00407 {
00408   std::string ret = "";
00409   size_t bit = fullname.rfind('/');
00410   if ( bit < fullname.size() - 2 ) {
00411     ret=fullname.substr(bit+1);
00412   }
00413   return ret;
00414 }
00415 
00416 std::string
00417 DDLParser::getNameSpace( const std::string& fname )
00418 {
00419   size_t j = 0;
00420   std::string ret="";
00421   while (j < fname.size() && fname[j] != '.')
00422     ++j;
00423   if (j < fname.size() && fname[j] == '.')
00424     ret = fname.substr(0, j);
00425   return ret;
00426 }