CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/DetectorDescription/Core/src/DDLogicalPart.cc

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