CMS 3D CMS Logo

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