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
00020 Property<PropertyBag> isbag;
00021 isbag = *sit;
00022 if ( isbag.ready() && isbag.value().getType() != "PropertyBag") {
00023
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 has_error = true;
00037 }
00038 } else {
00039 if ( isbag.ready() ) {
00040
00041 Property<PropertyBag>* newbag = new Property<PropertyBag>(isbag.getName(), isbag.getDescription());
00042 if ( composePropertyBag(isbag.value(), newbag->value()) == false) {
00043 delete newbag;
00044 has_error = true;
00045 }
00046 target.ownProperty( newbag );
00047 } else {
00048
00049 target.ownProperty( (*sit)->clone() );
00050 }
00051 }
00052 }
00053
00054 return !has_error;
00055 }
00056
00057 bool RTT::types::decomposePropertyBag( PropertyBag const& sourcebag, PropertyBag& target)
00058 {
00059 if ( !target.empty() ) {
00060 log(Error) <<"decomposePropertyBag: target bag must be empty."<< endlog();
00061 return false;
00062 }
00063 PropertyBag::const_iterator sit = sourcebag.begin();
00064 while( sit != sourcebag.end()) {
00065
00066 Property<PropertyBag> isbag;
00067 isbag = *sit;
00068 if ( isbag.ready() ) {
00069
00070 Property<PropertyBag>* newtarget = new Property<PropertyBag>(isbag.getName(), isbag.getDescription() );
00071 target.ownProperty( newtarget );
00072 if ( decomposePropertyBag(isbag.value(), newtarget->value() ) == false) {
00073 assert(false && "internal error in decomposePropertyBag.");
00074 }
00075 } else {
00076
00077 log(Debug) << "Checking for decompose "<< (*sit)->getName() <<endlog();
00078
00079
00080 DataSourceBase::shared_ptr dsb = (*sit)->getTypeInfo()->decomposeType( (*sit)->getDataSource() );
00081 if ( dsb ) {
00082
00083 if ( dsb == (*sit)->getDataSource() ) {
00084
00085 target.ownProperty( (*sit)->clone() );
00086 } else {
00087 DataSource<PropertyBag>::shared_ptr bagds = DataSource<PropertyBag>::narrow(dsb.get());
00088 if ( bagds ) {
00089
00090
00091 Property<PropertyBag>* newtarget = new Property<PropertyBag>((*sit)->getName(), (*sit)->getDescription() );
00092 target.ownProperty( newtarget );
00093 if ( decomposePropertyBag(bagds->rvalue(), newtarget->value() ) == false) {
00094 assert(false && "internal error in decomposePropertyBag.");
00095 }
00096 } else {
00097
00098 base::PropertyBase* p = dsb->getTypeInfo()->buildProperty((*sit)->getName(), (*sit)->getDescription(), dsb);
00099 if ( target.ownProperty( p ) == false)
00100 log(Error) <<"Failed to create a property of decomposed data of type "<<(*sit)->getType() <<endlog();
00101 }
00102 }
00103 } else {
00104
00105 Property<PropertyBag> res((*sit)->getName(), (*sit)->getDescription() );
00106
00107 if ( types::propertyDecomposition(*sit, res.value() ) ) {
00108 target.ownProperty( res.clone() );
00109 }
00110 }
00111 }
00112 ++sit;
00113 }
00114 return true;
00115 }