CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/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     pair <std::string, std::string> pss;
00123     pss.first = filename;
00124     pss.second = absoluteFileName; //url+filename;
00125     int fIndex = nFiles_;
00126     fileNames_[nFiles_] = pss;
00127     ++nFiles_;
00128     parsed_[fIndex]=false;
00129 
00130     currFileName_ = fileNames_[fIndex].second;
00131 
00132     // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00133     // this because of CMSSW rules. but keep the commented way I used to
00134     // do it...
00135     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00136     //         {
00137     SAX2Parser_->setContentHandler(expHandler_);
00138     expHandler_->setNameSpace( getNameSpace(filename) );
00139     //    std::cout << "0) namespace = " << getNameSpace(filename) << std::endl;
00140     LogDebug ("DDLParser") << "ParseOneFile() Parsing: " << fileNames_[fIndex].second << std::endl;
00141     parseFile ( fIndex );
00142 
00143     //         }
00144     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00145     //         edm::LogError ("DDLParser") << "\nDDLParser::ParseOneFile, PASS1: XMLException while processing files... \n"
00146     //              << "Exception message is: \n"
00147     //              << StrX(toCatch.getMessage()) << "\n" ;
00148     //         XMLPlatformUtils::Terminate();
00149     //         throw (DDException("  See XMLException above. "));
00150     //       }
00151 
00152     // PASS 2:
00153 
00154     DCOUT_V('P', "DDLParser::ParseOneFile(): PASS2: Just before setting Xerces content and error handlers... ");
00155 
00156     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00157     //         {
00158 
00159     SAX2Parser_->setContentHandler(fileHandler_);
00160     //      std::cout << "currFileName = " << currFileName_ << std::endl;
00161     fileHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
00162     //      std::cout << "1)  namespace = " << getNameSpace(currFileName_) << std::endl;
00163     parseFile ( fIndex );
00164     parsed_[fIndex] = true;
00165 
00166     //         }
00167     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00168     //         edm::LogError ("DDLParser") << "\nDDLParser::ParseOneFile, PASS2: XMLException while processing files... \n"
00169     //              << "Exception message is: \n"
00170     //              << StrX(toCatch.getMessage()) << "\n" ;
00171     //         XMLPlatformUtils::Terminate();
00172     //         throw (DDException("  See XMLException above."));
00173     //       }
00174   }
00175   else // was found and is parsed...
00176   {
00177     DCOUT('P', " WARNING: DDLParser::ParseOneFile() file " + filename
00178           + " was already parsed as " + fileNames_[foundFile].second);
00179     return true;
00180   }
00181   return false;
00182 }
00183 
00184 //  This is for parsing the content of a blob stored in the conditions system of CMS.
00185 void
00186 DDLParser::parse( const std::vector<unsigned char>& ablob, unsigned int bsize )
00187 {
00188   char* dummy(0);
00189   MemBufInputSource  mbis( &*ablob.begin(), bsize, dummy );
00190   SAX2Parser_->parse(mbis);
00191 }
00192 
00193 std::vector < std::string >
00194 DDLParser::getFileList( void ) 
00195 {
00196   std::vector<std::string> flist;
00197   for (FileNameHolder::const_iterator fit = fileNames_.begin(); fit != fileNames_.end(); ++fit)
00198   {
00199     flist.push_back(fit->second.first); // was .second (mec: 2003:02:19
00200   }
00201   return flist;
00202 }
00203 
00204 void
00205 DDLParser::dumpFileList( void )
00206 {
00207   edm::LogInfo ("DDLParser") << "File List:" << std::endl;
00208   for (FileNameHolder::const_iterator it = fileNames_.begin(); it != fileNames_.end(); ++it)
00209     edm::LogInfo ("DDLParser") << it->second.second << std::endl;
00210 }
00211 
00212 void
00213 DDLParser::dumpFileList( ostream& co )
00214 {
00215   co << "File List:" << std::endl;
00216   for (FileNameHolder::const_iterator it = fileNames_.begin(); it != fileNames_.end(); ++it)
00217     co << it->second.second << std::endl;
00218 }
00219 
00220 int
00221 DDLParser::parse( const DDLDocumentProvider& dp )
00222 {
00223   //  edm::LogInfo ("DDLParser") << "Start Parsing.  Validation is set to " << dp.doValidation() << "." << std::endl;
00224   edm::LogInfo ("DDLParser") << "Start Parsing.  Validation is set off for the time being." << std::endl;
00225   // prep for pass 1 through DDD XML
00226   //   // Since this block does nothing for CMSSW right now, I have taken it all out
00227   //   This clean-up involves interface changes such as the removal of doValidation() everywhere (OR NOT 
00228   //   if I decide to keep it for other testing reasons.)
00229   //    if (dp.doValidation())
00230   //      { 
00231   // //       DCOUT_V('P', "WARNING:  PARSER VALIDATION IS TURNED OFF REGARDLESS OF <Schema... ELEMENT");
00232   //   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, true);
00233   //   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
00234   // //       //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
00235   //      }
00236   //    else
00237   //     {
00238   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, false);
00239   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);
00240   //       //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
00241 
00242   //     }
00243 
00244   //  This need be only done once, so might as well to it here.
00245   size_t fileIndex = 0;
00246   std::vector<std::string> fullFileName;
00247 
00248   for (; fileIndex < (dp.getFileList()).size(); ++fileIndex)
00249   { 
00250     std::string ts = dp.getURLList()[fileIndex];
00251     std::string tf = dp.getFileList()[fileIndex];
00252     if ( ts.size() > 0 ) {
00253       if ( ts[ts.size() - 1] == '/') {
00254         fullFileName.push_back( ts + tf );
00255       } else {
00256         fullFileName.push_back( ts + "/" + tf );
00257       }
00258     } else {
00259       fullFileName.push_back( tf );
00260     }
00261   }
00262 
00263   for (std::vector<std::string>::const_iterator fnit = fullFileName.begin(); 
00264        fnit != fullFileName.end();
00265        ++fnit)
00266   {
00267     size_t foundFile = isFound(extractFileName( *fnit )); 
00268         
00269     if (!foundFile)
00270     {
00271       pair <std::string, std::string> pss;
00272       pss.first = extractFileName( *fnit );
00273       pss.second = *fnit;
00274       fileNames_[nFiles_++] = pss;
00275       parsed_[nFiles_ - 1]=false;
00276     }
00277   }
00278     
00279   // Start processing the files found in the config file.
00280   
00281   // PASS 1:  This was added later (historically) to implement the DDD
00282   // requirement for Expressions.
00283   DCOUT('P', "DDLParser::parse(): PASS1: Just before setting Xerces content and error handlers... ");
00284   
00285   
00286   // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00287   // this because of CMSSW rules. but keep the commented way I used to
00288   // do it...
00289   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00290   //     {
00291   SAX2Parser_->setContentHandler(expHandler_);
00292   for (size_t i = 0; i < fileNames_.size(); ++i)
00293   {
00294     //    seal::SealTimer t("DDLParser: parsing expressions of file " +fileNames_[i].first);
00295     if (!parsed_[i])
00296     {
00297       currFileName_ = fileNames_[i].second;
00298       //              std::cout << "currFileName = " << currFileName_ << std::endl;
00299       expHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
00300       //              std::cout << "2)  namespace = " << getNameSpace(extractFileName(currFileName_)) << std::endl;
00301       parseFile(i);
00302     }
00303   }
00304   expHandler_->dumpElementTypeCounter();
00305   //     }
00306   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00307   //     edm::LogInfo ("DDLParser") << "\nPASS1: XMLException while processing files... \n"
00308   //     << "Exception message is: \n"
00309   //     << StrX(toCatch.getMessage()) << "\n" ;
00310   //     XMLPlatformUtils::Terminate();
00311   //     // FIX use this after DEPRECATED stuff removed:    throw(DDException("See XML Exception above"));
00312   //     return -1;
00313   //   }
00314   // PASS 2:
00315 
00316   DCOUT('P', "DDLParser::parse(): PASS2: Just before setting Xerces content and error handlers... ");
00317 
00318   // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00319   // this because of CMSSW rules. but keep the commented way I used to
00320   // do it...
00321   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00322   //     {
00323   SAX2Parser_->setContentHandler(fileHandler_);
00324 
00325   // No need to validate (regardless of user's doValidation
00326   // because the files have already been validated on the first pass.
00327   // This optimization suggested by Martin Liendl.
00328   //       SAX2Parser_->setFeature(StrX("http://xml.org/sax/features/validation"), false);   // optional
00329   //       SAX2Parser_->setFeature(StrX("http://xml.org/sax/features/namespaces"), false);   // optional
00330   //       SAX2Parser_->setFeature(StrX("http://apache.org/xml/features/validation/dynamic"), false);
00331 
00332 
00333   // Process files again.
00334   for (size_t i = 0; i < fileNames_.size(); ++i)
00335   {
00336     //    seal::SealTimer t("DDLParser: parsing all elements of file " +fileNames_[i].first);
00337     if (!parsed_[i]) {
00338       currFileName_ = fileNames_[i].second;
00339       //            std::cout << "currFileName = " << currFileName_ << std::endl;
00340       fileHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
00341       //            std::cout << "3)  namespace = " << getNameSpace(extractFileName(currFileName_)) << std::endl;
00342       parseFile(i);
00343       parsed_[i] = true;
00344       pair<std::string, std::string> namePair = fileNames_[i];
00345       LogDebug ("DDLParser") << "Completed parsing file " << namePair.second << std::endl;
00346     }
00347   }
00348   //     }
00349   //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
00350   //     edm::LogError ("DDLParser") << "\nPASS2: XMLException while processing files... \n"
00351   //     << "Exception message is: \n"
00352   //     << StrX(toCatch.getMessage()) << "\n" ;
00353   //     XMLPlatformUtils::Terminate();
00354   //     return -1;
00355   //   }
00356   return 0;
00357 }
00358 
00359 void
00360 DDLParser::parseFile( const int& numtoproc ) 
00361 {
00362   if (!parsed_[numtoproc])
00363   {
00364     const std::string & fname = fileNames_[numtoproc].second;
00365 
00366     // in cleaning up try-catch blocks 2007-06-26 I decided to remove
00367     // this because of CMSSW rules. but keep the commented way I used to
00368     // do it...
00369     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
00370     //  {
00371     currFileName_ = fname;
00372     SAX2Parser_->parse(currFileName_.c_str());
00373     //  }
00374     //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch)
00375     //  {
00376     //    std::string e("\nWARNING: DDLParser::parseFile, File: '");
00377     //    e += currFileName_ + "'\n"
00378     //      + "Exception message is: \n"
00379     //      + std::string(StrX(toCatch.getMessage()).localForm()) + "\n";
00380     //    throw(DDException(e));
00381     //  }
00382   }
00383   else
00384   {
00385     DCOUT('P', "\nWARNING: File " + fileNames_[numtoproc].first 
00386           + " has already been processed as " + fileNames_[numtoproc].second);
00387   }
00388 }
00389 
00390 // Return the name of the Current file being processed by the parser.
00391 std::string
00392 DDLParser::getCurrFileName( void )
00393 {
00394   return currFileName_;
00395 }
00396 
00397 void
00398 DDLParser::clearFiles( void )
00399 {
00400   fileNames_.clear();
00401   parsed_.clear();
00402 }
00403 
00404 std::string
00405 DDLParser::extractFileName( std::string fullname )
00406 {
00407   std::string ret = "";
00408   size_t bit = fullname.rfind('/');
00409   if ( bit < fullname.size() - 2 ) {
00410     ret=fullname.substr(bit+1);
00411   }
00412   return ret;
00413 }
00414 
00415 std::string
00416 DDLParser::getNameSpace( const std::string& fname )
00417 {
00418   size_t j = 0;
00419   std::string ret="";
00420   while (j < fname.size() && fname[j] != '.')
00421     ++j;
00422   if (j < fname.size() && fname[j] == '.')
00423     ret = fname.substr(0, j);
00424   return ret;
00425 }