PropertyComposition.cpp
Go to the documentation of this file.
00001 #include "PropertyComposition.hpp"
00002 #include "PropertyDecomposition.hpp"
00003 #include "../Logger.hpp"
00004 #include "../Property.hpp"
00005 #include "types/Types.hpp"
00006 
00007 using namespace RTT;
00008 using namespace RTT::detail;
00009 
00010 bool RTT::types::composePropertyBag( PropertyBag const& sourcebag, PropertyBag& target )
00011 {
00012     if ( !target.empty() ) {
00013         log(Error) <<"composePropertyBag: target bag must be empty."<< endlog();
00014         return false;
00015     }
00016     bool has_error = false;
00017     PropertyBag::const_iterator sit = sourcebag.begin();
00018     for( ; sit != sourcebag.end(); ++sit) {
00019         // test if it's a property bag, then we need to recurse:
00020         Property<PropertyBag> isbag;
00021         isbag = *sit; // separate assignment avoids error message !
00022         if ( isbag.ready() && isbag.value().getType() != "PropertyBag") {
00023             // typed property bag, need to compose it.
00024             TypeInfo* ti = Types()->type( isbag.value().getType() );
00025             if ( ti == 0) {
00026                 log(Error) <<"Could not compose unknown type '" << isbag.value().getType() <<"'." <<endlog();
00027                 has_error = true;
00028                 continue;
00029             }
00030             PropertyBase* tgtprop = ti->buildProperty(isbag.getName(), isbag.getDescription());
00031             if ( ti->composeType(isbag.getDataSource(), tgtprop->getDataSource()) ) {
00032                 log(Debug) << "Used user's composition function for " << tgtprop->getName() <<":"<<tgtprop->getType()<<endlog();
00033                 target.ownProperty(tgtprop);
00034             } else {
00035                 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();
00036                 delete tgtprop;
00037                 has_error = true;
00038                 continue;
00039             }
00040         } else {
00041             if ( isbag.ready() ) {
00042                 // plain property bag, clone and recurse:
00043                 Property<PropertyBag>* newbag = new Property<PropertyBag>(isbag.getName(), isbag.getDescription());
00044                 if ( composePropertyBag(isbag.value(), newbag->value()) == false) {
00045                     delete newbag;
00046                     has_error = true;
00047                     continue;
00048                 }
00049                 target.ownProperty( newbag );
00050             } else {
00051                 // plain property, not a bag:
00052                 target.ownProperty( (*sit)->clone() );
00053             }
00054         }
00055     }
00056 
00057     return !has_error;
00058 }
00059 
00060 bool RTT::types::decomposePropertyBag( PropertyBag const& sourcebag, PropertyBag&  target)
00061 {
00062     if ( !target.empty() ) {
00063         log(Error) <<"decomposePropertyBag: target bag must be empty."<< endlog();
00064         return false;
00065     }
00066     PropertyBag::const_iterator sit = sourcebag.begin();
00067     while( sit != sourcebag.end()) {
00068         // test if it's a property bag, then we need to recurse:
00069         Property<PropertyBag> isbag;
00070         isbag = *sit; // avoid logging error
00071         if ( isbag.ready() ) {
00072             // create an empty instance to recurse in:
00073             Property<PropertyBag>* newtarget = new Property<PropertyBag>(isbag.getName(), isbag.getDescription() );
00074             newtarget->value().setType( isbag.rvalue().getType() );
00075             target.ownProperty( newtarget );
00076             if ( decomposePropertyBag(isbag.value(), newtarget->value() ) == false) {
00077                 assert(false && "internal error in decomposePropertyBag."); // this is a best effort function.
00078             }
00079         } else {
00080             // decompose non-bag type:
00081             log(Debug) << "Checking for decompose "<< (*sit)->getName() <<endlog();
00082 
00083             // Try decomposeType() first because this is the user's implementation of decomposition:
00084             DataSourceBase::shared_ptr dsb = (*sit)->getTypeInfo()->decomposeType( (*sit)->getDataSource() );
00085             if ( dsb ) {
00086                 // check if type returned itself to avoid decomposition:
00087                 if ( dsb == (*sit)->getDataSource() ) {
00088                     // primitive type : clone the instance
00089                     target.ownProperty( (*sit)->clone() );
00090                 } else {
00091                     DataSource<PropertyBag>::shared_ptr bagds = DataSource<PropertyBag>::narrow(dsb.get());
00092                     if ( bagds ) {
00093                         // property bag ? -> further decompose
00094                         // create an empty instance to recurse in:
00095                         Property<PropertyBag>* newtarget = new Property<PropertyBag>((*sit)->getName(), (*sit)->getDescription() );
00096                         newtarget->value().setType( bagds->rvalue().getType() );
00097                         target.ownProperty( newtarget );
00098                         if ( decomposePropertyBag(bagds->rvalue(), newtarget->value() ) == false) {
00099                             assert(false && "internal error in decomposePropertyBag."); // this is a best effort function.
00100                         }
00101                     } else {
00102                         // other type ? -> add
00103                         base::PropertyBase* p = dsb->getTypeInfo()->buildProperty((*sit)->getName(), (*sit)->getDescription(), dsb);
00104                         if ( target.ownProperty( p ) == false)
00105                             log(Error) <<"Failed to create a property of decomposed data of type "<<(*sit)->getType() <<endlog();
00106                     }
00107                 }
00108             } else {
00109                 // if decomposeType() returned null, try generic decomposition, based on getMember():
00110                 Property<PropertyBag> res((*sit)->getName(), (*sit)->getDescription() );
00111                 // propertyDecomposition decomposes fully, so the result does not need to be recursed:
00112                 if ( types::propertyDecomposition(*sit, res.value() ) ) {
00113                     target.ownProperty( res.clone() );
00114                 }
00115             }
00116         }
00117         ++sit;
00118     }
00119     return true;
00120 }


rtt
Author(s): RTT Developers
autogenerated on Fri Sep 9 2016 04:01:56