Orocos Real-Time Toolkit
2.5.0
|
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 target.ownProperty( newtarget ); 00075 if ( decomposePropertyBag(isbag.value(), newtarget->value() ) == false) { 00076 assert(false && "internal error in decomposePropertyBag."); // this is a best effort function. 00077 } 00078 } else { 00079 // decompose non-bag type: 00080 log(Debug) << "Checking for decompose "<< (*sit)->getName() <<endlog(); 00081 00082 // Try decomposeType() first because this is the user's implementation of decomposition: 00083 DataSourceBase::shared_ptr dsb = (*sit)->getTypeInfo()->decomposeType( (*sit)->getDataSource() ); 00084 if ( dsb ) { 00085 // check if type returned itself to avoid decomposition: 00086 if ( dsb == (*sit)->getDataSource() ) { 00087 // primitive type : clone the instance 00088 target.ownProperty( (*sit)->clone() ); 00089 } else { 00090 DataSource<PropertyBag>::shared_ptr bagds = DataSource<PropertyBag>::narrow(dsb.get()); 00091 if ( bagds ) { 00092 // property bag ? -> further decompose 00093 // create an empty instance to recurse in: 00094 Property<PropertyBag>* newtarget = new Property<PropertyBag>((*sit)->getName(), (*sit)->getDescription() ); 00095 target.ownProperty( newtarget ); 00096 if ( decomposePropertyBag(bagds->rvalue(), newtarget->value() ) == false) { 00097 assert(false && "internal error in decomposePropertyBag."); // this is a best effort function. 00098 } 00099 } else { 00100 // other type ? -> add 00101 base::PropertyBase* p = dsb->getTypeInfo()->buildProperty((*sit)->getName(), (*sit)->getDescription(), dsb); 00102 if ( target.ownProperty( p ) == false) 00103 log(Error) <<"Failed to create a property of decomposed data of type "<<(*sit)->getType() <<endlog(); 00104 } 00105 } 00106 } else { 00107 // if decomposeType() returned null, try generic decomposition, based on getMember(): 00108 Property<PropertyBag> res((*sit)->getName(), (*sit)->getDescription() ); 00109 // propertyDecomposition decomposes fully, so the result does not need to be recursed: 00110 if ( types::propertyDecomposition(*sit, res.value() ) ) { 00111 target.ownProperty( res.clone() ); 00112 } 00113 } 00114 } 00115 ++sit; 00116 } 00117 return true; 00118 }