CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_9/src/DetectorDescription/Core/src/DDPartSelection.cc

Go to the documentation of this file.
00001 #include "DetectorDescription/Base/interface/Singleton.h"
00002 #include "DetectorDescription/Core/interface/DDPartSelection.h"
00003 #include "DetectorDescription/Base/interface/DDException.h"
00004 #include "DetectorDescription/Base/interface/DDdebug.h"
00005 #include "DetectorDescription/Core/interface/DDSplit.h"
00006 
00007 #include "boost/spirit/include/classic.hpp"
00008 
00009 // Message logger.
00010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00011 
00012 #include <map>
00013 
00014 namespace boost { namespace spirit { namespace classic { } } } using namespace boost::spirit::classic;
00015 
00016 struct DDSelLevelCollector
00017 {
00018   std::string namespace_;
00019   std::string name_;
00020   int copyNo_;
00021   bool isCopyNoValid_;
00022   bool isChild_;
00023   std::vector<DDPartSelRegExpLevel>* p_;
00024 
00025   std::vector<DDPartSelRegExpLevel>* path(std::vector<DDPartSelRegExpLevel>* p=0) {
00026     if (p) {
00027       p_=p; 
00028       namespace_="";
00029       name_="";
00030       copyNo_=0;
00031       isCopyNoValid_=false;
00032       isChild_=false;
00033     }
00034     return p_;
00035   }
00036 };
00037 
00038 
00039 void noNameSpace(char const * /*first*/, char const* /*last*/) {
00040   DDI::Singleton<DDSelLevelCollector>::instance().namespace_="";
00041 }
00042 /* Functor for the parser; it does not consume memory -
00043   pointers are only used to store references to memory
00044   managed elsewhere 
00045 */
00046 struct DDSelLevelFtor
00047 {
00048   DDSelLevelFtor() 
00049     : c_(DDI::Singleton<DDSelLevelCollector>::instance())
00050   { }
00051   
00052   // parser calls this whenever a selection has been parsed ( //ns:nm[cn], /nm, //ns:nm, .... ) 
00053   void operator() (char const* /*first*/, char const* /*last*/) const {
00054    if(c_.path()){
00055     if (c_.isCopyNoValid_ && c_.isChild_) {
00056       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddchildposp));
00057       //edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddchildposp << std::endl;
00058     } else
00059     if (c_.isCopyNoValid_ && !c_.isChild_) {
00060       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddanyposp));
00061       //      edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddanyposp << std::endl;
00062     } else
00063     if (!c_.isCopyNoValid_ && c_.isChild_) {
00064       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddchildlogp));
00065       //      edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddchildlogp << std::endl;
00066     } else
00067     if (!c_.isCopyNoValid_ && !c_.isChild_) {
00068       c_.path()->push_back(DDPartSelRegExpLevel(c_.namespace_,c_.name_,c_.copyNo_,ddanylogp));
00069       //      edm::LogInfo("DDPartSelection")  << namespace_ << name_ << copyNo_ << ' ' << ddanylogp << std::endl;
00070     } 
00071     c_.namespace_="";
00072     c_.name_="";
00073     c_.isCopyNoValid_=false;   
00074    } 
00075   }
00076      
00077   DDSelLevelCollector & c_;    
00078 };
00079 
00080 struct DDIsChildFtor
00081 {
00082   
00083   void operator()(char const* first, char const* last) const {
00084    DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();
00085    if ( (last-first) > 1) 
00086      sl.isChild_=false;
00087    if ( (last-first) ==1 )
00088      sl.isChild_=true;
00089    //edm::LogInfo("DDPartSelection")  << "DDIsChildFtor  isChild=" << (last-first) << std::endl;
00090   }
00091  
00092 };
00093 
00094 
00095 struct DDNameSpaceFtor
00096 {
00097   
00098   void operator()(char const* first, char const* last) const {
00099     DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();  
00100     sl.namespace_.assign(first,last);
00101     // edm::LogInfo("DDPartSelection")  << "DDNameSpaceFtor singletonname=" << DDI::Singleton<DDSelLevelCollector>::instance().namespace_ << std::endl;
00102   }
00103   
00104   DDSelLevelFtor* selLevelFtor_;
00105 };
00106 
00107 
00108 struct DDNameFtor
00109 {
00110  
00111   void operator()(char const* first, char const* last) const {
00112     DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();
00113     sl.name_.assign(first,last);  
00114     // edm::LogInfo("DDPartSelection")  << "DDNameFtor singletonname=" << Singleton<DDSelLevelCollector>::instance().name_ << std::endl;
00115   }
00116   
00117 };
00118 
00119 
00120 struct DDCopyNoFtor
00121 {
00122   
00123   void operator()(int i) const {
00124     DDSelLevelCollector & sl = DDI::Singleton<DDSelLevelCollector>::instance();  
00125     sl.copyNo_ = i;
00126     sl.isCopyNoValid_ = true;
00127     // edm::LogInfo("DDPartSelection")  << "DDCopyNoFtor ns=" << i;
00128   }
00129  
00130 };
00131  
00132  
00133 
00135 struct SpecParParser : public grammar<SpecParParser>
00136 {
00137   template <typename ScannerT>
00138   struct definition
00139   {
00140     definition(SpecParParser const& /*self*/) {
00141          
00142         Selection  //= FirstStep[selLevelFtor()] 
00143                   //>> *SelectionStep[selLevelFtor()]
00144                    = +SelectionStep[selLevelFtor()]
00145                    ;
00146 
00147         FirstStep  = Descendant 
00148                   >> Part
00149                    ; 
00150 
00151         Part       = PartNameCopyNumber 
00152                    | PartName
00153                    ;
00154 
00155         PartNameCopyNumber = PartName 
00156                   >> CopyNumber
00157                    ;
00158 
00159         SelectionStep = NavigationalElement[isChildFtor()] 
00160                   >> Part
00161                    ;
00162 
00163         NavigationalElement = Descendant 
00164                    | Child
00165                    ;
00166 
00167         CopyNumber = ch_p('[') 
00168                   >> int_p[copyNoFtor()] 
00169                   >> ch_p(']')
00170                    ;
00171 
00172         PartName   = NameSpaceName 
00173                    | SimpleName[nameFtor()][&noNameSpace]
00174                    ;
00175 
00176         SimpleName = +( alnum_p | ch_p('_') | ch_p('.') | ch_p('*') )
00177                    ;
00178 
00179         NameSpaceName = SimpleName[nameSpaceFtor()] 
00180                   >> ':' 
00181                   >> SimpleName[nameFtor()]
00182                    ;
00183 
00184         Descendant = ch_p('/') 
00185                   >> ch_p('/')
00186                    ;
00187 
00188         Child      = ch_p('/')
00189                     ;
00190   
00191          }
00192   
00193     rule<ScannerT> Selection, FirstStep, Part, SelectionStep, NavigationalElement,
00194         CopyNumber, PartName, PartNameCopyNumber, NameSpaceName, SimpleName, 
00195         Descendant, Child; 
00196 
00197     rule<ScannerT> const& start() const { return Selection; }
00198     
00199     DDSelLevelFtor & selLevelFtor() {
00200       return DDI::Singleton<DDSelLevelFtor>::instance();
00201     }
00202     
00203     DDNameFtor & nameFtor() {
00204      static DDNameFtor f_;
00205      return f_;
00206     }
00207     
00208     DDNameSpaceFtor & nameSpaceFtor() {
00209      static DDNameSpaceFtor f_;
00210      return f_;
00211     }
00212     
00213     DDIsChildFtor & isChildFtor() {
00214      static DDIsChildFtor f_;
00215      return f_;
00216     }
00217 
00218     DDCopyNoFtor & copyNoFtor() {
00219      static DDCopyNoFtor f_;
00220      return f_;
00221     }    
00222   };
00223   
00224 };
00225 
00226 
00227 /*
00228 std::ostream & operator<<(std::ostream & os, const DDPartSelection & ps)
00229 {
00230   DDPartSelection::const_iterator it = ps.begin();
00231   for (; it != ps.end(); ++it) {
00232     std::string s;
00233     switch (it->selectionType_) {
00234       case ddunknown: case ddanynode: case ddanychild:
00235         os << "*ERROR*";
00236         break;
00237       case ddanylogp: 
00238         os << "//" << it->lp_.ddname();
00239         break;
00240       case ddanyposp:
00241         os << "//" << it->lp_.ddname() << '[' << it->copyno_ << ']';
00242         break;
00243       case ddchildlogp:                 
00244         os << "/" << it->lp_.ddname();
00245         break;
00246       case ddchildposp:
00247         os << "/" << it->lp_.ddname() << '[' << it->copyno_ << ']';             
00248         break;
00249     }
00250   
00251   }
00252   return os;
00253 }
00254 */
00255 
00256 DDPartSelectionLevel::DDPartSelectionLevel(const DDLogicalPart & lp, int c, ddselection_type t)
00257  : lp_(lp), copyno_(c), selectionType_(t)
00258 {
00259   
00260 }
00261 
00262 
00263 
00264 void DDTokenize2(const std::string & sel, std::vector<DDPartSelRegExpLevel> & path)
00265 {
00266   static SpecParParser parser;
00267   DDI::Singleton<DDSelLevelCollector>::instance().path(&path);
00268   bool result = parse(sel.c_str(), parser).full;
00269   if (!result) {
00270     edm::LogError("DDPartSelection") << "DDTokenize2() error in parsing of " << sel << std::endl;
00271   }
00272 }
00273 
00274 // uhhhhhhhhhhhhhhhh! Spaghetti code!!!!!!!!! (or worse?)
00275 // FIXME: DDTokenize: if a LogicalPart is not yet defined during parsing of a SpecPar 
00276 // FIXME: (ddunknown is then the corresponding ddselection_type of the PartSelection)
00277 // FIXME: then set a state-variable to 'undefined' .
00278 // FIXME: After parsing, reprocess all undefined SpecPars ...
00279 void DDTokenize(const std::string & sel, std::vector<DDPartSelRegExpLevel> &  path)
00280 {
00281 
00282 
00283   static bool isInit(false);
00284   static std::vector<std::string> tokens;
00285   if(!isInit) {
00286     // initialize with valid tokens
00287     tokens.push_back("/"); 
00288     tokens.push_back("//");
00289     tokens.push_back("[");
00290     tokens.push_back("]");
00291   }
00292   std::string s = sel;
00293   std::string::size_type st = std::string::npos;
00294   std::string::size_type cu = 0;
00295   std::vector<std::string> toksVec;
00296   std::vector<std::string> textVec;
00297   std::string tkn, txt;
00298   bool braceOpen(false);
00299   /*
00300     the following code should decompose a selection std::string into 2 std::vectors,
00301     a token-std::vector and a text-std::vector. Tokens are /,//,[,] 
00302     example: "//Abc[3]/Def" ->
00303              tokens  text
00304              //      ""
00305              [       Abc
00306              ]       3
00307              /       ""
00308                      "Def"
00309   */  
00310   
00311   while (s.size()) {
00312     std::vector<std::string>::iterator tkit = tokens.begin();
00313     std::vector<std::string>::iterator mint = tokens.end();
00314     st=s.size();
00315     std::string::size_type ts;
00316     for(;tkit!=tokens.end();++tkit) { // find the first match of one of the token std::strings
00317       ts = s.find(*tkit); 
00318       if (ts<=st) { 
00319         st=ts;
00320         mint = tkit;
00321       }  
00322     }
00323     
00324     if (mint!=tokens.end())     
00325      tkn = s.substr(st,mint->size());
00326     else
00327      tkn=""; 
00328     txt = s.substr(cu,st);
00329     toksVec.push_back(tkn);
00330     textVec.push_back(txt);
00331     if (braceOpen) {
00332       if (tkn!="]")
00333         throw DDException(std::string("PartSelector: syntaxerror in ") + sel + 
00334                           std::string("\ncheck the braces!") );
00335       else
00336         braceOpen=false;
00337     }           
00338     if (tkn=="[")
00339       braceOpen=true;
00340     DCOUT_V('C',"tkn=" << tkn << " txt=" << txt);   
00341     if (mint!=tokens.end())
00342       s.erase(cu,st+mint->size()); 
00343     else
00344       s.erase();  
00345     DCOUT_V('C', std::endl << "s=" << s);   
00346     //break;    
00347   }
00348   DCOUT_V('C', "The original std::string was:" << std::endl);
00349   unsigned int i=0;
00350   DCOUT_V('C', "toks\ttext");
00351   for (i=0; i<toksVec.size();++i) {
00352     DCOUT_V('C',  toksVec[i] << "\t" << textVec[i]);
00353   }  
00354   DCOUT_V('C', std::endl); 
00355   
00356   // now some spaghetti code 
00357   std::string nm = "blabla" ; // std::string("PartSelector=") + ns() + std::string(":") + name();
00358   if (textVec[0] != "")
00359     throw DDException( nm 
00360                       +std::string(" selection must not start with a LogicalPart-name")); 
00361   
00362   if ((toksVec[0] != "//"))
00363     throw DDException( nm 
00364                       +std::string(" selection must start with '//' !")); 
00365   
00366   if (textVec.size() < 2)
00367     throw DDException( nm + std::string(" internal error [textVec.size()<2]!"));
00368     
00369   std::vector<std::string>::iterator tk_it = toksVec.begin();
00370   std::vector<std::string>::iterator tx_it = textVec.begin(); ++tx_it;
00371   // the BIG switch - yes, this is OO!!!
00372   while(tk_it != toksVec.end() && tx_it != textVec.end()) {
00373  
00374     // anynode ... token //* makes no sense (except as last entry which is forbidden ...)
00375     DCOUT_V('C', ">- anynode tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00376     if ( *tk_it == "//" && *tx_it=="*" ) { 
00377       path.push_back(DDPartSelRegExpLevel("","",0,ddanynode));
00378       DCOUT_V('C', "--anynode: //*" << std::endl);
00379       ++tk_it;
00380       ++tx_it;
00381       continue;
00382     }
00383              
00384     // anychild
00385     DCOUT_V('C', ">- anychild tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00386     if ( *tk_it == "/" && *tx_it=="*" ) { 
00387       path.push_back(DDPartSelRegExpLevel("","",0,ddanychild));
00388       DCOUT_V('C', "--anychild: /*" << std::endl);
00389       ++tk_it;
00390       ++tx_it;
00391       continue;
00392     }    
00393 
00394     // anylogp
00395     DCOUT_V('C', ">- anylogp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00396     if ( *tk_it == "//" && tx_it->size()) {
00397       ++tk_it;
00398       if ( tk_it != toksVec.end() && *tk_it != "[" && *tk_it != "]") {
00399         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00400           path.push_back(DDPartSelRegExpLevel(p.second,p.first,0,ddanylogp));
00401         DCOUT_V('C', "--anylogp: " << *tx_it << std::endl);
00402         ++tx_it;
00403         continue;
00404       } 
00405       --tk_it;
00406     }    
00407 
00408     // childlogp
00409     DCOUT_V('C', ">- childlogp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00410     if ( *tk_it == "/" && tx_it->size()) {
00411       ++tk_it;
00412       if ( tk_it == toksVec.end() - 1 ) {
00413         DCOUT_V('C', "--childlogp: " << *tx_it << std::endl);
00414         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00415           path.push_back(DDPartSelRegExpLevel(p.second,p.first,0,ddchildlogp));
00416         ++tx_it;   
00417         continue;
00418       }
00419       if ( *tk_it == "/" || *tk_it=="//") {
00420         DCOUT_V('C', "--childlogp: " << *tx_it << std::endl);
00421         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00422           path.push_back(DDPartSelRegExpLevel(p.second,p.first,0,ddchildlogp));
00423         ++tx_it;
00424         continue;
00425       }
00426       --tk_it;
00427     }   
00428 
00429 
00430     // anyposp
00431     DCOUT_V('C', ">- anyposp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00432     if ( *tk_it == "//" && tx_it->size()) {
00433       ++tk_it;
00434       if ( tk_it != toksVec.end() && *tk_it == "[" ) {
00435         ++tk_it;
00436         if ( tk_it == toksVec.end() || (tk_it != toksVec.end() && *tk_it != "]")) {
00437          DCOUT_V('C', *tk_it << " " << *tx_it );
00438            break;
00439         }  
00440         ++tx_it;
00441         ++tk_it;
00442         std::pair<std::string,std::string> p(DDSplit(*(tx_it-1)));
00443           path.push_back(DDPartSelRegExpLevel(p.second,p.first,atoi(tx_it->c_str()),ddanyposp));
00444         DCOUT_V('C', "--anyposp: " << *tx_it << " " << atoi(tx_it->c_str()) << std::endl);
00445         ++tx_it;
00446         ++tx_it;
00447         continue;
00448       } 
00449     }    
00450         
00451          
00452     // childposp
00453     DCOUT_V('C', ">- childposp tkn=" << *tk_it << " d=" << tk_it-toksVec.begin() << " txt=" << *tx_it << std::endl);
00454     if ( *tk_it == "/" && tx_it->size()) {
00455       ++tk_it;
00456       if ( tk_it != toksVec.end() && *tk_it=="[" ) {
00457         DCOUT_V('C', "--childposp: " << *tx_it << " " << *tk_it << *(tx_it+1) << std::endl);
00458         std::pair<std::string,std::string> p(DDSplit(*tx_it));
00459           path.push_back(DDPartSelRegExpLevel(p.second,p.first,atoi((tx_it+1)->c_str()),ddchildposp));
00460 
00461         ++tx_it;
00462 
00463         ++tx_it;
00464         ++tk_it;
00465         if (tk_it != toksVec.end() && *tk_it != "]") 
00466           break;
00467         ++tk_it;
00468         ++tx_it;
00469         continue;  
00470       }
00471     }
00472     
00473     // any
00474     throw DDException( nm + std::string(" syntax error in:\n") + sel + 
00475                             std::string("\n  tkn=") + *tk_it + std::string("  txt=")+ *tx_it);                              
00476   }
00477   //FIXME: DDPartSelectorImpl::tokenize : prototype has restricted support for selection std::string (code below restricts)
00478   ddselection_type tmp = path.back().selectionType_;
00479   if (tmp==ddunknown || tmp==ddanynode || tmp==ddanychild ) 
00480         throw DDException(std::string("PartSelector: last element in selection std::string in ") + sel + 
00481                           std::string("\nmust address a distinct LogicalPart or PosPart!") );
00482 }
00483 
00484 
00485 std::ostream & operator<<(std::ostream & o, const DDPartSelection & p)
00486 {
00487   DDPartSelection::const_iterator it(p.begin()), ed(p.end());
00488   for (; it != ed; ++it) {
00489     const DDPartSelectionLevel lv  =*it;
00490     switch (lv.selectionType_) {
00491     case ddanylogp:
00492       o << "//" << lv.lp_.ddname();
00493       break;
00494     case ddanyposp:
00495       o << "//" << lv.lp_.ddname() << '[' << lv.copyno_ << ']';
00496       break;
00497     case ddchildlogp:
00498       o << "/" << lv.lp_.ddname();
00499       break;
00500     case ddchildposp:
00501       o << "/" << lv.lp_.ddname() << '[' << lv.copyno_ << ']';
00502       break;
00503     default:
00504       o << "{Syntax ERROR}";
00505     }
00506   }
00507   return o;
00508 }
00509 
00510 std::ostream & operator<<(std::ostream & os, const std::vector<DDPartSelection> & v)
00511 {
00512   std::vector<DDPartSelection>::const_iterator it(v.begin()), ed(v.end());
00513   for (; it != (ed-1); ++it) {
00514     os << *it << std::endl;
00515   }
00516   if ( it != ed ) {
00517     ++it;
00518     os << *it;
00519   }
00520   return os;
00521 }
00522 
00523 // explicit template instantiation.
00524 
00525 template class DDI::Singleton<DDSelLevelFtor>;
00526 //template class DDI::Singleton<DDI::Store<DDName, DDSelLevelCollector> >;
00527 template class DDI::Singleton<DDSelLevelCollector>;
00528 #include <DetectorDescription/Base/interface/Singleton.icc>