Orocos Real-Time Toolkit  2.9.0
PropertyComposition.cpp
Go to the documentation of this file.
3 #include "../Logger.hpp"
4 #include "../Property.hpp"
5 #include "types/Types.hpp"
6 
7 using namespace RTT;
8 using namespace RTT::detail;
9 
10 bool RTT::types::composePropertyBag( PropertyBag const& sourcebag, PropertyBag& target )
11 {
12  if ( !target.empty() ) {
13  log(Error) <<"composePropertyBag: target bag must be empty."<< endlog();
14  return false;
15  }
16  bool has_error = false;
17  PropertyBag::const_iterator sit = sourcebag.begin();
18  for( ; sit != sourcebag.end(); ++sit) {
19  // test if it's a property bag, then we need to recurse:
21  isbag = *sit; // separate assignment avoids error message !
22  if ( isbag.ready() && isbag.value().getType() != "PropertyBag") {
23  // typed property bag, need to compose it.
24  TypeInfo* ti = Types()->type( isbag.value().getType() );
25  if ( ti == 0) {
26  log(Error) <<"Could not compose unknown type '" << isbag.value().getType() <<"'." <<endlog();
27  has_error = true;
28  continue;
29  }
30  PropertyBase* tgtprop = ti->buildProperty(isbag.getName(), isbag.getDescription());
31  if ( ti->composeType(isbag.getDataSource(), tgtprop->getDataSource()) ) {
32  log(Debug) << "Used user's composition function for " << tgtprop->getName() <<":"<<tgtprop->getType()<<endlog();
33  target.ownProperty(tgtprop);
34  } else {
35  log(Error) <<"The type '" << isbag.value().getType() <<"' did not provide a type composition function, but I need one to compose it from a PropertyBag." <<endlog();
36  delete tgtprop;
37  has_error = true;
38  continue;
39  }
40  } else {
41  if ( isbag.ready() ) {
42  // plain property bag, clone and recurse:
43  Property<PropertyBag>* newbag = new Property<PropertyBag>(isbag.getName(), isbag.getDescription());
44  if ( composePropertyBag(isbag.value(), newbag->value()) == false) {
45  delete newbag;
46  has_error = true;
47  continue;
48  }
49  target.ownProperty( newbag );
50  } else {
51  // plain property, not a bag:
52  target.ownProperty( (*sit)->clone() );
53  }
54  }
55  }
56 
57  return !has_error;
58 }
59 
61 {
62  if ( !target.empty() ) {
63  log(Error) <<"decomposePropertyBag: target bag must be empty."<< endlog();
64  return false;
65  }
66  PropertyBag::const_iterator sit = sourcebag.begin();
67  while( sit != sourcebag.end()) {
68  // test if it's a property bag, then we need to recurse:
70  isbag = *sit; // avoid logging error
71  if ( isbag.ready() ) {
72  // create an empty instance to recurse in:
73  Property<PropertyBag>* newtarget = new Property<PropertyBag>(isbag.getName(), isbag.getDescription() );
74  newtarget->value().setType( isbag.rvalue().getType() );
75  target.ownProperty( newtarget );
76  if ( decomposePropertyBag(isbag.value(), newtarget->value() ) == false) {
77  assert(false && "internal error in decomposePropertyBag."); // this is a best effort function.
78  }
79  } else {
80  // decompose non-bag type:
81  log(Debug) << "Checking for decompose "<< (*sit)->getName() <<endlog();
82 
83  // Try decomposeType() first because this is the user's implementation of decomposition:
84  DataSourceBase::shared_ptr dsb = (*sit)->getTypeInfo()->decomposeType( (*sit)->getDataSource() );
85  if ( dsb ) {
86  // check if type returned itself to avoid decomposition:
87  if ( dsb == (*sit)->getDataSource() ) {
88  // primitive type : clone the instance
89  target.ownProperty( (*sit)->clone() );
90  } else {
92  if ( bagds ) {
93  // property bag ? -> further decompose
94  // create an empty instance to recurse in:
95  Property<PropertyBag>* newtarget = new Property<PropertyBag>((*sit)->getName(), (*sit)->getDescription() );
96  newtarget->value().setType( bagds->rvalue().getType() );
97  target.ownProperty( newtarget );
98  if ( decomposePropertyBag(bagds->rvalue(), newtarget->value() ) == false) {
99  assert(false && "internal error in decomposePropertyBag."); // this is a best effort function.
100  }
101  } else {
102  // other type ? -> add
103  base::PropertyBase* p = dsb->getTypeInfo()->buildProperty((*sit)->getName(), (*sit)->getDescription(), dsb);
104  if ( target.ownProperty( p ) == false)
105  log(Error) <<"Failed to create a property of decomposed data of type "<<(*sit)->getType() <<endlog();
106  }
107  }
108  } else {
109  // if decomposeType() returned null, try generic decomposition, based on getMember():
110  Property<PropertyBag> res((*sit)->getName(), (*sit)->getDescription() );
111  // propertyDecomposition decomposes fully, so the result does not need to be recursed:
112  if ( types::propertyDecomposition(*sit, res.value() ) ) {
113  target.ownProperty( res.clone() );
114  }
115  }
116  }
117  ++sit;
118  }
119  return true;
120 }
virtual base::DataSourceBase::shared_ptr getDataSource() const
Get an assignable base::DataSource through which this PropertyBase can be manipulated.
Definition: Property.hpp:393
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
bool ready() const
Inspect if this Property is correctly initialised and ready for usage.
Base class for all properties.
bool RTT_API composePropertyBag(PropertyBag const &sourcebag, PropertyBag &target)
Uses the type composition to compose all typed properties from a property bag.
const_reference_t rvalue() const
Read-only (const&) access to the value of the Property.
Definition: Property.hpp:285
A container for holding references to properties.
Definition: PropertyBag.hpp:96
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
bool RTT_API decomposePropertyBag(PropertyBag const &sourcebag, PropertyBag &target)
Inverse of RTT::types::composePropertyBag().
Convenient short notation for every sub-namespace of RTT.
virtual const_reference_t rvalue() const =0
Get a const reference to the value of this DataSource.
A property represents a named value of any type with a description.
Definition: Property.hpp:76
virtual std::string getType() const =0
Returns the type of this PropertyBase.
A class for representing a user type, and which can build instances of that type. ...
Definition: TypeInfo.hpp:67
bool propertyDecomposition(base::PropertyBase *source, PropertyBag &targetbag, bool recurse)
Uses the type decomposition to decompose a property into a property bag that refers to all its parts...
const std::string & getDescription() const
Get a description of the property.
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
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.
bool empty() const
Return true if no properties are present in this bag.
boost::intrusive_ptr< DataSource< T > > shared_ptr
Definition: DataSource.hpp:115
const std::string & getName() const
Get the name of the property.
static DataSource< T > * narrow(base::DataSourceBase *db)
This method narrows a base::DataSourceBase to a typeded DataSource, possibly returning a new object...
Definition: DataSource.inl:66
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
virtual DataSourceBase::shared_ptr getDataSource() const =0
Get an assignable base::DataSource through which this PropertyBase can be manipulated.
iterator begin()
virtual const types::TypeInfo * getTypeInfo() const =0
Returns the types::TypeInfo object of this Property.