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 "types/PropertyDecomposition.hpp"
00044 #include "types/Types.hpp"
00045 #include "Logger.hpp"
00046 #include <algorithm>
00047 #include "rtt-fwd.hpp"
00048
00049 namespace RTT
00050 {
00051 using namespace detail;
00052 using namespace std;
00053
00054 PropertyBag::PropertyBag( )
00055 : mproperties(), type("PropertyBag")
00056 {}
00057
00058 PropertyBag::PropertyBag( const std::string& _type)
00059 : mproperties(), type(_type)
00060 {}
00061
00062 PropertyBag::PropertyBag( const PropertyBag& orig)
00063 : mproperties()
00064 {
00065 *this = orig;
00066 }
00067
00068 PropertyBag::~PropertyBag()
00069 {
00070 this->clear();
00071 }
00072
00073 void PropertyBag::add(PropertyBase *p)
00074 {
00075 this->addProperty(*p);
00076 }
00077
00078 void PropertyBag::remove(PropertyBase *p)
00079 {
00080 this->removeProperty(p);
00081 }
00082
00083 bool PropertyBag::ownProperty(PropertyBase* p)
00084 {
00085 if (p == 0)
00086 return false;
00087 if ( ! p->ready() )
00088 return false;
00089 removeProperty(p);
00090 mproperties.push_back(p);
00091 mowned_props.push_back(p);
00092 return true;
00093 }
00094
00095 bool PropertyBag::ownsProperty(PropertyBase* p) const
00096 {
00097 if (p == 0)
00098 return false;
00099 const_iterator i = std::find(mowned_props.begin(), mowned_props.end(), p);
00100 if ( i != mowned_props.end() )
00101 return true;
00102 return false;
00103 }
00104
00105 bool PropertyBag::addProperty(PropertyBase& p)
00106 {
00107 if (&p == 0)
00108 return false;
00109 if ( ! p.ready() )
00110 return false;
00111 mproperties.push_back(&p);
00112 return true;
00113 }
00114
00115 bool PropertyBag::removeProperty(PropertyBase *p)
00116 {
00117 if (p == 0)
00118 return false;
00119 iterator i = std::find(mproperties.begin(), mproperties.end(), p);
00120 if ( i != mproperties.end() ) {
00121 mproperties.erase(i);
00122 i = std::find(mowned_props.begin(), mowned_props.end(), p);
00123 if ( i != mowned_props.end() ) {
00124 delete *i;
00125 mowned_props.erase(i);
00126 }
00127 return true;
00128 }
00129 return false;
00130 }
00131
00132 void PropertyBag::clear()
00133 {
00134 mproperties.clear();
00135 for ( iterator i = mowned_props.begin();
00136 i != mowned_props.end();
00137 i++ )
00138 {
00139 delete *i;
00140 }
00141 mowned_props.clear();
00142 }
00143
00144 void PropertyBag::list(std::vector<std::string> &names) const
00145 {
00146 for ( const_iterator i = mproperties.begin();
00147 i != mproperties.end();
00148 i++ )
00149 {
00150 names.push_back( (*i)->getName() );
00151 }
00152 }
00153
00154 std::vector<std::string> PropertyBag::list() const
00155 {
00156 std::vector<std::string> names;
00157 for ( const_iterator i = mproperties.begin();
00158 i != mproperties.end();
00159 i++ )
00160 {
00161 names.push_back( (*i)->getName() );
00162 }
00163 return names;
00164 }
00165
00166 PropertyBag::Properties PropertyBag::getProperties(const std::string& name) const
00167 {
00168 Properties names;
00169 for ( const_iterator i = mproperties.begin();
00170 i != mproperties.end();
00171 i++ )
00172 {
00173 if ( (*i)->getName() == name )
00174 names.push_back( (*i) );
00175 }
00176 return names;
00177 }
00178
00179
00180 void PropertyBag::identify( PropertyIntrospection* pi ) const
00181 {
00182 for ( const_iterator i = mproperties.begin();
00183 i != mproperties.end();
00184 i++ )
00185 {
00186 (*i)->identify(pi);
00187 }
00188 }
00189
00190 void PropertyBag::identify( PropertyBagVisitor* pi ) const
00191 {
00192 for ( const_iterator i = mproperties.begin();
00193 i != mproperties.end();
00194 i++ )
00195 {
00196 (*i)->identify(pi);
00197 }
00198 }
00199
00204 struct FindProp : public std::binary_function<const base::PropertyBase*,const std::string, bool>
00205 {
00206 bool operator()(const base::PropertyBase* b1, const std::string& b2) const { return b1->getName() == b2; }
00207 };
00210 PropertyBase* PropertyBag::find(const std::string& name) const
00211 {
00212 const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(FindProp(), name ) ) );
00213 if ( i != mproperties.end() )
00214 return ( *i );
00215 return 0;
00216 }
00217
00218 base::PropertyBase* PropertyBag::getProperty(const std::string& name) const
00219 {
00220 const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(FindProp(), name ) ) );
00221 if ( i != mproperties.end() )
00222 return *i;
00223 return 0;
00224 }
00225
00226
00227 PropertyBag& PropertyBag::operator=(const PropertyBag& orig)
00228 {
00229 if(this == &orig)
00230 return *this;
00231
00232 this->clear();
00233
00234 for( const_iterator i = orig.mproperties.begin(); i != orig.mproperties.end(); ++i) {
00235 if ( orig.ownsProperty( *i ) ) {
00236 PropertyBase* copy = (*i)->copy();
00237 this->ownProperty( copy );
00238 } else {
00239 this->add( *i );
00240 }
00241 }
00242
00243 this->setType( orig.getType() );
00244 return *this;
00245 }
00246
00247 PropertyBag& PropertyBag::operator<<=(const PropertyBag& source)
00248 {
00249
00250 const_iterator it(source.getProperties().begin());
00251 while ( it != source.getProperties().end() )
00252 {
00253 PropertyBase* mine = find( (*it)->getName() );
00254 if (mine != 0)
00255 remove(mine);
00256 add( (*it) );
00257 ++it;
00258 }
00259 this->setType( source.getType() );
00260 return *this;
00261 }
00262
00263 template<>
00264 bool Property<PropertyBag>::update( const Property<PropertyBag>& orig)
00265 {
00266 if ( !ready() )
00267 return false;
00268 if ( _description.empty() )
00269 _description = orig.getDescription();
00270 return updateProperties( this->_value->set(), orig.rvalue() );
00271 }
00272
00273 template<>
00274 bool Property<PropertyBag>::refresh( const Property<PropertyBag>& orig)
00275 {
00276 if ( !ready() )
00277 return false;
00278 return refreshProperties( this->_value->set(), orig.rvalue() );
00279 }
00280
00281 template<>
00282 bool Property<PropertyBag>::copy( const Property<PropertyBag>& orig)
00283 {
00284 if ( !ready() )
00285 return false;
00286 _name = orig.getName();
00287 _description = orig.getDescription();
00288 return copyProperties( this->_value->set(), orig.rvalue() );
00289 }
00290
00291 std::ostream& operator<<(std::ostream& os, const PropertyBag& bag) {
00292 int size = bag.size();
00293 os << "[[";
00294 for(int i=0; i != size; ++i) {
00295 os << bag.getItem(i)->getName() << "='"<< bag.getItem(i) <<"'"<<endl;
00296 }
00297 os << "]]";
00298
00299 return os;
00300 }
00301
00302 std::istream& operator>>(std::istream& is, PropertyBag& bag) { return is; }
00303
00304
00305 PropertyBase* findProperty(const PropertyBag& bag, const std::string& nameSequence, const std::string& separator)
00306 {
00307 PropertyBase* result;
00308 Property<PropertyBag>* result_bag;
00309 std::string token;
00310 std::string::size_type start = 0;
00311 if ( separator.length() != 0 && nameSequence.find(separator) == 0 )
00312 start = separator.length();
00313 std::string::size_type len = nameSequence.find(separator, start);
00314 if (len != std::string::npos) {
00315 token = nameSequence.substr(start,len-start);
00316 start = len + separator.length();
00317 if ( start >= nameSequence.length() )
00318 start = std::string::npos;
00319 }
00320 else {
00321 token = nameSequence.substr(start);
00322 start = std::string::npos;
00323 }
00324 result = bag.find(token);
00325 if (result != 0 )
00326 {
00327 result_bag = dynamic_cast<Property<PropertyBag>*>(result);
00328 if ( result_bag != 0 && start != std::string::npos ) {
00329 return findProperty( result_bag->rvalue(), nameSequence.substr( start ), separator );
00330 }
00331 else
00332 return result;
00333 }
00334 return 0;
00335 }
00336
00340 void listPropertiesHelper(const PropertyBag& source, const std::string& separator, const string& prefix, vector<string>& result)
00341 {
00342 PropertyBag::const_iterator it( source.getProperties().begin() );
00343 while ( it != source.getProperties().end() ) {
00344 Property<PropertyBag>* sub = dynamic_cast<Property<PropertyBag>*>(*it);
00345 string itemname = prefix.empty() ? (*it)->getName() : prefix + separator + (*it)->getName();
00346 result.push_back( itemname );
00347 if ( sub && sub->ready() ) {
00348 listPropertiesHelper( sub->value(), separator, itemname, result );
00349 }
00350 ++it;
00351 }
00352 }
00353
00356 void listDescriptionsHelper(const PropertyBag& source, const std::string& separator, vector<string>& result)
00357 {
00358 PropertyBag::const_iterator it( source.getProperties().begin() );
00359 while ( it != source.getProperties().end() ) {
00360 Property<PropertyBag>* sub = dynamic_cast<Property<PropertyBag>*>(*it);
00361 result.push_back( (*it)->getDescription() );
00362 if ( sub && sub->ready() ) {
00363 listDescriptionsHelper( sub->value(), separator, result );
00364 }
00365 ++it;
00366 }
00367 }
00370 vector<string> listProperties(const PropertyBag& source, const std::string& separator)
00371 {
00372 vector<string> result;
00373 listPropertiesHelper( source, separator, "", result);
00374 return result;
00375 }
00376
00377 vector<string> listPropertyDescriptions(const PropertyBag& source, const std::string& separator)
00378 {
00379 vector<string> result;
00380 listDescriptionsHelper( source, separator, result);
00381 return result;
00382 }
00383
00384 bool storeProperty(PropertyBag& bag, const std::string& path, base::PropertyBase* item, const std::string& separator )
00385 {
00386 Logger::In in("storeProperty");
00387 if ( path.empty() || path == separator )
00388 return bag.ownProperty( item );
00389
00390 string pname, rest;
00391 if ( path.find(separator) != string::npos ) {
00392 pname = path.substr( 0, path.find(separator));
00393 rest = path.substr( path.find(separator) + separator.length() );
00394 } else {
00395 pname = path;
00396 }
00397
00398 if ( pname.empty() && !rest.empty() )
00399 return storeProperty( bag, rest, item, separator);
00400
00401
00402 PropertyBase* parent = bag.find(pname);
00403 if (!parent) {
00404 bag.ownProperty( new Property<PropertyBag>(pname,"") );
00405 parent = bag.find(pname);
00406 }
00407 Property<PropertyBag>* parentbag = dynamic_cast<Property<PropertyBag>* >(parent);
00408 if ( !parentbag ) {
00409 log(Error) << "Path component '" << pname << "' in path '"<<path<<"' does not point to a PropertyBag."<<endlog();
00410 return false;
00411 }
00412
00413 return storeProperty( parentbag->value(), rest, item, separator);
00414 }
00415
00416 bool removeProperty(PropertyBag& bag, const std::string& path, const std::string& separator )
00417 {
00418
00419 if ( path.empty() || path == separator )
00420 return false;
00421
00422 if ( path.find( separator ) == string::npos)
00423 return bag.removeProperty( bag.find(path) );
00424
00425 string prefix = path.substr( 0, path.rfind(separator));
00426 string pname = path.substr( path.rfind(separator) + separator.length() );
00427
00428 if ( prefix.empty() )
00429 return bag.removeProperty( bag.find(pname) );
00430
00431 Property<PropertyBag> parent = findProperty( bag, prefix);
00432 if ( !parent.ready() )
00433 return false;
00434 return parent.value().removeProperty( parent.value().find( pname ) );
00435 }
00436
00437 bool updateOrRefreshProperty( PropertyBase* source, PropertyBase* target, bool update)
00438 {
00439 #ifndef NDEBUG
00440 if (update)
00441 log(Debug) << "updateProperties: updating Property "
00442 << source->getType() << " "<< source->getName()
00443 << "." << endlog();
00444 else
00445 log(Debug) << "refreshProperties: refreshing Property "
00446 << source->getType() << " "<< source->getName()
00447 << "." << endlog();
00448 #endif
00449
00450 if ( (update && target->update( source ) == false ) || (!update && target->refresh( source ) == false ) ) {
00451
00452 DataSourceBase::shared_ptr converted = target->getTypeInfo()->convert( source->getDataSource() );
00453 if ( !converted || converted == source->getDataSource() ) {
00454
00455 converted = target->getDataSource();
00456 if (target->getTypeInfo()->composeType( source->getDataSource(), converted ) ) {
00457
00458 log(Debug) << "Composed Property "
00459 << target->getType() << " "<< source->getName() << " to type " <<target->getType()
00460 << " from type " << source->getType() << endlog();
00461 return true;
00462 } else {
00463
00464 log(Error) << (update ? "updateProperties: " : "refreshProperties: ") << " Could not update, nor convert Property "
00465 << target->getType() << " "<< target->getName()
00466 << ": type mismatch, can not update with "
00467 << source->getType() << " "<< source->getName() << endlog();
00468 return false;
00469 }
00470 } else {
00471
00472
00473
00474 PropertyBase* dummy = target->getTypeInfo()->buildProperty("","");
00475 dummy->getDataSource()->update( converted.get() );
00476 assert(dummy->getTypeInfo() == converted->getTypeInfo() );
00477
00478 if (update)
00479 target->update(dummy);
00480 else
00481 target->refresh(dummy);
00482 log(Debug) << "Converted Property "
00483 << target->getType() << " "<< source->getName() << " to type " <<dummy->getType()
00484 << " from type " << source->getType() << endlog();
00485 }
00486 }
00487 return true;
00488 }
00489
00490 bool refreshProperties(const PropertyBag& target, const PropertyBag& source, bool allprops)
00491 {
00492 Logger::In in("refreshProperties");
00493
00494
00495 if ( Types()->type(target.getType()) != Types()->getTypeInfo<PropertyBag>() && Types()->type( target.getType() ) != Types()->type( source.getType() ) ) {
00496 log(Error) << "Can not populate typed PropertyBag '"<< target.getType() <<"' from '"<<source.getType()<<"' (source and target type differed)."<<endlog();
00497 return false;
00498 }
00499
00500
00501 PropertyBag::const_iterator it( target.getProperties().begin() );
00502 bool failure = false;
00503 while ( it != target.getProperties().end() )
00504 {
00505 PropertyBase* srcprop;
00506 if ( (*it)->getName() == "" )
00507 srcprop = source.getItem( it - target.getProperties().begin() );
00508 else
00509 srcprop = source.find( (*it)->getName() );
00510 PropertyBase* tgtprop = *it;
00511 if (srcprop != 0)
00512 {
00513 if (updateOrRefreshProperty( srcprop, tgtprop, false) == false)
00514 return false;
00515
00516 } else if (allprops) {
00517 log(Error) << "Could not find Property "
00518 << tgtprop->getType() << " "<< tgtprop->getName()
00519 << " in source."<< endlog();
00520 failure = true;
00521 }
00522 ++it;
00523 }
00524 return !failure;
00525 }
00526
00527 bool refreshProperty(const PropertyBag& target, const PropertyBase& source)
00528 {
00529 PropertyBase* target_prop;
00530
00531 if ( 0 != (target_prop = target.find( source.getName() ) ) )
00532 {
00533 return target_prop->refresh( &source );
00534 }
00535 return false;
00536 }
00537
00538 bool copyProperties(PropertyBag& target, const PropertyBag& source)
00539 {
00540
00541
00542 PropertyBag::const_iterator it( source.getProperties().begin() );
00543 while ( it != source.getProperties().end() )
00544 {
00545
00546 PropertyBase* temp = (*it)->create();
00547
00548 temp->copy( *it );
00549
00550 target.ownProperty( temp );
00551 ++it;
00552 }
00553 return true;
00554 }
00555
00556
00557 bool updateProperties(PropertyBag& target, const PropertyBag& source)
00558 {
00559
00560 if ( target.getType() == "" || target.getType() == "type_less" )
00561 target.setType("PropertyBag");
00562
00563
00564 if ( Types()->type( target.getType() ) != Types()->getTypeInfo<PropertyBag>() && Types()->type(target.getType()) != Types()->type(source.getType()) ) {
00565 log(Error) << "Can not populate typed PropertyBag '"<< target.getType() <<"' from '"<<source.getType()<<"' (source and target type differed)."<<endlog();
00566 return false;
00567 }
00568
00569 target.setType( source.getType() );
00570
00571
00572
00573
00574 PropertyBag::Names allnames = source.list();
00575 PropertyBag::Names::const_iterator endnames = std::unique(allnames.begin(), allnames.end());
00576 PropertyBag::Names::const_iterator it( allnames.begin() );
00577 while ( it != endnames )
00578 {
00579 PropertyBag::Properties sources = source.getProperties(*it);
00580 PropertyBag::Properties mines = target.getProperties(*it);
00581 PropertyBag::iterator mit = mines.begin();
00582 for( PropertyBag::const_iterator sit = sources.begin(); sit != sources.end(); ++sit ) {
00583 if ( mit != mines.end() ) {
00584 assert( (*sit)->getName() == (*mit)->getName());
00585 if ( updateOrRefreshProperty( *sit, *mit, true) == false)
00586 return false;
00587
00588 ++mit;
00589 }
00590 else
00591 {
00592 #ifndef NDEBUG
00593 Logger::log() << Logger::Debug;
00594 Logger::log() << "updateProperties: creating Property "
00595 << (*sit)->getType() << " "<< (*sit)->getName()
00596 << "." << Logger::endl;
00597 #endif
00598
00599 PropertyBase* temp = 0;
00600 #if 0
00601 Property<PropertyBag>* tester = dynamic_cast<Property<PropertyBag>* >(*sit);
00602 if (tester && Types()->type( tester->value().getType() ) != Types()->getTypeInfo<PropertyBag>()) {
00603 if (TypeInfo* ti = types::Types()->type(tester->value().getType())) {
00604 temp = ti->buildProperty( tester->getName(), tester->getDescription() );
00605 assert(temp);
00606 bool res = temp->getTypeInfo()->composeType( tester->getDataSource(), temp->getDataSource() );
00607 if (!res ) return false;
00608 }
00609 }
00610 #endif
00611 if (!temp) {
00612
00613 temp = (*sit)->create();
00614
00615 temp->update( (*sit) );
00616 }
00617
00618 target.add( temp );
00619 }
00620 }
00621 ++it;
00622 }
00623 return true;
00624 }
00625
00626 bool updateProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator)
00627 {
00628 Logger::In in("updateProperty");
00629
00630 PropertyBase* source_walker;
00631 PropertyBase* target_walker;
00632 std::string token;
00633 std::string::size_type start = 0;
00634 if ( separator.length() != 0 && name.find(separator) == 0 )
00635 start = separator.length();
00636 std::string::size_type len = name.find(separator, start);
00637 if (len != std::string::npos) {
00638 token = name.substr(start,len-start);
00639 start = len + separator.length();
00640 if ( start >= name.length() )
00641 start = std::string::npos;
00642 }
00643 else {
00644 token = name.substr(start);
00645 start = std::string::npos;
00646 }
00647 source_walker = source.find(token);
00648 target_walker = target.find(token);
00649 if (source_walker != 0 )
00650 {
00651 if ( target_walker == 0 ) {
00652
00653 target_walker = source_walker->create();
00654 target.ownProperty( target_walker );
00655 }
00656 Property<PropertyBag>* source_walker_bag;
00657 Property<PropertyBag>* target_walker_bag;
00658 source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker);
00659 target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker);
00660 if ( source_walker_bag != 0 && start != std::string::npos ) {
00661 if ( target_walker_bag == 0 ) {
00662 log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog();
00663 return false;
00664 }
00665 return updateProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );
00666 }
00667 else {
00668
00669 if (updateOrRefreshProperty( source_walker, target_walker, true) == false)
00670 return false;
00671 log(Debug) << "Found Property '"<<target_walker->getName() <<"': update done." << endlog();
00672 return true;
00673 }
00674 } else {
00675
00676 log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
00677 return false;
00678 }
00679
00680 return false;
00681 }
00682
00683 bool refreshProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator)
00684 {
00685 Logger::In in("refreshProperty");
00686
00687 PropertyBase* source_walker;
00688 PropertyBase* target_walker;
00689 std::string token;
00690 std::string::size_type start = 0;
00691 if ( separator.length() != 0 && name.find(separator) == 0 )
00692 start = separator.length();
00693 std::string::size_type len = name.find(separator, start);
00694 if (len != std::string::npos) {
00695 token = name.substr(start,len-start);
00696 start = len + separator.length();
00697 if ( start >= name.length() )
00698 start = std::string::npos;
00699 }
00700 else {
00701 token = name.substr(start);
00702 start = std::string::npos;
00703 }
00704 source_walker = source.find(token);
00705 target_walker = target.find(token);
00706 if (source_walker != 0 )
00707 {
00708 if ( target_walker == 0 ) {
00709 log(Error) << "Property '"<<source_walker->getName()<<"' was not found in target !"<<endlog();
00710 return false;
00711 }
00712 Property<PropertyBag>* source_walker_bag;
00713 Property<PropertyBag>* target_walker_bag;
00714 source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker);
00715 target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker);
00716 if ( source_walker_bag != 0 && start != std::string::npos ) {
00717 if ( target_walker_bag == 0 ) {
00718 log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog();
00719 return false;
00720 }
00721 return refreshProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );
00722 }
00723 else {
00724 if (updateOrRefreshProperty( source_walker, target_walker, false) == false)
00725 return false;
00726 log(Debug) << "Found Property '"<<target_walker->getName() <<"': refresh done." << endlog();
00727 return true;
00728 }
00729 } else {
00730
00731 log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
00732 return false;
00733 }
00734
00735 return false;
00736 }
00737
00738 void deleteProperties(PropertyBag& target)
00739 {
00740
00741 PropertyBag::const_iterator it( target.getProperties().begin() );
00742 while ( it != target.getProperties().end() )
00743 {
00744
00745 if (!target.ownsProperty( *it ))
00746 delete (*it);
00747 ++it;
00748 }
00749 target.clear();
00750 }
00751
00752 void deletePropertyBag(PropertyBag& target)
00753 {
00754
00755 PropertyBag::const_iterator it( target.getProperties().begin() );
00756 while ( it != target.getProperties().end() )
00757 {
00758
00759 Property<PropertyBag>* result = dynamic_cast< Property<PropertyBag>* >( *it );
00760 if ( result != 0 )
00761 deletePropertyBag( result->value() );
00762 if (!target.ownsProperty( *it ))
00763 delete (*it);
00764 ++it;
00765 }
00766
00767 target.clear();
00768 }
00769
00770 void flattenPropertyBag(PropertyBag& target, const std::string& separator)
00771 {
00772
00773 Property<PropertyBag>* result;
00774 PropertyBag::const_iterator it( target.getProperties().begin() );
00775 while ( it != target.getProperties().end() )
00776 {
00777 result = dynamic_cast< Property<PropertyBag>* >( *it );
00778 if ( result != 0 )
00779 {
00780 flattenPropertyBag( result->value(), separator );
00781
00782 PropertyBag::const_iterator flat_it( result->value().getProperties().begin() ) ;
00783 if ( flat_it != result->value().getProperties().end() )
00784 {
00785 while (flat_it != result->value().getProperties().end() )
00786 {
00787 (*flat_it)->setName( result->getName() + separator + (*flat_it)->getName() );
00788 target.add( (*flat_it) );
00789 result->value().remove( *flat_it );
00790 flat_it = result->value().getProperties().begin();
00791 }
00792 it = target.getProperties().begin();
00793 continue;
00794 }
00795
00796 }
00797 ++it;
00798 }
00799 }
00800
00801 }