Orocos Real-Time Toolkit  2.9.0
PropertyBag.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon May 10 19:10:30 CEST 2004 PropertyBag.cxx
3 
4  PropertyBag.cxx - description
5  -------------------
6  begin : Mon May 10 2004
7  copyright : (C) 2004 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 #ifdef ORO_PRAGMA_INTERFACE
39 #pragma implementation
40 #endif
41 #include "PropertyBag.hpp"
42 #include "Property.hpp"
44 #include "types/Types.hpp"
45 #include "Logger.hpp"
46 #include <algorithm>
47 #include "rtt-fwd.hpp"
48 
49 namespace RTT
50 {
51  using namespace detail;
52  using namespace std;
53 
55  : mproperties(), type("PropertyBag")
56  {}
57 
58  PropertyBag::PropertyBag( const std::string& _type)
59  : mproperties(), type(_type)
60  {}
61 
63  : mproperties()
64  {
65  *this = orig;
66  }
67 
69  {
70  this->clear();
71  }
72 
74  {
75  this->addProperty(*p);
76  }
77 
79  {
80  this->removeProperty(p);
81  }
82 
84  {
85  if (p == 0)
86  return false;
87  if ( ! p->ready() )
88  return false;
89  removeProperty(p);
90  mproperties.push_back(p);
91  mowned_props.push_back(p);
92  return true;
93  }
94 
96  {
97  if (p == 0)
98  return false;
99  const_iterator i = std::find(mowned_props.begin(), mowned_props.end(), p);
100  if ( i != mowned_props.end() )
101  return true;
102  return false;
103  }
104 
106  {
107  if (&p == 0)
108  return false;
109  if ( ! p.ready() )
110  return false;
111  mproperties.push_back(&p);
112  return true;
113  }
114 
116  {
117  if (p == 0)
118  return false;
119  iterator i = std::find(mproperties.begin(), mproperties.end(), p);
120  if ( i != mproperties.end() ) {
121  mproperties.erase(i);
122  i = std::find(mowned_props.begin(), mowned_props.end(), p);
123  if ( i != mowned_props.end() ) {
124  delete *i;
125  mowned_props.erase(i); // invalidates i
126  }
127  return true;
128  }
129  return false;
130  }
131 
133  {
134  mproperties.clear();
135  for ( iterator i = mowned_props.begin();
136  i != mowned_props.end();
137  i++ )
138  {
139  delete *i;
140  }
141  mowned_props.clear();
142  }
143 
144  void PropertyBag::list(std::vector<std::string> &names) const
145  {
146  for ( const_iterator i = mproperties.begin();
147  i != mproperties.end();
148  i++ )
149  {
150  names.push_back( (*i)->getName() );
151  }
152  }
153 
154  std::vector<std::string> PropertyBag::list() const
155  {
156  std::vector<std::string> names;
157  for ( const_iterator i = mproperties.begin();
158  i != mproperties.end();
159  i++ )
160  {
161  names.push_back( (*i)->getName() );
162  }
163  return names;
164  }
165 
167  {
168  Properties names;
169  for ( const_iterator i = mproperties.begin();
170  i != mproperties.end();
171  i++ )
172  {
173  if ( (*i)->getName() == name )
174  names.push_back( (*i) );
175  }
176  return names;
177  }
178 
179 
181  {
182  for ( const_iterator i = mproperties.begin();
183  i != mproperties.end();
184  i++ )
185  {
186  (*i)->identify(pi);
187  }
188  }
189 
191  {
192  for ( const_iterator i = mproperties.begin();
193  i != mproperties.end();
194  i++ )
195  {
196  (*i)->identify(pi);
197  }
198  }
199 
204  struct FindProp : public std::binary_function<const base::PropertyBase*,const std::string, bool>
205  {
206  bool operator()(const base::PropertyBase* b1, const std::string& b2) const { return b1->getName() == b2; }
207  };
210  PropertyBase* PropertyBag::find(const std::string& name) const
211  {
212  const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(FindProp(), name ) ) );
213  if ( i != mproperties.end() )
214  return ( *i );
215  return 0;
216  }
217 
218  base::PropertyBase* PropertyBag::getProperty(const std::string& name) const
219  {
220  const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(FindProp(), name ) ) );
221  if ( i != mproperties.end() )
222  return *i;
223  return 0;
224  }
225 
226 
228  {
229  if(this == &orig)
230  return *this;
231 
232  this->clear();
233 
234  for( const_iterator i = orig.mproperties.begin(); i != orig.mproperties.end(); ++i) {
235  if ( orig.ownsProperty( *i ) ) {
236  PropertyBase* copy = (*i)->create( (*i)->getDataSource() );
237  this->ownProperty( copy );
238  } else {
239  this->add( *i );
240  }
241  }
242 
243  this->setType( orig.getType() );
244  return *this;
245  }
246 
248  {
249  //iterate over orig, update or clone PropertyBases
250  const_iterator it(source.getProperties().begin());
251  while ( it != source.getProperties().end() )
252  {
253  PropertyBase* mine = find( (*it)->getName() );
254  if (mine != 0)
255  remove(mine);
256  add( (*it) );
257  ++it;
258  }
259  this->setType( source.getType() );
260  return *this;
261  }
262 
263  template<>
265  {
266  if ( !ready() )
267  return false;
268  if ( _description.empty() )
269  _description = orig.getDescription();
270  return updateProperties( this->_value->set(), orig.rvalue() );
271  }
272 
273  template<>
275  {
276  if ( !ready() )
277  return false;
278  return refreshProperties( this->_value->set(), orig.rvalue() );
279  }
280 
281  template<>
283  {
284  if ( !ready() )
285  return false;
286  _name = orig.getName();
287  _description = orig.getDescription();
288  return copyProperties( this->_value->set(), orig.rvalue() );
289  }
290 
291  std::ostream& operator<<(std::ostream& os, const PropertyBag& bag) {
292  int size = bag.size();
293  os << "[[";
294  for(int i=0; i != size; ++i) {
295  os << bag.getItem(i)->getName() << "='"<< bag.getItem(i) <<"'"<<endl;
296  }
297  os << "]]";
298 
299  return os;
300  }
301 
302  std::istream& operator>>(std::istream& is, PropertyBag& bag) { return is; }
303 
304 
305  PropertyBase* findProperty(const PropertyBag& bag, const std::string& nameSequence, const std::string& separator)
306  {
307  PropertyBase* result;
308  Property<PropertyBag>* result_bag;
309  std::string token;
310  std::string::size_type start = 0;
311  if ( separator.length() != 0 && nameSequence.find(separator) == 0 ) // detect 'root' attribute
312  start = separator.length();
313  std::string::size_type len = nameSequence.find(separator, start);
314  if (len != std::string::npos) {
315  token = nameSequence.substr(start,len-start);
316  start = len + separator.length(); // reset start to next token.
317  if ( start >= nameSequence.length() )
318  start = std::string::npos;
319  }
320  else {
321  token = nameSequence.substr(start);
322  start = std::string::npos; // do not look further.
323  }
324  result = bag.find(token);
325  if (result != 0 ) // get the base with this name
326  {
327  result_bag = dynamic_cast<Property<PropertyBag>*>(result);
328  if ( result_bag != 0 && start != std::string::npos ) {
329  return findProperty( result_bag->rvalue(), nameSequence.substr( start ), separator );// a bag so search recursively
330  }
331  else
332  return result; // not a bag, so it is a result.
333  }
334  return 0; // failure
335  }
336 
340  void listPropertiesHelper(const PropertyBag& source, const std::string& separator, const string& prefix, vector<string>& result)
341  {
342  PropertyBag::const_iterator it( source.getProperties().begin() );
343  while ( it != source.getProperties().end() ) {
344  Property<PropertyBag>* sub = dynamic_cast<Property<PropertyBag>*>(*it);
345  string itemname = prefix.empty() ? (*it)->getName() : prefix + separator + (*it)->getName();
346  result.push_back( itemname );
347  if ( sub && sub->ready() ) {
348  listPropertiesHelper( sub->value(), separator, itemname, result );
349  }
350  ++it;
351  }
352  }
353 
356  void listDescriptionsHelper(const PropertyBag& source, const std::string& separator, vector<string>& result)
357  {
358  PropertyBag::const_iterator it( source.getProperties().begin() );
359  while ( it != source.getProperties().end() ) {
360  Property<PropertyBag>* sub = dynamic_cast<Property<PropertyBag>*>(*it);
361  result.push_back( (*it)->getDescription() );
362  if ( sub && sub->ready() ) {
363  listDescriptionsHelper( sub->value(), separator, result );
364  }
365  ++it;
366  }
367  }
370  vector<string> listProperties(const PropertyBag& source, const std::string& separator)
371  {
372  vector<string> result;
373  listPropertiesHelper( source, separator, "", result);
374  return result;
375  }
376 
377  vector<string> listPropertyDescriptions(const PropertyBag& source, const std::string& separator)
378  {
379  vector<string> result;
380  listDescriptionsHelper( source, separator, result);
381  return result;
382  }
383 
384  bool storeProperty(PropertyBag& bag, const std::string& path, base::PropertyBase* item, const std::string& separator )
385  {
386  Logger::In in("storeProperty");
387  if ( path.empty() || path == separator )
388  return bag.ownProperty( item );
389  // find top-level parent
390  string pname, rest;
391  if ( path.find(separator) != string::npos ) {
392  pname = path.substr( 0, path.find(separator));
393  rest = path.substr( path.find(separator) + separator.length() );
394  } else {
395  pname = path;
396  }
397 
398  if ( pname.empty() && !rest.empty() )
399  return storeProperty( bag, rest, item, separator); // recurse
400 
401  // pname is parent
402  PropertyBase* parent = bag.find(pname);
403  if (!parent) {
404  bag.ownProperty( new Property<PropertyBag>(pname,"") );
405  parent = bag.find(pname);
406  }
407  Property<PropertyBag>* parentbag = dynamic_cast<Property<PropertyBag>* >(parent);
408  if ( !parentbag ) {
409  log(Error) << "Path component '" << pname << "' in path '"<<path<<"' does not point to a PropertyBag."<<endlog();
410  return false;
411  }
412  // recurse using new parentbag and rest.
413  return storeProperty( parentbag->value(), rest, item, separator);
414  }
415 
416  bool removeProperty(PropertyBag& bag, const std::string& path, const std::string& separator )
417  {
418  // empty path
419  if ( path.empty() || path == separator )
420  return false;
421  // single item path
422  if ( path.find( separator ) == string::npos)
423  return bag.removeProperty( bag.find(path) );
424  // multi item path
425  string prefix = path.substr( 0, path.rfind(separator));
426  string pname = path.substr( path.rfind(separator) + separator.length() );
427  // '.item' form:
428  if ( prefix.empty() )
429  return bag.removeProperty( bag.find(pname) );
430  // 'bag.item' form:
431  Property<PropertyBag> parent = findProperty( bag, prefix);
432  if ( !parent.ready() )
433  return false;
434  return parent.value().removeProperty( parent.value().find( pname ) );
435  }
436 
437  bool updateOrRefreshProperty( PropertyBase* source, PropertyBase* target, bool update)
438  {
439 #ifndef NDEBUG
440  if (update)
441  log(Debug) << "updateProperties: updating Property "
442  << source->getType() << " "<< source->getName()
443  << "." << endlog();
444  else
445  log(Debug) << "refreshProperties: refreshing Property "
446  << source->getType() << " "<< source->getName()
447  << "." << endlog();
448 #endif
449  // no need to make new one, just update existing one
450  if ( (update && target->update( source ) == false ) || (!update && target->refresh( source ) == false ) ) {
451  // try conversion
452  DataSourceBase::shared_ptr converted = target->getTypeInfo()->convert( source->getDataSource() );
453  if ( !converted || converted == source->getDataSource() ) {
454  // no conversion, try composition:
455  converted = target->getDataSource();
456  if (target->getTypeInfo()->composeType( source->getDataSource(), converted ) ) {
457  // case where there is a type composition -> target was updated by composeType
458  log(Debug) << "Composed Property "
459  << target->getType() << " "<< source->getName() << " to type " <<target->getType()
460  << " from type " << source->getType() << endlog();
461  return true;
462  } else {
463  //if ( !target->getTypeInfo()->composeType( source->getDataSource(), target->getDataSource() ) )
464  log(Error) << (update ? "updateProperties: " : "refreshProperties: ") << " Could not update, nor convert Property "
465  << target->getType() << " "<< target->getName()
466  << ": type mismatch, can not update with "
467  << source->getType() << " "<< source->getName() << endlog();
468  return false;
469  }
470  } else {
471  // conversion: update with converted value:
472  // case where there is a type conversion -> do the update of the target
473  // since 'converted' might be a non-Assignable DataSource, we need a work-around:
474  PropertyBase* dummy = target->getTypeInfo()->buildProperty("","");
475  dummy->getDataSource()->update( converted.get() );
476  assert(dummy->getTypeInfo() == converted->getTypeInfo() );
477  // we need to use the PropertyBase API and not the DataSource API !
478  if (update)
479  target->update(dummy);
480  else
481  target->refresh(dummy);
482  log(Debug) << "Converted Property "
483  << target->getType() << " "<< source->getName() << " to type " <<dummy->getType()
484  << " from type " << source->getType() << endlog();
485  }
486  }
487  return true;
488  }
489 
490  bool refreshProperties(const PropertyBag& target, const PropertyBag& source, bool allprops)
491  {
492  Logger::In in("refreshProperties");
493 
494  // if the target is of different type than source, it is replaced by source.
495  if ( Types()->type(target.getType()) != Types()->getTypeInfo<PropertyBag>() && Types()->type( target.getType() ) != Types()->type( source.getType() ) ) {
496  log(Error) << "Can not populate typed PropertyBag '"<< target.getType() <<"' from '"<<source.getType()<<"' (source and target type differed)."<<endlog();
497  return false;
498  }
499 
500  //iterate over source, update PropertyBases
501  PropertyBag::const_iterator it( target.getProperties().begin() );
502  bool failure = false;
503  while ( it != target.getProperties().end() )
504  {
505  PropertyBase* srcprop;
506  if ( (*it)->getName() == "" ) //&& target.getType() == "Sequence" )
507  srcprop = source.getItem( it - target.getProperties().begin() );
508  else
509  srcprop = source.find( (*it)->getName() );
510  PropertyBase* tgtprop = *it;
511  if (srcprop != 0)
512  {
513  if (updateOrRefreshProperty( srcprop, tgtprop, false) == false)
514  return false;
515  // ok.
516  } else if (allprops) {
517  log(Error) << "Could not find Property "
518  << tgtprop->getType() << " "<< tgtprop->getName()
519  << " in source."<< endlog();
520  failure = true;
521  }
522  ++it;
523  }
524  return !failure;
525  }
526 
527  bool refreshProperty(const PropertyBag& target, const PropertyBase& source)
528  {
529  PropertyBase* target_prop;
530  // dynamic_cast ?
531  if ( 0 != (target_prop = target.find( source.getName() ) ) )
532  {
533  return target_prop->refresh( &source );
534  }
535  return false;
536  }
537 
538  bool copyProperties(PropertyBag& target, const PropertyBag& source)
539  {
540  // Make a full deep copy.
541  //iterate over source, clone all PropertyBases
542  PropertyBag::const_iterator it( source.getProperties().begin() );
543  while ( it != source.getProperties().end() )
544  {
545  // step 1 : clone a new instance (non deep copy)
546  PropertyBase* temp = (*it)->create();
547  // step 2 : deep copy clone with original.
548  temp->copy( *it );
549  // step 3 : add result to target bag.
550  target.ownProperty( temp );
551  ++it;
552  }
553  return true;
554  }
555 
556 
557  bool updateProperties(PropertyBag& target, const PropertyBag& source)
558  {
559  // check type consistency...
560  if ( target.getType() == "" || target.getType() == "type_less" )
561  target.setType("PropertyBag"); // RTT 1.2.0
562 
563  // if the target is of different type than source, it is replaced by source.
564  if ( Types()->type( target.getType() ) != Types()->getTypeInfo<PropertyBag>() && Types()->type(target.getType()) != Types()->type(source.getType()) ) {
565  log(Error) << "Can not populate typed PropertyBag '"<< target.getType() <<"' from '"<<source.getType()<<"' (source and target type differed)."<<endlog();
566  return false;
567  }
568 
569  target.setType( source.getType() );
570 
571  // Make an updated if present, create if not present
572  //iterate over source, update or clone PropertyBases
573 
574  PropertyBag::Names allnames = source.list();
575  PropertyBag::Names::const_iterator endnames = std::unique(allnames.begin(), allnames.end());
576  PropertyBag::Names::const_iterator it( allnames.begin() );
577  while ( it != endnames )
578  {
579  PropertyBag::Properties sources = source.getProperties(*it);
580  PropertyBag::Properties mines = target.getProperties(*it);
581  PropertyBag::iterator mit = mines.begin();
582  for( PropertyBag::const_iterator sit = sources.begin(); sit != sources.end(); ++sit ) {
583  if ( mit != mines.end() ) {
584  assert( (*sit)->getName() == (*mit)->getName());
585  if ( updateOrRefreshProperty( *sit, *mit, true) == false)
586  return false;
587  // ok.
588  ++mit;
589  }
590  else
591  {
592 #ifndef NDEBUG
594  Logger::log() << "updateProperties: creating Property "
595  << (*sit)->getType() << " "<< (*sit)->getName()
596  << "." << Logger::endl;
597 #endif
598  // step 1: test for composing a typed property bag:
599  PropertyBase* temp = 0;
600 #if 0
601  Property<PropertyBag>* tester = dynamic_cast<Property<PropertyBag>* >(*sit);
602  if (tester && Types()->type( tester->value().getType() ) != Types()->getTypeInfo<PropertyBag>()) {
603  if (TypeInfo* ti = types::Types()->type(tester->value().getType())) {
604  temp = ti->buildProperty( tester->getName(), tester->getDescription() );
605  assert(temp);
606  bool res = temp->getTypeInfo()->composeType( tester->getDataSource(), temp->getDataSource() );
607  if (!res ) return false;
608  }
609  }
610 #endif
611  if (!temp) {
612  // fallback : clone a new instance (non deep copy)
613  temp = (*sit)->create();
614  // deep copy clone with original, will never fail.
615  temp->update( (*sit) );
616  }
617  // step 3 : add result to target bag.
618  target.ownProperty( temp );
619  }
620  }
621  ++it;
622  }
623  return true;
624  }
625 
626  bool updateProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator)
627  {
628  Logger::In in("updateProperty");
629  // this code has been copied&modified from findProperty().
630  PropertyBase* source_walker;
631  PropertyBase* target_walker;
632  std::string token;
633  std::string::size_type start = 0;
634  if ( separator.length() != 0 && name.find(separator) == 0 ) // detect 'root' attribute
635  start = separator.length();
636  std::string::size_type len = name.find(separator, start);
637  if (len != std::string::npos) {
638  token = name.substr(start,len-start);
639  start = len + separator.length(); // reset start to next token.
640  if ( start >= name.length() )
641  start = std::string::npos;
642  }
643  else {
644  token = name.substr(start);
645  start = std::string::npos; // do not look further.
646  }
647  source_walker = source.find(token);
648  target_walker = target.find(token);
649  if (source_walker != 0 )
650  {
651  if ( target_walker == 0 ) {
652  // if not present in target, create it !
653  target_walker = source_walker->create();
654  target.ownProperty( target_walker );
655  }
656  Property<PropertyBag>* source_walker_bag;
657  Property<PropertyBag>* target_walker_bag;
658  source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker);
659  target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker);
660  if ( source_walker_bag != 0 && start != std::string::npos ) {
661  if ( target_walker_bag == 0 ) {
662  log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog();
663  return false;
664  }
665  return updateProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );// a bag so search recursively
666  }
667  else {
668  // found it, update !
669  if (updateOrRefreshProperty( source_walker, target_walker, true) == false)
670  return false;
671  log(Debug) << "Found Property '"<<target_walker->getName() <<"': update done." << endlog();
672  return true;
673  }
674  } else {
675  // error wrong path, not present in source !
676  log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
677  return false;
678  }
679  // not reached.
680  return false; // failure
681  }
682 
683  bool refreshProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator)
684  {
685  Logger::In in("refreshProperty");
686  // this code has been copied&modified from findProperty().
687  PropertyBase* source_walker;
688  PropertyBase* target_walker;
689  std::string token;
690  std::string::size_type start = 0;
691  if ( separator.length() != 0 && name.find(separator) == 0 ) // detect 'root' attribute
692  start = separator.length();
693  std::string::size_type len = name.find(separator, start);
694  if (len != std::string::npos) {
695  token = name.substr(start,len-start);
696  start = len + separator.length(); // reset start to next token.
697  if ( start >= name.length() )
698  start = std::string::npos;
699  }
700  else {
701  token = name.substr(start);
702  start = std::string::npos; // do not look further.
703  }
704  source_walker = source.find(token);
705  target_walker = target.find(token);
706  if (source_walker != 0 )
707  {
708  if ( target_walker == 0 ) {
709  log(Error) << "Property '"<<source_walker->getName()<<"' was not found in target !"<<endlog();
710  return false;
711  }
712  Property<PropertyBag>* source_walker_bag;
713  Property<PropertyBag>* target_walker_bag;
714  source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker);
715  target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker);
716  if ( source_walker_bag != 0 && start != std::string::npos ) {
717  if ( target_walker_bag == 0 ) {
718  log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog();
719  return false;
720  }
721  return refreshProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );// a bag so search recursively
722  }
723  else {
724  if (updateOrRefreshProperty( source_walker, target_walker, false) == false)
725  return false;
726  log(Debug) << "Found Property '"<<target_walker->getName() <<"': refresh done." << endlog();
727  return true;
728  }
729  } else {
730  // error wrong path, not present in source !
731  log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
732  return false;
733  }
734  // not reached.
735  return false; // failure
736  }
737 
739  {
740  //non-recursive delete.
741  PropertyBag::const_iterator it( target.getProperties().begin() );
742  while ( it != target.getProperties().end() )
743  {
744  // This loop is solely for deleting not owned properties.
745  if (!target.ownsProperty( *it ))
746  delete (*it);
747  ++it;
748  }
749  target.clear();
750  }
751 
753  {
754  //iterate over target, delete PropertyBases
755  PropertyBag::const_iterator it( target.getProperties().begin() );
756  while ( it != target.getProperties().end() )
757  {
758  // This loop is solely for deleting not owned properties and recursing
759  Property<PropertyBag>* result = dynamic_cast< Property<PropertyBag>* >( *it );
760  if ( result != 0 )
761  deletePropertyBag( result->value() );
762  if (!target.ownsProperty( *it ))
763  delete (*it);
764  ++it;
765  }
766  // deletes owned properties.
767  target.clear();
768  }
769 
770  void flattenPropertyBag(PropertyBag& target, const std::string& separator)
771  {
772  //iterate over target, recursively flatten bags.
773  Property<PropertyBag>* result;
774  PropertyBag::const_iterator it( target.getProperties().begin() );
775  while ( it != target.getProperties().end() )
776  {
777  result = dynamic_cast< Property<PropertyBag>* >( *it );
778  if ( result != 0 )
779  {
780  flattenPropertyBag( result->value(), separator );// a bag so flatten recursively
781  // copy all elements from result to target.
782  PropertyBag::const_iterator flat_it( result->value().getProperties().begin() ) ;
783  if ( flat_it != result->value().getProperties().end() )
784  {
785  while (flat_it != result->value().getProperties().end() )
786  {
787  (*flat_it)->setName( result->getName() + separator + (*flat_it)->getName() );
788  target.add( (*flat_it) );
789  result->value().remove( *flat_it );
790  flat_it = result->value().getProperties().begin();
791  }
792  it = target.getProperties().begin(); // reset iterator
793  continue; // do not increase it
794  }
795  // the bag is empty now, but it must stay in target.
796  }
797  ++it;
798  }
799  }
800 
801 }
virtual base::DataSourceBase::shared_ptr getDataSource() const
Get an assignable base::DataSource through which this PropertyBase can be manipulated.
Definition: Property.hpp:393
Names list() const
List the names of all properties.
bool updateProperty(PropertyBag &target, const PropertyBag &source, const std::string &name, const std::string &separator)
This function updates (recursively) the values of a single Property object of one Bag with the proper...
void remove(base::PropertyBase *p)
Remove a property from the container.
Definition: PropertyBag.cpp:78
bool composeType(base::DataSourceBase::shared_ptr source, base::DataSourceBase::shared_ptr target) const
Compose a type (target) from a DataSourceBase (source) containing its members.
Definition: TypeInfo.hpp:386
base::DataSourceBase::shared_ptr convert(base::DataSourceBase::shared_ptr arg) const
Automatic conversion: convert a internal::DataSource to this type.
Definition: TypeInfo.cpp:118
void add(base::PropertyBase *p)
Add a valid property to the container.
Definition: PropertyBag.cpp:73
virtual bool refresh(const base::PropertyBase *other)
Refresh the value of this Property with the value of an other Property.
Definition: Property.hpp:314
bool updateOrRefreshProperty(PropertyBase *source, PropertyBase *target, bool update)
bool updateProperties(PropertyBag &target, const PropertyBag &source)
This function updates (recursively) the values of Property objects of one Bag with the values of Prop...
bool ready() const
Inspect if this Property is correctly initialised and ready for usage.
bool storeProperty(PropertyBag &bag, const std::string &path, base::PropertyBase *item, const std::string &separator)
Stores a property in a bag given a certain path with transfer of ownership.
vector< string > listProperties(const PropertyBag &source, const std::string &separator)
List all properties in a PropertyBag in a single list.
PropertyBag & operator<<(base::PropertyBase *item)
The &#39;add&#39; operator.
std::istream & operator>>(std::istream &is, BufferPolicy &bp)
const std::string & getType() const
virtual bool copy(const base::PropertyBase *other)
Copy an other Property onto this property.
Definition: Property.hpp:323
Base class for all properties.
bool copyProperties(PropertyBag &target, const PropertyBag &source)
This function copies (recursively) the Properties of one Bag into another Bag.
void setType(const std::string &newtype)
STL namespace.
const_reference_t rvalue() const
Read-only (const&) access to the value of the Property.
Definition: Property.hpp:285
virtual PropertyBase * create() const =0
Create a new default instance of the PropertyBase.
void list(Names &names) const
List the names of all properties.
A container for holding references to properties.
Definition: PropertyBag.hpp:96
basic_ostreams & endl(basic_ostreams &s)
Flush and newline.
Definition: rtstreams.cpp:110
reference_t value()
Access to the value of the Property.
Definition: Property.hpp:277
bool ownProperty(base::PropertyBase *p)
Set a property to be owned by this bag.
Definition: PropertyBag.cpp:83
virtual bool refresh(const PropertyBase *other)=0
Refresh the value of this Property with the value of an other Property.
PropertyBase * findProperty(const PropertyBag &bag, const std::string &nameSequence, const std::string &separator)
This function locates a Property in nested PropertyBags.
void deletePropertyBag(PropertyBag &target)
This function iterates over a PropertyBag and recursively deletes all Property objects.
PropertyBag & operator<<=(const PropertyBag &source)
The update operator.
Property< T > & addProperty(const std::string &name, T &attr)
Adds a variable of any type as a property to this bag.
base::PropertyBase * find(const std::string &name) const
Find the base::PropertyBase with name name.
A simple introspection interface to visit PropertyBags.
vector< string > listPropertyDescriptions(const PropertyBag &source, const std::string &separator)
List all descriptions of properties in a PropertyBag in a single list.
A property represents a named value of any type with a description.
Definition: Property.hpp:76
static std::ostream & endl(std::ostream &__os)
Definition: Logger.cpp:383
~PropertyBag()
Destroy this object and destroy all owned properties.
Definition: PropertyBag.cpp:68
virtual std::string getType() const =0
Returns the type of this PropertyBase.
bool removeProperty(base::PropertyBase *p)
Remove a property from the container.
PropertyBag & operator=(const PropertyBag &orig)
This assignment assigns all PropertyBases of another bag in this bag, making an exact copy or the ori...
A class for representing a user type, and which can build instances of that type. ...
Definition: TypeInfo.hpp:67
const std::string & getDescription() const
Get a description of the property.
bool refreshProperty(const PropertyBag &target, const PropertyBase &source)
Refresh one Property in the target bag with the new value.
Properties mowned_props
base::PropertyBase * buildProperty(const std::string &name, const std::string &desc, base::DataSourceBase::shared_ptr source=0) const
Build a Property of this type.
Definition: TypeInfo.hpp:214
std::string type
Properties & getProperties()
Returns a list of all the property objects in this bag.
TypeInfoRepository::shared_ptr Types()
Obtain a pointer to the global type system.
Definition: Types.cpp:48
Properties::const_iterator const_iterator
A const iterator over the Properties.
void flattenPropertyBag(PropertyBag &target, const std::string &separator)
This function flattens a PropertyBag recursively.
An interface which all classes which wish to visit a Property should implement.
base::PropertyBase * getProperty(const std::string &name) const
Get a Property with name name.
base::PropertyBase * getItem(int i) const
Returns the i&#39;th Property, starting from 0.
void identify(base::PropertyIntrospection *pi) const
Identify the contents of this bag through introspection.
void deleteProperties(PropertyBag &target)
This function iterates over a PropertyBag and deletes all Property objects in it without recursion...
Notify the Logger in which &#39;module&#39; the message occured.
Definition: Logger.hpp:159
std::vector< std::string > Names
The container to hold names of Properties.
static Logger & log()
As Instance(), but more userfriendly.
Definition: Logger.cpp:117
virtual bool update(const base::PropertyBase *other)
Update the value of this Property with the value of an other Property.
Definition: Property.hpp:305
const std::string & getName() const
Get the name of the property.
Properties::iterator iterator
An iterator over the Properties.
boost::intrusive_ptr< DataSourceBase > shared_ptr
Use this type to store a pointer to a DataSourceBase.
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
size_t size() const
Get the number of Properties in this bag.
virtual bool copy(const PropertyBase *other)=0
Copy an other Property onto this property.
PropertyBag()
The default constructor.
Definition: PropertyBag.cpp:54
bool refreshProperties(const PropertyBag &target, const PropertyBag &source, bool allprops)
This function refreshes the values of the properties in one PropertyBag with the values of the proper...
virtual bool update(const PropertyBase *other)=0
Update the value of this Property with the value of an other Property.
bool ownsProperty(base::PropertyBase *p) const
Returns true if this property is owned by this Bag.
Definition: PropertyBag.cpp:95
Properties mproperties
void clear()
Removes all PropertyBases from this bag, without deleting them.
virtual DataSourceBase::shared_ptr getDataSource() const =0
Get an assignable base::DataSource through which this PropertyBase can be manipulated.
std::vector< base::PropertyBase * > Properties
The container in which the properties are stored.
virtual const types::TypeInfo * getTypeInfo() const =0
Returns the types::TypeInfo object of this Property.