CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DetectorDescription/Core/src/DDLogicalPart.cc

Go to the documentation of this file.
00001 #include "DetectorDescription/Core/interface/DDLogicalPart.h"
00002 #include "LogicalPart.h"
00003 #include "DetectorDescription/Base/interface/DDdebug.h"
00004 #include <ostream>
00005 
00006 // Message logger.
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 
00009 //DDBase<DDName,LogicalPart*>::StoreT::pointer_type
00010 //  DDBase<DDName,LogicalPart*>::StoreT::instance_ = 0;
00011 
00012 // cache to check for unique names (vs. unique namespace:name)
00013 //LPNAMES::pointer_type LPNAMES::instance_ = 0;
00014 
00015 
00016 void DD_NC(const DDName & n) {
00017  std::vector<DDName> & ns = LPNAMES::instance()[n.name()];
00018  typedef std::vector<DDName>::iterator IT;
00019  bool alreadyIn(false);
00020  for(IT p = ns.begin(); p != ns.end() ; ++p) {
00021    if ( p->ns() == n.ns()) {
00022      alreadyIn = true;
00023      break;
00024    } 
00025  }
00026  if (!alreadyIn) {
00027    ns.push_back(n);
00028  }  
00029 }
00030     
00031     
00032 std::ostream & 
00033 operator<<(std::ostream & os, const DDLogicalPart & part)
00034 {
00035   DDBase<DDName,DDI::LogicalPart*>::def_type defined(part.isDefined());
00036   if (defined.first) {
00037     os << *(defined.first) << " ";
00038     if (defined.second) {
00039       part.rep().stream(os); 
00040     }
00041     else {
00042       os << "* logicalpart not defined * ";  
00043     }
00044   }  
00045   else {
00046     os << "* logicalpart not declared * ";  
00047   }  
00048   return os;
00049 }
00050 
00051 // =================================================================================
00052 
00065 // now inlined... 
00066 
00099 DDLogicalPart::DDLogicalPart(const DDName & name) : DDBase<DDName,DDI::LogicalPart*>()
00100 { 
00101   prep_ = StoreT::instance().create(name);
00102   DD_NC(name);
00103 }
00104 
00117 DDLogicalPart::DDLogicalPart(const DDName & ddname,
00118                              const DDMaterial & material,
00119                              const DDSolid & solid,
00120                              DDEnums::Category cat) 
00121  : DDBase<DDName,DDI::LogicalPart*>() 
00122 { 
00123    DCOUT('C', "create LogicalPart ddname=" << ddname << " mat=" << material.name() << " sol=" << solid.name());
00124    prep_ = StoreT::instance().create(ddname, new DDI::LogicalPart(material,solid,cat));
00125    DD_NC(ddname);
00126 }
00127 
00128 
00129 // private!
00130 /*
00131 DDLogicalPart::DDLogicalPart(DDRedirect<DDLogicalPartImpl>* p, bool dummy)
00132  : DDMultiRegistered<DDLogicalPartImpl>(p,true)
00133 { }
00134 */
00135 
00136 DDEnums::Category DDLogicalPart::category() const
00137 { 
00138   return rep().category(); 
00139 }
00140 
00141 
00142 const DDMaterial & DDLogicalPart::material() const 
00143 {
00144   return rep().material();
00145 }  
00146 
00147 
00148 const DDSolid & DDLogicalPart::solid() const
00149 {
00150   return rep().solid();
00151 }
00152 
00153 
00154 /* 
00155    The weight must be calculated by using the method DDCompactView::weight().
00156    For the weight calculation the full subtree of children is expanded. As a 
00157    usefull side-effect the weight of all LogicalParts of the children is calculated
00158    as well.
00159    This method will return 0, if the weight has not yet been calculated 
00160    using the DDCompactView, otherwise the weight of the component and all
00161    its sub-components.
00162    \todo In future DDLogicalPart::weight() will be sufficient for weight calculations
00163    \todo make the method 'const'
00164 */  
00165 double & DDLogicalPart::weight() 
00166 {
00167   return rep().weight();
00168 }    
00169 
00170 
00224 std::vector<const DDsvalues_type *> DDLogicalPart::specifics() const
00225 {
00226   std::vector<const DDsvalues_type*> result;
00227   rep().specificsV(result);
00228   return result;
00229 }
00230 
00231 
00232 DDsvalues_type DDLogicalPart::mergedSpecifics() const
00233 {
00234   DDsvalues_type  result;
00235   rep().mergedSpecificsV(result);
00236   return result;
00237 }  
00238 
00239 // for internal use only
00240 void DDLogicalPart::addSpecifics(const std::pair<DDPartSelection*,DDsvalues_type*> & s)
00241 {
00242    DCOUT('S', "lp=" << name());
00243    rep().addSpecifics(s);
00244 }
00245 void DDLogicalPart::removeSpecifics(const std::pair<DDPartSelection*,DDsvalues_type*> & s)
00246 {
00247    rep().removeSpecifics(s);
00248 }
00249 bool DDLogicalPart::hasDDValue(const DDValue & v) const
00250 {
00251   return rep().hasDDValue(v);
00252 }
00253 // for internal use only
00254 /*
00255 const std::vector<DDSpecifics> & DDLogicalPart::specifics() const
00256 {
00257   return rep().specifics();
00258 }
00259 */
00260 // void DDLogicalPart::clear()
00261 // {
00262 //    StoreT::instance().clear();
00263 // }
00264 
00265 
00266 
00267 // finds out whether a DDLogicalPart is registered & already valid (initialized)
00268 // - returns (true,""), if so; result holds the corresponding DDLogicalPart
00269 // - returns (false,"some status message") otherwise
00270 // - nm corresponds to a regular expression, but will be anchored ( ^regexp$ )
00271 // - ns corresponds to a regular expression, but will be anchored ( ^regexp$ )
00272 #include <regex.h>
00273 #include <set>
00274 
00275 namespace {
00276 
00277   struct Regex {
00278 
00279     explicit Regex(const std::string & s) : m_ok(false), me(s) {
00280       size_t p = me.find(".");
00281       m_ok = p!=std::string::npos;
00282       if(m_ok) {
00283         if (p>0) {
00284           m_range.first = me.substr(0,p);
00285           m_range.second = m_range.first+"{"; // '{' is 'z'+1
00286         }
00287         me = "^" + me + "$";
00288         regcomp(&m_regex,me.c_str(),0);
00289       }
00290     } 
00291 
00292     ~Regex() { if(m_ok) regfree(&m_regex); }
00293 
00294     bool empty() const { return me.empty();}
00295 
00296     bool notRegex() const { return !m_ok;}
00297 
00298     const std::string & value() const { return me;}
00299 
00300     bool match(const std::string & s) const {
00301       if (m_ok)
00302         return !regexec(&m_regex, s.c_str(), 0,0,0);
00303       else
00304         return me==s;
00305     }
00306 
00307     const std::pair< std::string, std::string> & range() const { return m_range;}
00308   private:
00309     bool m_ok;
00310     regex_t m_regex;
00311     std::string me;
00312     // range of me in a collating sequence
00313     std::pair<std::string, std::string> m_range;
00314   };
00315 
00316 }
00317 
00318 std::pair<bool,std::string> DDIsValid(const std::string & ns, const std::string & nm, std::vector<DDLogicalPart> & result, bool doRegex)
00319 {
00320   //return std::make_pair(true,"");      
00321   if (!doRegex) {
00322     DDName ddnm(nm,ns);
00323     result.push_back(DDLogicalPart(ddnm));
00324     return std::make_pair(true,"");
00325   }
00326   std::string status;
00327   Regex aRegex(nm);
00328   Regex aNsRegex(ns);
00329   bool emptyNs = aNsRegex.empty();
00330     // std::cerr <<  "regex " << nm << " " << ns << std::endl;
00331  
00332   //edm::LogInfo("DDLogicalPart") << " . emptyNs=" << emptyNs << std::endl;
00333   //edm::LogInfo("DDLogicalPart") << " . qname=[" << ns << ":" << nm << "]" << std::endl;
00334   
00335   // THIS IS THE SLOW PART: I have to compare every namespace & name of every
00336   // logical part with a regex-comparison .... a linear search always through the
00337   // full range of logical parts!!!!
00338   /*
00339     Algorithm description:
00340     x. empty nm and ns argument of method means: use all matching regex ^.*$
00341     a. iterate over all logical part names, match against regex for names
00342     b. iterate over all namespaces of names found in a & match against regex for namespaces   
00343   */
00344   LPNAMES::value_type::const_iterator bn(LPNAMES::instance().begin()),
00345                                       ed(LPNAMES::instance().end());
00346   typedef std::vector< LPNAMES::value_type::const_iterator> Candidates;
00347   Candidates candidates;
00348   if ( aRegex.notRegex() ) {
00349     LPNAMES::value_type::const_iterator it = LPNAMES::instance().find(aRegex.value());
00350     if (it!=ed) candidates.push_back(it);
00351   }
00352   else {
00353     if ( !aRegex.range().first.empty()) {
00354       bn =  LPNAMES::instance().lower_bound(aRegex.range().first);
00355       ed =  LPNAMES::instance().upper_bound(aRegex.range().second);
00356     }
00357     for (LPNAMES::value_type::const_iterator it=bn; it != ed; ++it)
00358       if(aRegex.match(it->first)) candidates.push_back(it);
00359   }
00360   for (int i=0; i<int(candidates.size()); ++i) {
00361     LPNAMES::value_type::const_iterator it = candidates[i];
00362     //if (doit)  edm::LogInfo("DDLogicalPart") << "rgx: " << aName << ' ' << it->first << ' ' << doit << std::endl;
00363     std::vector<DDName>::size_type sz = it->second.size(); // no of 'compatible' namespaces
00364     if ( emptyNs && (sz==1) ) { // accept all logical parts in all the namespaces
00365       result.push_back(it->second[0]);
00366       //std::vector<DDName>::const_iterator nsIt(it->second.begin()), nsEd(it->second.end());
00367       //for(; nsIt != nsEd; ++nsIt) {
00368       //   result.push_back(DDLogicalPart(*nsIt));
00369       //   edm::LogInfo("DDLogicalPart") << "DDD-WARNING: multiple namespaces match (in SpecPars PartSelector): " << *nsIt << std::endl;
00370       //}
00371     }
00372     else if ( !emptyNs ) { // only accept matching namespaces
00373       std::vector<DDName>::const_iterator nsit(it->second.begin()), nsed(it->second.end());
00374       for (; nsit !=nsed; ++nsit) {
00375         //edm::LogInfo("DDLogicalPart") << "comparing " << aNs << " with " << *nsit << std::endl;
00376         bool another_doit = aNsRegex.match(nsit->ns());
00377         if ( another_doit ) {
00378           //temp.push_back(std::make_pair(it->first,*nsit));
00379           result.push_back(DDLogicalPart(*nsit));
00380         }
00381       }
00382     }
00383     else { // emtpyNs and sz>1 -> error, too ambigous
00384       std::string message = "DDLogicalPart-name \"" + it->first +"\" matching regex \""
00385         + nm + "\" has been found at least in following namespaces:\n";
00386       std::vector<DDName>::const_iterator vit = it->second.begin();
00387       for(; vit != it->second.end(); ++vit) {
00388         message += vit->ns();
00389         message += " "; 
00390       } 
00391         message += "\nQualify the name with a regexp for the namespace, i.e \".*:name-regexp\" !";
00392         return std::make_pair(false,message);        
00393     }
00394   }
00395   bool flag=true;    
00396   std::string message;
00397   
00398   // check whether the found logical-parts are also defined (i.e. have material, solid ...)
00399   if (result.size()) {
00400     std::vector<DDLogicalPart>::const_iterator lpit(result.begin()), lped(result.end());
00401     for (; lpit != lped; ++lpit) { 
00402       // std::cout << "VI- " << std::string(lpit->name()) << std::endl;
00403       if (!lpit->isDefined().second) {
00404          message = message + "LogicalPart " + lpit->name().fullname() + " not (yet) defined!\n";
00405          flag = false;
00406       }
00407     }
00408   }
00409   else {
00410     flag = false;
00411     message = "No regex-match for namespace=" + ns + "  name=" + nm + "\n";
00412   }
00413 
00414 
00415   return std::make_pair(flag,message);
00416 }
00417 
00418 
00419 const std::vector< std::pair<DDPartSelection*,DDsvalues_type*> > & 
00420 DDLogicalPart::attachedSpecifics() const
00421 {
00422   return rep().attachedSpecifics();
00423 }
00424 
00425 /*
00426 const std::vector<DDPartSelection*> & DDLogicalPart::partSelections(const DDValue & v) const
00427 {
00428   return rep().partSelections(v);
00429 }
00430 */