Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00046 #include "PropertyDecomposition.hpp"
00047 #include "../internal/DataSource.hpp"
00048 #include <vector>
00049 #include <string>
00050 #include <memory>
00051 #include <boost/lexical_cast.hpp>
00052 #include "../Logger.hpp"
00053 #include "TypeInfo.hpp"
00054 #include "../Property.hpp"
00055
00056
00057 using namespace std;
00058 using namespace RTT;
00059 using namespace RTT::detail;
00060
00061 namespace RTT { namespace types {
00062
00063 bool propertyDecomposition( base::PropertyBase* source, PropertyBag& targetbag, bool recurse )
00064 {
00065 if (!source)
00066 return false;
00067 DataSourceBase::shared_ptr dsb = source->getDataSource();
00068 if (!dsb)
00069 return false;
00070 return typeDecomposition( dsb, targetbag, recurse);
00071 }
00072
00073 bool typeDecomposition( base::DataSourceBase::shared_ptr dsb, PropertyBag& targetbag, bool recurse)
00074 {
00075 if (!dsb)
00076 return false;
00077
00078
00079 DataSourceBase::shared_ptr decomposed = dsb->getTypeInfo()->decomposeType(dsb);
00080
00081 if (decomposed == dsb)
00082 return false;
00083 if (decomposed) {
00084
00085 internal::AssignableDataSource<PropertyBag>::shared_ptr bag = internal::AssignableDataSource<PropertyBag>::narrow( decomposed.get() );
00086 if ( bag ) {
00087
00088 targetbag = bag->rvalue();
00089 return true;
00090 } else {
00091
00092
00093 return false;
00094 }
00095 }
00096
00097 vector<string> parts = dsb->getMemberNames();
00098 if ( parts.empty() ) {
00099 log(Debug) << "propertyDecomposition: "<< dsb->getTypeName() << " does not have any members." << endlog();
00100 return false;
00101 }
00102
00103 targetbag.setType( dsb->getTypeName() );
00104
00105
00106 auto_ptr< Property<PropertyBag> > recurse_bag( new Property<PropertyBag>("recurse_bag","Part") );
00107
00108 for(vector<string>::iterator it = parts.begin(); it != parts.end(); ++it ) {
00109 DataSourceBase::shared_ptr part = dsb->getMember( *it );
00110 if (!part) {
00111 log(Error) <<"propertyDecomposition: Inconsistent type info for "<< dsb->getTypeName() << ": reported to have part '"<<*it<<"' but failed to return it."<<endlog();
00112 continue;
00113 }
00114 if ( !part->isAssignable() ) {
00115
00116 log(Debug)<<"propertyDecomposition: Part "<< *it << ":"<< part->getTypeName() << " is not changeable."<<endlog();
00117 continue;
00118 }
00119
00120 PropertyBase* newpb = part->getTypeInfo()->buildProperty(*it,"Part",part);
00121 if ( !newpb ) {
00122 log(Error)<< "Decomposition failed because Part '"<<*it<<"' is not known to type system."<<endlog();
00123 continue;
00124 }
00125 if ( !recurse )
00126 targetbag.ownProperty( newpb );
00127 else if ( !propertyDecomposition( newpb, recurse_bag->value(), true) ) {
00128
00129 assert( recurse_bag->rvalue().empty() );
00130 base::DataSourceBase::shared_ptr clone = newpb->getDataSource();
00131 base::DataSourceBase::shared_ptr converted = clone->getTypeInfo()->decomposeType(clone);
00132 if ( converted && converted != clone ) {
00133
00134 targetbag.add( converted->getTypeInfo()->buildProperty(*it, "", converted) );
00135 } else {
00136
00137 targetbag.add( newpb );
00138 }
00139 } else {
00140 assert( recurse_bag->rvalue().size() >= 1 );
00141 recurse_bag->setName(*it);
00142
00143 targetbag.ownProperty( recurse_bag.release() );
00144 recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Part") );
00145 delete newpb;
00146 }
00147 }
00148
00149
00150 recurse_bag->setDescription("Item");
00151
00152
00153 DataSource<int>::shared_ptr size = DataSource<int>::narrow( dsb->getMember("size").get() );
00154 if (size) {
00155 int msize = size->get();
00156 for (int i=0; i < msize; ++i) {
00157 string indx = boost::lexical_cast<string>( i );
00158 DataSourceBase::shared_ptr item = dsb->getMember(indx);
00159 if (item) {
00160 if ( !item->isAssignable() ) {
00161
00162 log(Warning)<<"propertyDecomposition: Item '"<< indx << "' of type "<< dsb->getTypeName() << " is not changeable."<<endlog();
00163 continue;
00164 }
00165
00166 PropertyBase* newpb = item->getTypeInfo()->buildProperty( "Element" + indx,"Sequence Element",item);
00167 if ( !recurse || !propertyDecomposition( newpb, recurse_bag->value()) ) {
00168 targetbag.ownProperty( newpb );
00169 } else {
00170 delete newpb;
00171 recurse_bag->setName( "Element" + indx );
00172
00173 targetbag.ownProperty( recurse_bag.release() );
00174 recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Item") );
00175 }
00176 }
00177 }
00178 }
00179 if (targetbag.empty() )
00180 log(Debug) << "propertyDecomposition: "<< dsb->getTypeName() << " returns an empty property bag." << endlog();
00181 return true;
00182 }
00183
00184 }}