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 #ifdef ORO_PRAGMA_INTERFACE
00039 #pragma implementation
00040 #endif
00041 #include "PropertyBag.hpp"
00042 #include "Property.hpp"
00043 #include "Logger.hpp"
00044
00045 namespace RTT
00046 {
00047
00048 PropertyBag::PropertyBag( )
00049 : mproperties(), type("PropertyBag")
00050 {}
00051
00052 PropertyBag::PropertyBag( const std::string& _type)
00053 : mproperties(), type(_type)
00054 {}
00055
00056 PropertyBag::PropertyBag( const PropertyBag& orig)
00057 : mproperties( orig.getProperties() ), type( orig.getType() )
00058 {
00059 }
00060
00061 void PropertyBag::add(PropertyBase *p)
00062 {
00063 this->addProperty(p);
00064 }
00065
00066 void PropertyBag::remove(PropertyBase *p)
00067 {
00068 this->removeProperty(p);
00069 }
00070
00071 bool PropertyBag::addProperty(PropertyBase *p)
00072 {
00073 if ( ! p->ready() )
00074 return false;
00075 mproperties.push_back(p);
00076 return true;
00077 }
00078
00079 bool PropertyBag::removeProperty(PropertyBase *p)
00080 {
00081 iterator i = mproperties.begin();
00082 i = mproperties.end();
00083 i = std::find(mproperties.begin(), mproperties.end(), p);
00084 if ( i != mproperties.end() ) {
00085 mproperties.erase(i);
00086 return true;
00087 }
00088 return false;
00089 }
00090
00091 void PropertyBag::clear()
00092 {
00093 mproperties.clear();
00094 }
00095
00096 void PropertyBag::list(std::vector<std::string> &names) const
00097 {
00098 for (
00099 const_iterator i = mproperties.begin();
00100 i != mproperties.end();
00101 i++ )
00102 {
00103 names.push_back( (*i)->getName() );
00104 }
00105 }
00106
00107 std::vector<std::string> PropertyBag::list() const
00108 {
00109 std::vector<std::string> names;
00110 for (
00111 const_iterator i = mproperties.begin();
00112 i != mproperties.end();
00113 i++ )
00114 {
00115 names.push_back( (*i)->getName() );
00116 }
00117 return names;
00118 }
00119
00120 void PropertyBag::identify( PropertyIntrospection* pi ) const
00121 {
00122 for ( const_iterator i = mproperties.begin();
00123 i != mproperties.end();
00124 i++ )
00125 {
00126 (*i)->identify(pi);
00127 }
00128 }
00129
00130 void PropertyBag::identify( PropertyBagVisitor* pi ) const
00131 {
00132 for ( const_iterator i = mproperties.begin();
00133 i != mproperties.end();
00134 i++ )
00135 {
00136 (*i)->identify(pi);
00137 }
00138 }
00139
00140 PropertyBase* PropertyBag::find(const std::string& name) const
00141 {
00142 const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(PropertyBag::FindProp(), name ) ) );
00143 if ( i != mproperties.end() )
00144 return ( *i );
00145 return 0;
00146 }
00147
00148 PropertyBag& PropertyBag::operator=(const PropertyBag& orig)
00149 {
00150 mproperties.clear();
00151
00152 const_iterator i = orig.getProperties().begin();
00153 while (i != orig.getProperties().end() )
00154 {
00155 add( (*i) );
00156 ++i;
00157 }
00158 this->setType( orig.getType() );
00159 return *this;
00160 }
00161
00162 PropertyBag& PropertyBag::operator<<=(const PropertyBag& source)
00163 {
00164
00165 const_iterator it(source.getProperties().begin());
00166 while ( it != source.getProperties().end() )
00167 {
00168 PropertyBase* mine = find( (*it)->getName() );
00169 if (mine != 0)
00170 remove(mine);
00171 add( (*it) );
00172 ++it;
00173 }
00174 this->setType( source.getType() );
00175 return *this;
00176 }
00177
00178 PropertyBase* findProperty(const PropertyBag& bag, const std::string& nameSequence, const std::string& separator)
00179 {
00180 PropertyBase* result;
00181 Property<PropertyBag>* result_bag;
00182 std::string token;
00183 std::string::size_type start = 0;
00184 if ( separator.length() != 0 && nameSequence.find(separator) == 0 )
00185 start = separator.length();
00186 std::string::size_type len = nameSequence.find(separator, start);
00187 if (len != std::string::npos) {
00188 token = nameSequence.substr(start,len-start);
00189 start = len + separator.length();
00190 if ( start >= nameSequence.length() )
00191 start = std::string::npos;
00192 }
00193 else {
00194 token = nameSequence.substr(start);
00195 start = std::string::npos;
00196 }
00197 result = bag.find(token);
00198 if (result != 0 )
00199 {
00200 result_bag = dynamic_cast<Property<PropertyBag>*>(result);
00201 if ( result_bag != 0 && start != std::string::npos ) {
00202 return findProperty( result_bag->rvalue(), nameSequence.substr( start ), separator );
00203 }
00204 else
00205 return result;
00206 }
00207 return 0;
00208 }
00209
00210 bool refreshProperties(const PropertyBag& target, const PropertyBag& source, bool allprops)
00211 {
00212 Logger::In in("refreshProperties");
00213
00214 PropertyBag::const_iterator it( target.getProperties().begin() );
00215 bool failure = false;
00216 while ( it != target.getProperties().end() )
00217 {
00218 PropertyBase* srcprop;
00219 if ( (*it)->getName() == "" )
00220 srcprop = source.getItem( it - target.getProperties().begin() );
00221 else
00222 srcprop = source.find( (*it)->getName() );
00223 PropertyBase* tgtprop = *it;
00224 if (srcprop != 0)
00225 {
00226
00227 if ( tgtprop->refresh( srcprop ) == false ) {
00228
00229 if ( tgtprop->getTypeInfo()->composeType( srcprop->getDataSource(), tgtprop->getDataSource() ) == false ) {
00230 log(Error) << "Could not update, nor compose Property "
00231 << tgtprop->getType() << " "<< srcprop->getName()
00232 << ": type mismatch, can not refresh with type "
00233 << srcprop->getType() << endlog();
00234 failure = true;
00235 } else {
00236 log(Debug) << "Composed Property "
00237 << tgtprop->getType() << " "<< srcprop->getName()
00238 << " from type " << srcprop->getType() << endlog();
00239 }
00240 }
00241
00242 } else if (allprops) {
00243 log(Error) << "Could not find Property "
00244 << tgtprop->getType() << " "<< tgtprop->getName()
00245 << " in source."<< endlog();
00246 failure = true;
00247 }
00248 ++it;
00249 }
00250 return !failure;
00251 }
00252
00253 bool refreshProperty(const PropertyBag& target, const PropertyBase& source)
00254 {
00255 PropertyBase* target_prop;
00256
00257 if ( 0 != (target_prop = target.find( source.getName() ) ) )
00258 {
00259 return target_prop->refresh( &source );
00260 }
00261 return false;
00262 }
00263
00264 bool copyProperties(PropertyBag& target, const PropertyBag& source)
00265 {
00266
00267
00268 PropertyBag::const_iterator it( source.getProperties().begin() );
00269 while ( it != source.getProperties().end() )
00270 {
00271
00272 PropertyBase* temp = (*it)->create();
00273
00274 temp->copy( *it );
00275
00276 target.add( temp );
00277 ++it;
00278 }
00279 return true;
00280 }
00281
00282 bool updateProperties(PropertyBag& target, const PropertyBag& source)
00283 {
00284
00285 if ( target.getType() == "" || target.getType() == "type_less" )
00286 target.setType("PropertyBag");
00287
00288
00289 if ( target.getType() != "PropertyBag" && target.getType() != source.getType() ) {
00290 log(Debug) << "Rebuilding typed PropertyBag."<<endlog();
00291 deletePropertyBag(target);
00292 }
00293
00294 target.setType( source.getType() );
00295
00296
00297
00298 PropertyBag::const_iterator it( source.getProperties().begin() );
00299 while ( it != source.getProperties().end() )
00300 {
00301 PropertyBase* mine;
00302
00303 if ( (*it)->getName() == "" )
00304 mine = target.getItem( it - source.getProperties().begin() );
00305 else
00306 mine = target.find( (*it)->getName() );
00307 if (mine != 0) {
00308 #ifndef NDEBUG
00309 Logger::log() << Logger::Debug;
00310 Logger::log() << "updateProperties: updating Property "
00311 << (*it)->getType() << " "<< (*it)->getName()
00312 << "." << Logger::endl;
00313 #endif
00314
00315 if ( mine->update( (*it) ) == false ) {
00316
00317 if ( mine->getTypeInfo()->composeType( (*it)->getDataSource(), mine->getDataSource() ) == false ) {
00318 Logger::log() << Logger::Error;
00319 Logger::log() << "updateProperties: Could not update, nor compose Property "
00320 << mine->getType() << " "<< (*it)->getName()
00321 << ": type mismatch, can not update with type "
00322 << (*it)->getType() << Logger::endl;
00323 return false;
00324 }
00325 }
00326
00327 }
00328 else
00329 {
00330 #ifndef NDEBUG
00331 Logger::log() << Logger::Debug;
00332 Logger::log() << "updateProperties: created Property "
00333 << (*it)->getType() << " "<< (*it)->getName()
00334 << "." << Logger::endl;
00335 #endif
00336
00337 PropertyBase* temp = (*it)->create();
00338
00339 temp->update( (*it) );
00340
00341 target.add( temp );
00342 }
00343 ++it;
00344 }
00345 return true;
00346 }
00347
00348 bool updateProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator)
00349 {
00350 Logger::In in("updateProperty");
00351
00352 PropertyBase* source_walker;
00353 PropertyBase* target_walker;
00354 std::string token;
00355 std::string::size_type start = 0;
00356 if ( separator.length() != 0 && name.find(separator) == 0 )
00357 start = separator.length();
00358 std::string::size_type len = name.find(separator, start);
00359 if (len != std::string::npos) {
00360 token = name.substr(start,len-start);
00361 start = len + separator.length();
00362 if ( start >= name.length() )
00363 start = std::string::npos;
00364 }
00365 else {
00366 token = name.substr(start);
00367 start = std::string::npos;
00368 }
00369 source_walker = source.find(token);
00370 target_walker = target.find(token);
00371 if (source_walker != 0 )
00372 {
00373 if ( target_walker == 0 ) {
00374
00375 target_walker = source_walker->create();
00376 target.addProperty( target_walker );
00377 }
00378 Property<PropertyBag>* source_walker_bag;
00379 Property<PropertyBag>* target_walker_bag;
00380 source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker);
00381 target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker);
00382 if ( source_walker_bag != 0 && start != std::string::npos ) {
00383 if ( target_walker_bag == 0 ) {
00384 log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog();
00385 return false;
00386 }
00387 return updateProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );
00388 }
00389 else {
00390
00391 if (target_walker->update(source_walker) == false ) {
00392
00393 if ( target_walker->getTypeInfo()->composeType( source_walker->getDataSource(), target_walker->getDataSource() ) == false ) {
00394 log(Error) << "Could not update nor compose Property "
00395 << target_walker->getType() << " "<< target_walker->getName()
00396 << ": type mismatch, can not update with type "
00397 << source_walker->getType() << Logger::endl;
00398 }
00399 }
00400 log(Debug) << "Found Property '"<<target_walker->getName() <<"': update done." << endlog();
00401 return true;
00402 }
00403 } else {
00404
00405 log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
00406 return false;
00407 }
00408
00409 return false;
00410 }
00411
00412 bool refreshProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator)
00413 {
00414 Logger::In in("refreshProperty");
00415
00416 PropertyBase* source_walker;
00417 PropertyBase* target_walker;
00418 std::string token;
00419 std::string::size_type start = 0;
00420 if ( separator.length() != 0 && name.find(separator) == 0 )
00421 start = separator.length();
00422 std::string::size_type len = name.find(separator, start);
00423 if (len != std::string::npos) {
00424 token = name.substr(start,len-start);
00425 start = len + separator.length();
00426 if ( start >= name.length() )
00427 start = std::string::npos;
00428 }
00429 else {
00430 token = name.substr(start);
00431 start = std::string::npos;
00432 }
00433 source_walker = source.find(token);
00434 target_walker = target.find(token);
00435 if (source_walker != 0 )
00436 {
00437 if ( target_walker == 0 ) {
00438 log(Error) << "Property '"<<source_walker->getName()<<"' was not found in target !"<<endlog();
00439 return false;
00440 }
00441 Property<PropertyBag>* source_walker_bag;
00442 Property<PropertyBag>* target_walker_bag;
00443 source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker);
00444 target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker);
00445 if ( source_walker_bag != 0 && start != std::string::npos ) {
00446 if ( target_walker_bag == 0 ) {
00447 log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog();
00448 return false;
00449 }
00450 return refreshProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );
00451 }
00452 else {
00453
00454 if (target_walker->refresh(source_walker) == false ) {
00455
00456 if ( target_walker->getTypeInfo()->composeType( source_walker->getDataSource(), target_walker->getDataSource() ) == false ) {
00457 log(Error) << "Could not refresh nor compose Property "
00458 << target_walker->getType() << " "<< target_walker->getName()
00459 << ": type mismatch, can not refresh with type "
00460 << source_walker->getType() << Logger::endl;
00461 }
00462 }
00463 log(Debug) << "Found Property '"<<target_walker->getName() <<"': refresh done." << endlog();
00464 return true;
00465 }
00466 } else {
00467
00468 log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
00469 return false;
00470 }
00471
00472 return false;
00473 }
00474
00475 void deleteProperties(PropertyBag& target)
00476 {
00477
00478 PropertyBag::const_iterator it( target.getProperties().begin() );
00479 while ( it != target.getProperties().end() )
00480 {
00481 delete (*it);
00482 ++it;
00483 }
00484 target.clear();
00485 }
00486
00487 void deletePropertyBag(PropertyBag& target)
00488 {
00489
00490 PropertyBag::const_iterator it( target.getProperties().begin() );
00491 while ( it != target.getProperties().end() )
00492 {
00493 Property<PropertyBag>* result = dynamic_cast< Property<PropertyBag>* >( *it );
00494 if ( result != 0 )
00495 deletePropertyBag( result->value() );
00496 delete (*it);
00497 ++it;
00498 }
00499 target.clear();
00500 }
00501
00502 void flattenPropertyBag(PropertyBag& target, const std::string& separator)
00503 {
00504
00505 Property<PropertyBag>* result;
00506 PropertyBag::const_iterator it( target.getProperties().begin() );
00507 while ( it != target.getProperties().end() )
00508 {
00509 result = dynamic_cast< Property<PropertyBag>* >( *it );
00510 if ( result != 0 )
00511 {
00512 flattenPropertyBag( result->value(), separator );
00513
00514 PropertyBag::const_iterator flat_it( result->value().getProperties().begin() ) ;
00515 if ( flat_it != result->value().getProperties().end() )
00516 {
00517 while (flat_it != result->value().getProperties().end() )
00518 {
00519 (*flat_it)->setName( result->getName() + separator + (*flat_it)->getName() );
00520 target.add( *flat_it );
00521 result->value().remove( *flat_it );
00522 flat_it = result->value().getProperties().begin();
00523 }
00524 it = target.getProperties().begin();
00525 continue;
00526 }
00527
00528 }
00529 ++it;
00530 }
00531 }
00532
00533 }