Orocos Real-Time Toolkit  2.9.0
PropertyDecomposition.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 PropertyDecomposition.cpp
3 
4  PropertyDecomposition.cpp - description
5  -------------------
6  begin : Tue September 07 2010
7  copyright : (C) 2010 The SourceWorks
8  email : peter@thesourceworks.com
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 
47 #include "../internal/DataSource.hpp"
48 #include <vector>
49 #include <string>
50 #include <memory>
51 #include <boost/lexical_cast.hpp>
52 #include "../Logger.hpp"
53 #include "TypeInfo.hpp"
54 #include "../Property.hpp"
55 
56 
57 using namespace std;
58 using namespace RTT;
59 using namespace RTT::detail;
60 
61 namespace RTT { namespace types {
62 
63 bool propertyDecomposition( base::PropertyBase* source, PropertyBag& targetbag, bool recurse )
64 {
65  if (!source)
66  return false;
68  if (!dsb)
69  return false;
70  return typeDecomposition( dsb, targetbag, recurse);
71 }
72 
74 {
75  if (!dsb)
76  return false;
77 
78  // try user's custom type decomposition first:
79  DataSourceBase::shared_ptr decomposed = dsb->getTypeInfo()->decomposeType(dsb);
80  // In cases where decomposeType() returned dsb itself, we stop the decomposition here.
81  if (decomposed == dsb)
82  return false;
83  if (decomposed) {
84  // decomposed is or another type, or a PropertyBag
86  if ( bag ) {
87  // get it and copy it.
88  targetbag = bag->rvalue();
89  return true;
90  } else {
91  // it converted to something else than a bag.
92  //log(Debug) << "propertyDecomposition: decomposeType() of "<< dsb->getTypeName() << " did not return a PropertyBag but a " << decomposed->getTypeName() << endlog();
93  return false;
94  }
95  }
96 
97  vector<string> parts = dsb->getMemberNames();
98  if ( parts.empty() ) {
99  log(Debug) << "propertyDecomposition: "<< dsb->getTypeName() << " does not have any members." << endlog();
100  return false;
101  }
102 
103  targetbag.setType( dsb->getTypeName() );
104 
105  // needed for recursion.
106 #if __cplusplus > 199711L
107  unique_ptr< Property<PropertyBag> >
108 #else
109  auto_ptr< Property<PropertyBag> >
110 #endif
111  recurse_bag( new Property<PropertyBag>("recurse_bag","Part") );
112  // First at the explicitly listed parts:
113  for(vector<string>::iterator it = parts.begin(); it != parts.end(); ++it ) {
114  DataSourceBase::shared_ptr part = dsb->getMember( *it );
115  if (!part) {
116  log(Error) <<"propertyDecomposition: Inconsistent type info for "<< dsb->getTypeName() << ": reported to have part '"<<*it<<"' but failed to return it."<<endlog();
117  continue;
118  }
119  if ( !part->isAssignable() ) {
120  // For example: the case for size() and capacity() in SequenceTypeInfo
121  log(Debug)<<"propertyDecomposition: Part "<< *it << ":"<< part->getTypeName() << " is not changeable."<<endlog();
122  continue;
123  }
124  // finally recurse or add it to the target bag:
125  PropertyBase* newpb = part->getTypeInfo()->buildProperty(*it,"Part",part);
126  if ( !newpb ) {
127  log(Error)<< "Decomposition failed because Part '"<<*it<<"' is not known to type system."<<endlog();
128  continue;
129  }
130  if ( !recurse )
131  targetbag.ownProperty( newpb ); // leaf
132  else if ( !propertyDecomposition( newpb, recurse_bag->value(), true) ) {
133  //recurse_bag is empty
134  assert( recurse_bag->rvalue().empty() );
136  base::DataSourceBase::shared_ptr converted = clone->getTypeInfo()->decomposeType(clone);
137  if ( converted && converted != clone ) {
138  // converted contains another type
139  targetbag.add( converted->getTypeInfo()->buildProperty(*it, "", converted) );
140  } else {
141  // use the original
142  targetbag.add( newpb );
143  }
144  } else {
145  assert( recurse_bag->rvalue().size() >= 1 );
146  recurse_bag->setName(*it);
147  // setType() is done by recursive of self.
148  targetbag.ownProperty( recurse_bag.release() ); //recursed.
149  recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Part") );
150  delete newpb; // since we recursed, the recurse_bag now 'embodies' newpb.
151  }
152  }
153 
154  // Prepare recurse_bag for storing composite items:
155  recurse_bag->setDescription("Item");
156 
157  // Next get the numbered parts:
158  DataSource<int>::shared_ptr size = DataSource<int>::narrow( dsb->getMember("size").get() );
159  if (size) {
160  int msize = size->get();
161  for (int i=0; i < msize; ++i) {
162  string indx = boost::lexical_cast<string>( i );
163  DataSourceBase::shared_ptr item = dsb->getMember(indx);
164  if (item) {
165  if ( !item->isAssignable() ) {
166  // For example: the case for size() and capacity() in SequenceTypeInfo
167  log(Warning)<<"propertyDecomposition: Item '"<< indx << "' of type "<< dsb->getTypeName() << " is not changeable."<<endlog();
168  continue;
169  }
170  // finally recurse or add it to the target bag:
171  PropertyBase* newpb = item->getTypeInfo()->buildProperty( "Element" + indx,"Sequence Element",item);
172  if ( !recurse || !propertyDecomposition( newpb, recurse_bag->value()) ) {
173  targetbag.ownProperty( newpb ); // leaf
174  } else {
175  delete newpb;
176  recurse_bag->setName( "Element" + indx );
177  // setType() is done by recursive of self.
178  targetbag.ownProperty( recurse_bag.release() ); //recursed.
179  recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Item") );
180  }
181  }
182  }
183  }
184  if (targetbag.empty() )
185  log(Debug) << "propertyDecomposition: "<< dsb->getTypeName() << " returns an empty property bag." << endlog();
186  return true;
187 }
188 
189 }}
DataSource is a base class representing a generic way to read data of type T.
Definition: DataSource.hpp:94
virtual result_t get() const =0
Return the data as type T.
void add(base::PropertyBase *p)
Add a valid property to the container.
Definition: PropertyBag.cpp:73
Base class for all properties.
void setType(const std::string &newtype)
STL namespace.
A container for holding references to properties.
Definition: PropertyBag.hpp:96
bool ownProperty(base::PropertyBase *p)
Set a property to be owned by this bag.
Definition: PropertyBag.cpp:83
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
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...
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
bool empty() const
Return true if no properties are present in this bag.
boost::intrusive_ptr< DataSource< T > > shared_ptr
Definition: DataSource.hpp:115
boost::intrusive_ptr< AssignableDataSource< T > > shared_ptr
Use this type to store a pointer to an AssignableDataSource.
Definition: DataSource.hpp:198
A DataSource which has set() methods.
Definition: DataSource.hpp:184
bool typeDecomposition(base::DataSourceBase::shared_ptr dsb, PropertyBag &targetbag, bool recurse)
Identical to RTT::types::propertyDecomposition(), but takes a DataSourceBase as source.
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.
virtual const types::TypeInfo * getTypeInfo() const =0
Returns the types::TypeInfo object of this Property.