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 
18  bool alreadyIn( false );
19  for( const auto& p : ns )
20  {
21  if( p.ns() == n.ns())
22  {
23  alreadyIn = true;
24  break;
25  }
26  }
27  if( !alreadyIn )
28  {
29  ns.emplace_back( n );
30  }
31 }
32 
33 std::ostream &
34 operator<<( std::ostream & os, const DDLogicalPart & part )
35 {
37  if( defined.first )
38  {
39  os << *(defined.first) << " ";
40  if( defined.second )
41  {
42  part.rep().stream( os );
43  }
44  else
45  {
46  os << "* logicalpart not defined * ";
47  }
48  }
49  else
50  {
51  os << "* logicalpart not declared * ";
52  }
53  return os;
54 }
55 
56 // =================================================================================
57 
70 // now inlined...
71 
105  : DDBase<DDName, DDI::LogicalPart*>()
106 {
107  prep_ = StoreT::instance().create( name );
108  DD_NC( name );
109 }
110 
124  const DDMaterial & material,
125  const DDSolid & solid,
127  : DDBase<DDName,DDI::LogicalPart*>()
128 {
129  prep_ = StoreT::instance().create(ddname, new DDI::LogicalPart(material,solid,cat));
130  DD_NC(ddname);
131 }
132 
133 
134 // private!
135 /*
136 DDLogicalPart::DDLogicalPart(DDRedirect<DDLogicalPartImpl>* p, bool dummy)
137  : DDMultiRegistered<DDLogicalPartImpl>(p,true)
138 { }
139 */
140 
142 {
143  return rep().category();
144 }
145 
146 
148 {
149  return rep().material();
150 }
151 
152 
154 {
155  return rep().solid();
156 }
157 
158 
159 /*
160  The weight must be calculated by using the method DDCompactView::weight().
161  For the weight calculation the full subtree of children is expanded. As a
162  usefull side-effect the weight of all LogicalParts of the children is calculated
163  as well.
164  This method will return 0, if the weight has not yet been calculated
165  using the DDCompactView, otherwise the weight of the component and all
166  its sub-components.
167  \todo In future DDLogicalPart::weight() will be sufficient for weight calculations
168  \todo make the method 'const'
169 */
171 {
172  return rep().weight();
173 }
174 
175 
229 std::vector<const DDsvalues_type *> DDLogicalPart::specifics() const
230 {
231  std::vector<const DDsvalues_type*> result;
232  rep().specificsV(result);
233  return result;
234 }
235 
236 
238 {
240  rep().mergedSpecificsV(result);
241  return result;
242 }
243 
244 // for internal use only
245 void DDLogicalPart::addSpecifics(const std::pair<const DDPartSelection*, const DDsvalues_type*> & s)
246 {
247  rep().addSpecifics(s);
248 }
249 void DDLogicalPart::removeSpecifics(const std::pair<DDPartSelection*,DDsvalues_type*> & s)
250 {
251  rep().removeSpecifics(s);
252 }
254 {
255  return rep().hasDDValue(v);
256 }
257 
258 // finds out whether a DDLogicalPart is registered & already valid (initialized)
259 // - returns (true,""), if so; result holds the corresponding DDLogicalPart
260 // - returns (false,"some status message") otherwise
261 // - nm corresponds to a regular expression, but will be anchored ( ^regexp$ )
262 // - ns corresponds to a regular expression, but will be anchored ( ^regexp$ )
263 #include <regex.h>
264 #include <cstddef>
265 
266 namespace
267 {
268  struct Regex
269  {
270  explicit Regex( const std::string & s )
271  : m_ok( false ),
272  me( s )
273  {
274  size_t p = me.find(".");
275  m_ok = p != std::string::npos;
276  if( m_ok )
277  {
278  if( p > 0 )
279  {
280  m_range.first = me.substr( 0, p );
281  m_range.second = m_range.first + "{"; // '{' is 'z'+1
282  }
283  me = "^" + me + "$";
284  regcomp( &m_regex, me.c_str(), 0 );
285  }
286  }
287 
288  ~Regex( void ) { if( m_ok ) regfree( &m_regex ); }
289 
290  bool empty( void ) const { return me.empty(); }
291 
292  bool notRegex( void ) const { return !m_ok; }
293 
294  const std::string & value( void ) const { return me;}
295 
296  bool match( const std::string & s ) const {
297  if( m_ok )
298  return !regexec( &m_regex, s.c_str(), 0, nullptr, 0 );
299  else
300  return me == s;
301  }
302 
303  const std::pair< std::string, std::string> & range( void ) const { return m_range; }
304  private:
305  bool m_ok;
306  regex_t m_regex;
307  std::string me;
308  // range of me in a collating sequence
309  std::pair<std::string, std::string> m_range;
310  };
311 }
312 
313 std::pair<bool, std::string>
314 DDIsValid( const std::string & ns, const std::string & nm, std::vector<DDLogicalPart> & result, bool doRegex )
315 {
316  if( !doRegex )
317  {
318  DDName ddnm( nm, ns );
319  result.emplace_back( DDLogicalPart( ddnm ));
320  return std::make_pair( true, "" );
321  }
323  Regex aRegex( nm );
324  Regex aNsRegex( ns );
325  bool emptyNs = aNsRegex.empty();
326 
327  // THIS IS THE SLOW PART: I have to compare every namespace & name of every
328  // logical part with a regex-comparison .... a linear search always through the
329  // full range of logical parts!!!!
330  /*
331  Algorithm description:
332  x. empty nm and ns argument of method means: use all matching regex ^.*$
333  a. iterate over all logical part names, match against regex for names
334  b. iterate over all namespaces of names found in a & match against regex for namespaces
335  */
336  LPNAMES::value_type::const_iterator bn(LPNAMES::instance().begin()),
337  ed(LPNAMES::instance().end());
338  typedef std::vector< LPNAMES::value_type::const_iterator> Candidates;
339  Candidates candidates;
340  if ( aRegex.notRegex() ) {
341  LPNAMES::value_type::const_iterator it = LPNAMES::instance().find(aRegex.value());
342  if (it!=ed) candidates.emplace_back(it);
343  }
344  else {
345  if ( !aRegex.range().first.empty()) {
346  bn = LPNAMES::instance().lower_bound(aRegex.range().first);
347  ed = LPNAMES::instance().upper_bound(aRegex.range().second);
348  }
349  for (LPNAMES::value_type::const_iterator it=bn; it != ed; ++it)
350  if(aRegex.match(it->first)) candidates.emplace_back(it);
351  }
352  for (const auto & it : candidates) {
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.emplace_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.emplace_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.emplace_back(std::make_pair(it->first,*nsit));
370  result.emplace_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.empty()) {
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:15
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:38
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
void removeSpecifics(const std::pair< DDPartSelection *, DDsvalues_type * > &)
DDLogicalPart(void)
The default constructor provides an uninitialzed reference object.
Definition: DDLogicalPart.h:96
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