CMS 3D CMS Logo

DDLogicalPart.cc
Go to the documentation of this file.
2 
3 #include <ostream>
4 
10 
11 class DDValue;
12 
13 void
14 DD_NC( const DDName & n )
15 {
16  auto & ns = LPNAMES::instance()[n.name()];
17  bool alreadyIn( false );
18  for( const auto& p : ns )
19  {
20  if( p.ns() == n.ns())
21  {
22  alreadyIn = true;
23  break;
24  }
25  }
26  if( !alreadyIn )
27  {
28  ns.push_back( n );
29  }
30 }
31 
32 std::ostream &
33 operator<<( std::ostream & os, const DDLogicalPart & part )
34 {
36  if( defined.first )
37  {
38  os << *(defined.first) << " ";
39  if( defined.second )
40  {
41  part.rep().stream( os );
42  }
43  else
44  {
45  os << "* logicalpart not defined * ";
46  }
47  }
48  else
49  {
50  os << "* logicalpart not declared * ";
51  }
52  return os;
53 }
54 
55 // =================================================================================
56 
69 // now inlined...
70 
104  : DDBase<DDName, DDI::LogicalPart*>()
105 {
106  prep_ = StoreT::instance().create( name );
107  DD_NC( name );
108 }
109 
123  const DDMaterial & material,
124  const DDSolid & solid,
126  : DDBase<DDName,DDI::LogicalPart*>()
127 {
128  prep_ = StoreT::instance().create(ddname, new DDI::LogicalPart(material,solid,cat));
129  DD_NC(ddname);
130 }
131 
132 
133 // private!
134 /*
135 DDLogicalPart::DDLogicalPart(DDRedirect<DDLogicalPartImpl>* p, bool dummy)
136  : DDMultiRegistered<DDLogicalPartImpl>(p,true)
137 { }
138 */
139 
141 {
142  return rep().category();
143 }
144 
145 
147 {
148  return rep().material();
149 }
150 
151 
153 {
154  return rep().solid();
155 }
156 
157 
158 /*
159  The weight must be calculated by using the method DDCompactView::weight().
160  For the weight calculation the full subtree of children is expanded. As a
161  usefull side-effect the weight of all LogicalParts of the children is calculated
162  as well.
163  This method will return 0, if the weight has not yet been calculated
164  using the DDCompactView, otherwise the weight of the component and all
165  its sub-components.
166  \todo In future DDLogicalPart::weight() will be sufficient for weight calculations
167  \todo make the method 'const'
168 */
170 {
171  return rep().weight();
172 }
173 
174 
228 std::vector<const DDsvalues_type *> DDLogicalPart::specifics() const
229 {
230  std::vector<const DDsvalues_type*> result;
231  rep().specificsV(result);
232  return result;
233 }
234 
235 
237 {
239  rep().mergedSpecificsV(result);
240  return result;
241 }
242 
243 // for internal use only
244 void DDLogicalPart::addSpecifics(const std::pair<const DDPartSelection*, const DDsvalues_type*> & s)
245 {
246  rep().addSpecifics(s);
247 }
248 void DDLogicalPart::removeSpecifics(const std::pair<DDPartSelection*,DDsvalues_type*> & s)
249 {
250  rep().removeSpecifics(s);
251 }
253 {
254  return rep().hasDDValue(v);
255 }
256 
257 // finds out whether a DDLogicalPart is registered & already valid (initialized)
258 // - returns (true,""), if so; result holds the corresponding DDLogicalPart
259 // - returns (false,"some status message") otherwise
260 // - nm corresponds to a regular expression, but will be anchored ( ^regexp$ )
261 // - ns corresponds to a regular expression, but will be anchored ( ^regexp$ )
262 #include <regex.h>
263 #include <stddef.h>
264 
265 namespace
266 {
267  struct Regex
268  {
269  explicit Regex( const std::string & s )
270  : m_ok( false ),
271  me( s )
272  {
273  size_t p = me.find(".");
274  m_ok = p != std::string::npos;
275  if( m_ok )
276  {
277  if( p > 0 )
278  {
279  m_range.first = me.substr( 0, p );
280  m_range.second = m_range.first + "{"; // '{' is 'z'+1
281  }
282  me = "^" + me + "$";
283  regcomp( &m_regex, me.c_str(), 0 );
284  }
285  }
286 
287  ~Regex( void ) { if( m_ok ) regfree( &m_regex ); }
288 
289  bool empty( void ) const { return me.empty(); }
290 
291  bool notRegex( void ) const { return !m_ok; }
292 
293  const std::string & value( void ) const { return me;}
294 
295  bool match( const std::string & s ) const {
296  if( m_ok )
297  return !regexec( &m_regex, s.c_str(), 0, 0, 0 );
298  else
299  return me == s;
300  }
301 
302  const std::pair< std::string, std::string> & range( void ) const { return m_range; }
303  private:
304  bool m_ok;
305  regex_t m_regex;
306  std::string me;
307  // range of me in a collating sequence
308  std::pair<std::string, std::string> m_range;
309  };
310 }
311 
312 std::pair<bool, std::string>
313 DDIsValid( const std::string & ns, const std::string & nm, std::vector<DDLogicalPart> & result, bool doRegex )
314 {
315  if( !doRegex )
316  {
317  DDName ddnm( nm, ns );
318  result.push_back( DDLogicalPart( ddnm ));
319  return std::make_pair( true, "" );
320  }
322  Regex aRegex( nm );
323  Regex aNsRegex( ns );
324  bool emptyNs = aNsRegex.empty();
325 
326  // THIS IS THE SLOW PART: I have to compare every namespace & name of every
327  // logical part with a regex-comparison .... a linear search always through the
328  // full range of logical parts!!!!
329  /*
330  Algorithm description:
331  x. empty nm and ns argument of method means: use all matching regex ^.*$
332  a. iterate over all logical part names, match against regex for names
333  b. iterate over all namespaces of names found in a & match against regex for namespaces
334  */
335  LPNAMES::value_type::const_iterator bn(LPNAMES::instance().begin()),
336  ed(LPNAMES::instance().end());
337  typedef std::vector< LPNAMES::value_type::const_iterator> Candidates;
338  Candidates candidates;
339  if ( aRegex.notRegex() ) {
340  LPNAMES::value_type::const_iterator it = LPNAMES::instance().find(aRegex.value());
341  if (it!=ed) candidates.push_back(it);
342  }
343  else {
344  if ( !aRegex.range().first.empty()) {
345  bn = LPNAMES::instance().lower_bound(aRegex.range().first);
346  ed = LPNAMES::instance().upper_bound(aRegex.range().second);
347  }
348  for (LPNAMES::value_type::const_iterator it=bn; it != ed; ++it)
349  if(aRegex.match(it->first)) candidates.push_back(it);
350  }
351  for (int i=0; i<int(candidates.size()); ++i) {
352  LPNAMES::value_type::const_iterator it = candidates[i];
353  //if (doit) edm::LogInfo("DDLogicalPart") << "rgx: " << aName << ' ' << it->first << ' ' << doit << std::endl;
354  std::vector<DDName>::size_type sz = it->second.size(); // no of 'compatible' namespaces
355  if ( emptyNs && (sz==1) ) { // accept all logical parts in all the namespaces
356  result.push_back(it->second[0]);
357  //std::vector<DDName>::const_iterator nsIt(it->second.begin()), nsEd(it->second.end());
358  //for(; nsIt != nsEd; ++nsIt) {
359  // result.push_back(DDLogicalPart(*nsIt));
360  // edm::LogInfo("DDLogicalPart") << "DDD-WARNING: multiple namespaces match (in SpecPars PartSelector): " << *nsIt << std::endl;
361  //}
362  }
363  else if ( !emptyNs ) { // only accept matching namespaces
364  std::vector<DDName>::const_iterator nsit(it->second.begin()), nsed(it->second.end());
365  for (; nsit !=nsed; ++nsit) {
366  //edm::LogInfo("DDLogicalPart") << "comparing " << aNs << " with " << *nsit << std::endl;
367  bool another_doit = aNsRegex.match(nsit->ns());
368  if ( another_doit ) {
369  //temp.push_back(std::make_pair(it->first,*nsit));
370  result.push_back(DDLogicalPart(*nsit));
371  }
372  }
373  }
374  else { // emtpyNs and sz>1 -> error, too ambigous
375  std::string message = "DDLogicalPart-name \"" + it->first +"\" matching regex \""
376  + nm + "\" has been found at least in following namespaces:\n";
377  std::vector<DDName>::const_iterator vit = it->second.begin();
378  for(; vit != it->second.end(); ++vit) {
379  message += vit->ns();
380  message += " ";
381  }
382  message += "\nQualify the name with a regexp for the namespace, i.e \".*:name-regexp\" !";
383  return std::make_pair(false,message);
384  }
385  }
386  bool flag=true;
388 
389  // check whether the found logical-parts are also defined (i.e. have material, solid ...)
390  if (result.size()) {
391  std::vector<DDLogicalPart>::const_iterator lpit(result.begin()), lped(result.end());
392  for (; lpit != lped; ++lpit) {
393  // std::cout << "VI- " << std::string(lpit->name()) << std::endl;
394  if (!lpit->isDefined().second) {
395  message = message + "LogicalPart " + lpit->name().fullname() + " not (yet) defined!\n";
396  flag = false;
397  }
398  }
399  }
400  else {
401  flag = false;
402  message = "No regex-match for namespace=" + ns + " name=" + nm + "\n";
403  }
404 
405  return std::make_pair(flag,message);
406 }
407 
408 const std::vector< std::pair<const DDPartSelection*, const DDsvalues_type*> > &
410 {
411  return rep().attachedSpecifics();
412 }
Definition: DDBase.h:10
const DDI::rep_traits< N, C >::reference rep() const
Definition: DDBase.h:84
bool hasDDValue(const DDValue &) const
def_type isDefined() const
Definition: DDBase.h:110
DDMaterial is used to define and access material information.
Definition: DDMaterial.h:41
DDEnums::Category category(void) const
Returns the categorization of the DDLogicalPart (sensitive detector element, cable, ...)
std::ostream & operator<<(std::ostream &os, const DDLogicalPart &part)
const std::string & ns() const
Returns the namespace.
Definition: DDName.cc:104
DDName is used to identify DDD entities uniquely.
Definition: DDName.h:16
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
uint16_t size_type
double & weight(void)
Weight of the LogicalPart viewed as a component, if cached, else -1.
A DDSolid represents the shape of a part.
Definition: DDSolid.h:37
std::vector< const DDsvalues_type * > specifics(void) const
returns the specific-data attached to the LogicalPart only (not to a DDExpandedNode) ...
static value_type & instance()
def cat(path)
Definition: eostools.py:400
std::vector< std::pair< unsigned int, DDValue > > DDsvalues_type
std::maps an index to a DDValue. The index corresponds to the index assigned to the name of the std::...
Definition: DDsvalues.h:20
std::pair< bool, std::string > DDIsValid(const std::string &ns, const std::string &nm, std::vector< DDLogicalPart > &result, bool doRegex)
Category
Definition: DDEnums.h:7
A DDLogicalPart aggregates information concerning material, solid and sensitveness ...
Definition: DDLogicalPart.h:92
void DD_NC(const DDName &n)
DDsvalues_type mergedSpecifics(void) const
returns the merged-specifics, i.e. the last specified specifics of this logical-part ...
void addSpecifics(const std::pair< const DDPartSelection *, const DDsvalues_type * > &)
don&#39;t use, internal only /todo make it private
part
Definition: HCALResponse.h:20
Definition: rep_type.h:4
void removeSpecifics(const std::pair< DDPartSelection *, DDsvalues_type * > &)
DDLogicalPart(void)
The default constructor provides an uninitialzed reference object.
Definition: DDLogicalPart.h:98
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
const std::vector< std::pair< const DDPartSelection *, const DDsvalues_type * > > & attachedSpecifics(void) const
const std::string & name() const
Returns the name.
Definition: DDName.cc:90
const DDMaterial & material(void) const
Returns a reference object of the material this LogicalPart is made of.
const DDName & ddname() const
Definition: DDBase.h:80