PageRenderTime 64ms CodeModel.GetById 7ms app.highlight 52ms RepoModel.GetById 1ms app.codeStats 0ms

/DetectorDescription/Parser/src/DDLParser.cc

https://github.com/aivanov-cern/cmssw
C++ | 401 lines | 226 code | 47 blank | 128 comment | 32 complexity | fb56be528db7dc02f90876721ecbc4cd MD5 | raw file
  1/***************************************************************************
  2                          DDLParser.cc  -  description
  3                             -------------------
  4    begin                : Mon Oct 22 2001
  5    email                : case@ucdhep.ucdavis.edu
  6***************************************************************************/
  7
  8/***************************************************************************
  9 *                                                                         *
 10 *           DDDParser sub-component of DDD                                *
 11 *                                                                         *
 12 ***************************************************************************/
 13
 14#include "DetectorDescription/Parser/interface/DDLParser.h"
 15#include "DetectorDescription/Parser/interface/DDLDocumentProvider.h"
 16
 17#include "DetectorDescription/Base/interface/DDdebug.h"
 18
 19#include <xercesc/framework/MemBufInputSource.hpp>
 20#include "FWCore/ParameterSet/interface/FileInPath.h"
 21#include "FWCore/Concurrency/interface/Xerces.h"
 22
 23#include <iostream>
 24
 25using namespace std;
 26
 27using namespace XERCES_CPP_NAMESPACE;
 28
 29/// Constructor MUST associate a DDCompactView storage.
 30DDLParser::DDLParser( DDCompactView& cpv )
 31  : cpv_( cpv ),
 32    nFiles_( 0 )
 33{
 34  cms::concurrency::xercesInitialize();
 35  SAX2Parser_  = XMLReaderFactory::createXMLReader();
 36  
 37  SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, false);   // optional
 38  SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);   // optional
 39  // Specify other parser features, e.g.
 40  //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
 41  
 42  expHandler_  = new DDLSAX2ExpressionHandler(cpv);
 43  fileHandler_ = new DDLSAX2FileHandler(cpv);
 44  errHandler_  = new DDLSAX2Handler();
 45  SAX2Parser_->setErrorHandler(errHandler_); 
 46  SAX2Parser_->setContentHandler(fileHandler_); 
 47  
 48  DCOUT_V('P', "DDLParser::DDLParser(): new (and only) DDLParser"); 
 49}
 50
 51/// Destructor terminates the XMLPlatformUtils (as required by Xerces)
 52DDLParser::~DDLParser( void )
 53{ 
 54  // clean up and leave
 55  delete expHandler_;
 56  delete fileHandler_;
 57  delete errHandler_;
 58  cms::concurrency::xercesTerminate();
 59  DCOUT_V('P', "DDLParser::~DDLParser(): destruct DDLParser"); 
 60}
 61
 62/**  This method allows external "users" to use the current DDLParser on their own.
 63 *   by giving them access to the SAX2XMLReader.  This may not be a good idea!  The
 64 *   reason that I 
 65 */ 
 66SAX2XMLReader*
 67DDLParser::getXMLParser( void )
 68{
 69  return SAX2Parser_;
 70}
 71
 72DDLSAX2FileHandler*
 73DDLParser::getDDLSAX2FileHandler( void )
 74{ 
 75  return fileHandler_; 
 76}
 77
 78size_t
 79DDLParser::isFound( const std::string& filename )
 80{
 81  FileNameHolder::const_iterator it = fileNames_.begin();
 82  size_t i = 1;
 83  bool foundFile = false;
 84  while( it != fileNames_.end() && !foundFile )
 85  {
 86    if( it->second.first == filename )
 87    {
 88      foundFile = true;
 89    }
 90    else ++i;
 91    ++it;
 92  }
 93  if( foundFile )
 94    return i;
 95  return 0;
 96}
 97
 98bool
 99DDLParser::isParsed( const std::string& filename )
100{
101  size_t found = isFound(filename);
102  if (found)
103    return parsed_[found];
104  return false;
105}
106
107// Must receive a filename and path relative to the src directory of a CMSSW release
108// e.g. DetectorDescription/test/myfile.xml
109bool
110DDLParser::parseOneFile( const std::string& fullname ) //, const std::string& url)
111{
112  //  std::string filename = expHandler_->extractFileName(fullname);
113  std::string filename = extractFileName(fullname);
114  //  std::cout << "parseOneFile - fullname = " << fullname << std::endl;
115  //  std::cout << "parseOneFile - filename = " << filename << std::endl;
116  edm::FileInPath fp(fullname);
117  std::string absoluteFileName = fp.fullPath();
118  size_t foundFile = isFound(filename);
119  if (!foundFile)
120  {
121    pair <std::string, std::string> pss;
122    pss.first = filename;
123    pss.second = absoluteFileName; //url+filename;
124    int fIndex = nFiles_;
125    fileNames_[nFiles_] = pss;
126    ++nFiles_;
127    parsed_[fIndex]=false;
128
129    currFileName_ = fileNames_[fIndex].second;
130
131    // in cleaning up try-catch blocks 2007-06-26 I decided to remove
132    // this because of CMSSW rules. but keep the commented way I used to
133    // do it...
134    //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
135    //         {
136    SAX2Parser_->setContentHandler(expHandler_);
137    expHandler_->setNameSpace( getNameSpace(filename) );
138    //	  std::cout << "0) namespace = " << getNameSpace(filename) << std::endl;
139    LogDebug ("DDLParser") << "ParseOneFile() Parsing: " << fileNames_[fIndex].second << std::endl;
140    parseFile ( fIndex );
141
142    //         }
143    //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
144    //         edm::LogError ("DDLParser") << "\nDDLParser::ParseOneFile, PASS1: XMLException while processing files... \n"
145    //              << "Exception message is: \n"
146    //              << StrX(toCatch.getMessage()) << "\n" ;
147    //         cms::concurrency::xercesTerminate();
148    //         throw (DDException("  See XMLException above. "));
149    //       }
150
151    // PASS 2:
152
153    DCOUT_V('P', "DDLParser::ParseOneFile(): PASS2: Just before setting Xerces content and error handlers... ");
154
155    //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
156    //         {
157
158    SAX2Parser_->setContentHandler(fileHandler_);
159    //      std::cout << "currFileName = " << currFileName_ << std::endl;
160    fileHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
161    //      std::cout << "1)  namespace = " << getNameSpace(currFileName_) << std::endl;
162    parseFile ( fIndex );
163    parsed_[fIndex] = true;
164
165    //         }
166    //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
167    //         edm::LogError ("DDLParser") << "\nDDLParser::ParseOneFile, PASS2: XMLException while processing files... \n"
168    //              << "Exception message is: \n"
169    //              << StrX(toCatch.getMessage()) << "\n" ;
170    //         cms::concurrency::xercesTerminate();
171    //         throw (DDException("  See XMLException above."));
172    //       }
173  }
174  else // was found and is parsed...
175  {
176    DCOUT('P', " WARNING: DDLParser::ParseOneFile() file " + filename
177	  + " was already parsed as " + fileNames_[foundFile].second);
178    return true;
179  }
180  return false;
181}
182
183//  This is for parsing the content of a blob stored in the conditions system of CMS.
184void
185DDLParser::parse( const std::vector<unsigned char>& ablob, unsigned int bsize )
186{
187  char* dummy(0);
188  MemBufInputSource  mbis( &*ablob.begin(), bsize, dummy );
189  SAX2Parser_->parse(mbis);
190}
191
192std::vector < std::string >
193DDLParser::getFileList( void ) 
194{
195  std::vector<std::string> flist;
196  for (FileNameHolder::const_iterator fit = fileNames_.begin(); fit != fileNames_.end(); ++fit)
197  {
198    flist.push_back(fit->second.first); // was .second (mec: 2003:02:19
199  }
200  return flist;
201}
202
203int
204DDLParser::parse( const DDLDocumentProvider& dp )
205{
206  //  edm::LogInfo ("DDLParser") << "Start Parsing.  Validation is set to " << dp.doValidation() << "." << std::endl;
207  edm::LogInfo ("DDLParser") << "Start Parsing.  Validation is set off for the time being." << std::endl;
208  // prep for pass 1 through DDD XML
209  //   // Since this block does nothing for CMSSW right now, I have taken it all out
210  //   This clean-up involves interface changes such as the removal of doValidation() everywhere (OR NOT 
211  //   if I decide to keep it for other testing reasons.)
212  //    if (dp.doValidation())
213  //      { 
214  // //       DCOUT_V('P', "WARNING:  PARSER VALIDATION IS TURNED OFF REGARDLESS OF <Schema... ELEMENT");
215  //   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, true);
216  //   SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
217  // //       //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, true);
218  //      }
219  //    else
220  //     {
221  SAX2Parser_->setFeature(XMLUni::fgSAX2CoreValidation, false);
222  SAX2Parser_->setFeature(XMLUni::fgSAX2CoreNameSpaces, false);
223  //       //  SAX2Parser_->setFeature(XMLUni::fgXercesSchemaFullChecking, false);
224
225  //     }
226
227  //  This need be only done once, so might as well to it here.
228  size_t fileIndex = 0;
229  std::vector<std::string> fullFileName;
230
231  for (; fileIndex < (dp.getFileList()).size(); ++fileIndex)
232  { 
233    std::string ts = dp.getURLList()[fileIndex];
234    std::string tf = dp.getFileList()[fileIndex];
235    if ( ts.size() > 0 ) {
236      if ( ts[ts.size() - 1] == '/') {
237	fullFileName.push_back( ts + tf );
238      } else {
239	fullFileName.push_back( ts + "/" + tf );
240      }
241    } else {
242      fullFileName.push_back( tf );
243    }
244  }
245
246  for (std::vector<std::string>::const_iterator fnit = fullFileName.begin(); 
247       fnit != fullFileName.end();
248       ++fnit)
249  {
250    size_t foundFile = isFound(extractFileName( *fnit )); 
251	
252    if (!foundFile)
253    {
254      pair <std::string, std::string> pss;
255      pss.first = extractFileName( *fnit );
256      pss.second = *fnit;
257      fileNames_[nFiles_++] = pss;
258      parsed_[nFiles_ - 1]=false;
259    }
260  }
261    
262  // Start processing the files found in the config file.
263  
264  // PASS 1:  This was added later (historically) to implement the DDD
265  // requirement for Expressions.
266  DCOUT('P', "DDLParser::parse(): PASS1: Just before setting Xerces content and error handlers... ");
267  
268  
269  // in cleaning up try-catch blocks 2007-06-26 I decided to remove
270  // this because of CMSSW rules. but keep the commented way I used to
271  // do it...
272  //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
273  //     {
274  SAX2Parser_->setContentHandler(expHandler_);
275  for (size_t i = 0; i < fileNames_.size(); ++i)
276  {
277    // 	  seal::SealTimer t("DDLParser: parsing expressions of file " +fileNames_[i].first);
278    if (!parsed_[i])
279    {
280      currFileName_ = fileNames_[i].second;
281      //	      std::cout << "currFileName = " << currFileName_ << std::endl;
282      expHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
283      //	      std::cout << "2)  namespace = " << getNameSpace(extractFileName(currFileName_)) << std::endl;
284      parseFile(i);
285    }
286  }
287  expHandler_->dumpElementTypeCounter();
288  //     }
289  //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
290  //     edm::LogInfo ("DDLParser") << "\nPASS1: XMLException while processing files... \n"
291  // 	 << "Exception message is: \n"
292  // 	 << StrX(toCatch.getMessage()) << "\n" ;
293  //     cms::concurrency::xercesTerminate();
294  //     // FIX use this after DEPRECATED stuff removed:    throw(DDException("See XML Exception above"));
295  //     return -1;
296  //   }
297  // PASS 2:
298
299  DCOUT('P', "DDLParser::parse(): PASS2: Just before setting Xerces content and error handlers... ");
300
301  // in cleaning up try-catch blocks 2007-06-26 I decided to remove
302  // this because of CMSSW rules. but keep the commented way I used to
303  // do it...
304  //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
305  //     {
306  SAX2Parser_->setContentHandler(fileHandler_);
307
308  // No need to validate (regardless of user's doValidation
309  // because the files have already been validated on the first pass.
310  // This optimization suggested by Martin Liendl.
311  //       SAX2Parser_->setFeature(StrX("http://xml.org/sax/features/validation"), false);   // optional
312  //       SAX2Parser_->setFeature(StrX("http://xml.org/sax/features/namespaces"), false);   // optional
313  //       SAX2Parser_->setFeature(StrX("http://apache.org/xml/features/validation/dynamic"), false);
314
315
316  // Process files again.
317  for (size_t i = 0; i < fileNames_.size(); ++i)
318  {
319    // 	  seal::SealTimer t("DDLParser: parsing all elements of file " +fileNames_[i].first);
320    if (!parsed_[i]) {
321      currFileName_ = fileNames_[i].second;
322      //	    std::cout << "currFileName = " << currFileName_ << std::endl;
323      fileHandler_->setNameSpace( getNameSpace(extractFileName(currFileName_)) );
324      //	    std::cout << "3)  namespace = " << getNameSpace(extractFileName(currFileName_)) << std::endl;
325      parseFile(i);
326      parsed_[i] = true;
327      pair<std::string, std::string> namePair = fileNames_[i];
328      LogDebug ("DDLParser") << "Completed parsing file " << namePair.second << std::endl;
329    }
330  }
331  //     }
332  //   DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch) {
333  //     edm::LogError ("DDLParser") << "\nPASS2: XMLException while processing files... \n"
334  // 	 << "Exception message is: \n"
335  // 	 << StrX(toCatch.getMessage()) << "\n" ;
336  //     cms::concurrency::xercesTerminate();
337  //     return -1;
338  //   }
339  return 0;
340}
341
342void
343DDLParser::parseFile( const int& numtoproc ) 
344{
345  if (!parsed_[numtoproc])
346  {
347    const std::string & fname = fileNames_[numtoproc].second;
348
349    // in cleaning up try-catch blocks 2007-06-26 I decided to remove
350    // this because of CMSSW rules. but keep the commented way I used to
351    // do it...
352    //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! try
353    // 	{
354    currFileName_ = fname;
355    SAX2Parser_->parse(currFileName_.c_str());
356    // 	}
357    //       DO NOT UNCOMMENT FOR ANY RELEASE; ONLY FOR DEBUGGING! catch (const XMLException& toCatch)
358    // 	{
359    // 	  std::string e("\nWARNING: DDLParser::parseFile, File: '");
360    // 	  e += currFileName_ + "'\n"
361    // 	    + "Exception message is: \n"
362    // 	    + std::string(StrX(toCatch.getMessage()).localForm()) + "\n";
363    // 	  throw(DDException(e));
364    // 	}
365  }
366  else
367  {
368    DCOUT('P', "\nWARNING: File " + fileNames_[numtoproc].first 
369	  + " has already been processed as " + fileNames_[numtoproc].second);
370  }
371}
372
373void
374DDLParser::clearFiles( void )
375{
376  fileNames_.clear();
377  parsed_.clear();
378}
379
380std::string
381DDLParser::extractFileName( std::string fullname )
382{
383  std::string ret = "";
384  size_t bit = fullname.rfind('/');
385  if ( bit < fullname.size() - 2 ) {
386    ret=fullname.substr(bit+1);
387  }
388  return ret;
389}
390
391std::string
392DDLParser::getNameSpace( const std::string& fname )
393{
394  size_t j = 0;
395  std::string ret="";
396  while (j < fname.size() && fname[j] != '.')
397    ++j;
398  if (j < fname.size() && fname[j] == '.')
399    ret = fname.substr(0, j);
400  return ret;
401}