Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: Peter Soetens Mon May 10 19:10:30 CEST 2004 PropertyBag.cxx 00003 00004 PropertyBag.cxx - description 00005 ------------------- 00006 begin : Mon May 10 2004 00007 copyright : (C) 2004 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.ac.be 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 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(), type( orig.getType() ) 00064 { 00065 for( const_iterator i = orig.mproperties.begin(); i != orig.mproperties.end(); ++i) { 00066 if ( orig.ownsProperty( *i ) ) { 00067 PropertyBase* copy = (*i)->clone(); 00068 this->ownProperty( copy ); 00069 } else { 00070 this->add( *i ); 00071 } 00072 } 00073 } 00074 00075 PropertyBag::~PropertyBag() 00076 { 00077 this->clear(); 00078 } 00079 00080 void PropertyBag::add(PropertyBase *p) 00081 { 00082 this->addProperty(*p); 00083 } 00084 00085 void PropertyBag::remove(PropertyBase *p) 00086 { 00087 this->removeProperty(p); 00088 } 00089 00090 bool PropertyBag::ownProperty(PropertyBase* p) 00091 { 00092 if (p == 0) 00093 return false; 00094 if ( ! p->ready() ) 00095 return false; 00096 removeProperty(p); 00097 mproperties.push_back(p); 00098 mowned_props.push_back(p); 00099 return true; 00100 } 00101 00102 bool PropertyBag::ownsProperty(PropertyBase* p) const 00103 { 00104 if (p == 0) 00105 return false; 00106 const_iterator i = std::find(mowned_props.begin(), mowned_props.end(), p); 00107 if ( i != mowned_props.end() ) 00108 return true; 00109 return false; 00110 } 00111 00112 bool PropertyBag::addProperty(PropertyBase& p) 00113 { 00114 if (&p == 0) 00115 return false; 00116 if ( ! p.ready() ) 00117 return false; 00118 mproperties.push_back(&p); 00119 return true; 00120 } 00121 00122 bool PropertyBag::removeProperty(PropertyBase *p) 00123 { 00124 if (p == 0) 00125 return false; 00126 iterator i = std::find(mproperties.begin(), mproperties.end(), p); 00127 if ( i != mproperties.end() ) { 00128 mproperties.erase(i); 00129 i = std::find(mowned_props.begin(), mowned_props.end(), p); 00130 if ( i != mowned_props.end() ) { 00131 delete *i; 00132 mowned_props.erase(i); // invalidates i 00133 } 00134 return true; 00135 } 00136 return false; 00137 } 00138 00139 void PropertyBag::clear() 00140 { 00141 mproperties.clear(); 00142 for ( iterator i = mowned_props.begin(); 00143 i != mowned_props.end(); 00144 i++ ) 00145 { 00146 delete *i; 00147 } 00148 mowned_props.clear(); 00149 } 00150 00151 void PropertyBag::list(std::vector<std::string> &names) const 00152 { 00153 for ( const_iterator i = mproperties.begin(); 00154 i != mproperties.end(); 00155 i++ ) 00156 { 00157 names.push_back( (*i)->getName() ); 00158 } 00159 } 00160 00161 std::vector<std::string> PropertyBag::list() const 00162 { 00163 std::vector<std::string> names; 00164 for ( const_iterator i = mproperties.begin(); 00165 i != mproperties.end(); 00166 i++ ) 00167 { 00168 names.push_back( (*i)->getName() ); 00169 } 00170 return names; 00171 } 00172 00173 PropertyBag::Properties PropertyBag::getProperties(const std::string& name) const 00174 { 00175 Properties names; 00176 for ( const_iterator i = mproperties.begin(); 00177 i != mproperties.end(); 00178 i++ ) 00179 { 00180 if ( (*i)->getName() == name ) 00181 names.push_back( (*i) ); 00182 } 00183 return names; 00184 } 00185 00186 00187 void PropertyBag::identify( PropertyIntrospection* pi ) const 00188 { 00189 for ( const_iterator i = mproperties.begin(); 00190 i != mproperties.end(); 00191 i++ ) 00192 { 00193 (*i)->identify(pi); 00194 } 00195 } 00196 00197 void PropertyBag::identify( PropertyBagVisitor* pi ) const 00198 { 00199 for ( const_iterator i = mproperties.begin(); 00200 i != mproperties.end(); 00201 i++ ) 00202 { 00203 (*i)->identify(pi); 00204 } 00205 } 00206 00211 struct FindProp : public std::binary_function<const base::PropertyBase*,const std::string, bool> 00212 { 00213 bool operator()(const base::PropertyBase* b1, const std::string& b2) const { return b1->getName() == b2; } 00214 }; 00217 PropertyBase* PropertyBag::find(const std::string& name) const 00218 { 00219 const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(FindProp(), name ) ) ); 00220 if ( i != mproperties.end() ) 00221 return ( *i ); 00222 return 0; 00223 } 00224 00225 base::PropertyBase* PropertyBag::getProperty(const std::string& name) const 00226 { 00227 const_iterator i( std::find_if(mproperties.begin(), mproperties.end(), std::bind2nd(FindProp(), name ) ) ); 00228 if ( i != mproperties.end() ) 00229 return *i; 00230 return 0; 00231 } 00232 00233 00234 PropertyBag& PropertyBag::operator=(const PropertyBag& orig) 00235 { 00236 if(this == &orig) 00237 return *this; 00238 00239 this->clear(); 00240 00241 const_iterator i = orig.getProperties().begin(); 00242 while (i != orig.getProperties().end() ) 00243 { 00244 add( (*i) ); 00245 ++i; 00246 } 00247 this->setType( orig.getType() ); 00248 return *this; 00249 } 00250 00251 PropertyBag& PropertyBag::operator<<=(const PropertyBag& source) 00252 { 00253 //iterate over orig, update or clone PropertyBases 00254 const_iterator it(source.getProperties().begin()); 00255 while ( it != source.getProperties().end() ) 00256 { 00257 PropertyBase* mine = find( (*it)->getName() ); 00258 if (mine != 0) 00259 remove(mine); 00260 add( (*it) ); 00261 ++it; 00262 } 00263 this->setType( source.getType() ); 00264 return *this; 00265 } 00266 00267 template<> 00268 bool Property<PropertyBag>::update( const Property<PropertyBag>& orig) 00269 { 00270 if ( !ready() ) 00271 return false; 00272 if ( _description.empty() ) 00273 _description = orig.getDescription(); 00274 return updateProperties( this->_value->set(), orig.rvalue() ); 00275 } 00276 00277 template<> 00278 bool Property<PropertyBag>::refresh( const Property<PropertyBag>& orig) 00279 { 00280 if ( !ready() ) 00281 return false; 00282 return refreshProperties( this->_value->set(), orig.rvalue() ); 00283 } 00284 00285 template<> 00286 bool Property<PropertyBag>::copy( const Property<PropertyBag>& orig) 00287 { 00288 if ( !ready() ) 00289 return false; 00290 _name = orig.getName(); 00291 _description = orig.getDescription(); 00292 return copyProperties( this->_value->set(), orig.rvalue() ); 00293 } 00294 00295 std::ostream& operator<<(std::ostream& os, const PropertyBag& bag) { 00296 int size = bag.size(); 00297 os << "[["; 00298 for(int i=0; i != size; ++i) { 00299 os << bag.getItem(i)->getName() << "='"<< bag.getItem(i) <<"'"<<endl; 00300 } 00301 os << "]]"; 00302 00303 return os; 00304 } 00305 00306 std::istream& operator>>(std::istream& is, PropertyBag& bag) { return is; } 00307 00308 00309 PropertyBase* findProperty(const PropertyBag& bag, const std::string& nameSequence, const std::string& separator) 00310 { 00311 PropertyBase* result; 00312 Property<PropertyBag>* result_bag; 00313 std::string token; 00314 std::string::size_type start = 0; 00315 if ( separator.length() != 0 && nameSequence.find(separator) == 0 ) // detect 'root' attribute 00316 start = separator.length(); 00317 std::string::size_type len = nameSequence.find(separator, start); 00318 if (len != std::string::npos) { 00319 token = nameSequence.substr(start,len-start); 00320 start = len + separator.length(); // reset start to next token. 00321 if ( start >= nameSequence.length() ) 00322 start = std::string::npos; 00323 } 00324 else { 00325 token = nameSequence.substr(start); 00326 start = std::string::npos; // do not look further. 00327 } 00328 result = bag.find(token); 00329 if (result != 0 ) // get the base with this name 00330 { 00331 result_bag = dynamic_cast<Property<PropertyBag>*>(result); 00332 if ( result_bag != 0 && start != std::string::npos ) { 00333 return findProperty( result_bag->rvalue(), nameSequence.substr( start ), separator );// a bag so search recursively 00334 } 00335 else 00336 return result; // not a bag, so it is a result. 00337 } 00338 return 0; // failure 00339 } 00340 00344 void listPropertiesHelper(const PropertyBag& source, const std::string& separator, const string& prefix, vector<string>& result) 00345 { 00346 PropertyBag::const_iterator it( source.getProperties().begin() ); 00347 while ( it != source.getProperties().end() ) { 00348 Property<PropertyBag>* sub = dynamic_cast<Property<PropertyBag>*>(*it); 00349 string itemname = prefix.empty() ? (*it)->getName() : prefix + separator + (*it)->getName(); 00350 result.push_back( itemname ); 00351 if ( sub && sub->ready() ) { 00352 listPropertiesHelper( sub->value(), separator, itemname, result ); 00353 } 00354 ++it; 00355 } 00356 } 00357 00360 void listDescriptionsHelper(const PropertyBag& source, const std::string& separator, vector<string>& result) 00361 { 00362 PropertyBag::const_iterator it( source.getProperties().begin() ); 00363 while ( it != source.getProperties().end() ) { 00364 Property<PropertyBag>* sub = dynamic_cast<Property<PropertyBag>*>(*it); 00365 result.push_back( (*it)->getDescription() ); 00366 if ( sub && sub->ready() ) { 00367 listDescriptionsHelper( sub->value(), separator, result ); 00368 } 00369 ++it; 00370 } 00371 } 00374 vector<string> listProperties(const PropertyBag& source, const std::string& separator) 00375 { 00376 vector<string> result; 00377 listPropertiesHelper( source, separator, "", result); 00378 return result; 00379 } 00380 00381 vector<string> listPropertyDescriptions(const PropertyBag& source, const std::string& separator) 00382 { 00383 vector<string> result; 00384 listDescriptionsHelper( source, separator, result); 00385 return result; 00386 } 00387 00388 bool storeProperty(PropertyBag& bag, const std::string& path, base::PropertyBase* item, const std::string& separator ) 00389 { 00390 Logger::In in("storeProperty"); 00391 if ( path.empty() || path == separator ) 00392 return bag.ownProperty( item ); 00393 // find top-level parent 00394 string pname, rest; 00395 if ( path.find(separator) != string::npos ) { 00396 pname = path.substr( 0, path.find(separator)); 00397 rest = path.substr( path.find(separator) + separator.length() ); 00398 } else { 00399 pname = path; 00400 } 00401 00402 if ( pname.empty() && !rest.empty() ) 00403 return storeProperty( bag, rest, item, separator); // recurse 00404 00405 // pname is parent 00406 PropertyBase* parent = bag.find(pname); 00407 if (!parent) { 00408 bag.ownProperty( new Property<PropertyBag>(pname,"") ); 00409 parent = bag.find(pname); 00410 } 00411 Property<PropertyBag>* parentbag = dynamic_cast<Property<PropertyBag>* >(parent); 00412 if ( !parentbag ) { 00413 log(Error) << "Path component '" << pname << "' in path '"<<path<<"' does not point to a PropertyBag."<<endlog(); 00414 return false; 00415 } 00416 // recurse using new parentbag and rest. 00417 return storeProperty( parentbag->value(), rest, item, separator); 00418 } 00419 00420 bool removeProperty(PropertyBag& bag, const std::string& path, const std::string& separator ) 00421 { 00422 // empty path 00423 if ( path.empty() || path == separator ) 00424 return false; 00425 // single item path 00426 if ( path.find( separator ) == string::npos) 00427 return bag.removeProperty( bag.find(path) ); 00428 // multi item path 00429 string prefix = path.substr( 0, path.rfind(separator)); 00430 string pname = path.substr( path.rfind(separator) + separator.length() ); 00431 // '.item' form: 00432 if ( prefix.empty() ) 00433 return bag.removeProperty( bag.find(pname) ); 00434 // 'bag.item' form: 00435 Property<PropertyBag> parent = findProperty( bag, prefix); 00436 if ( !parent.ready() ) 00437 return false; 00438 return parent.value().removeProperty( parent.value().find( pname ) ); 00439 } 00440 00441 bool updateOrRefreshProperty( PropertyBase* source, PropertyBase* target, bool update) 00442 { 00443 #ifndef NDEBUG 00444 if (update) 00445 log(Debug) << "updateProperties: updating Property " 00446 << source->getType() << " "<< source->getName() 00447 << "." << endlog(); 00448 else 00449 log(Debug) << "refreshProperties: refreshing Property " 00450 << source->getType() << " "<< source->getName() 00451 << "." << endlog(); 00452 #endif 00453 // no need to make new one, just update existing one 00454 if ( (update && target->update( source ) == false ) || (!update && target->refresh( source ) == false ) ) { 00455 // try conversion 00456 DataSourceBase::shared_ptr converted = target->getTypeInfo()->convert( source->getDataSource() ); 00457 if ( !converted || converted == source->getDataSource() ) { 00458 // no conversion, try composition: 00459 converted = target->getDataSource(); 00460 if (target->getTypeInfo()->composeType( source->getDataSource(), converted ) ) { 00461 // case where there is a type composition -> target was updated by composeType 00462 log(Debug) << "Composed Property " 00463 << target->getType() << " "<< source->getName() << " to type " <<target->getType() 00464 << " from type " << source->getType() << endlog(); 00465 return true; 00466 } else { 00467 //if ( !target->getTypeInfo()->composeType( source->getDataSource(), target->getDataSource() ) ) 00468 log(Error) << (update ? "updateProperties: " : "refreshProperties: ") << " Could not update, nor convert Property " 00469 << target->getType() << " "<< target->getName() 00470 << ": type mismatch, can not update with " 00471 << source->getType() << " "<< source->getName() << endlog(); 00472 return false; 00473 } 00474 } else { 00475 // conversion: update with converted value: 00476 // case where there is a type conversion -> do the update of the target 00477 // since 'converted' might be a non-Assignable DataSource, we need a work-around: 00478 PropertyBase* dummy = target->getTypeInfo()->buildProperty("",""); 00479 dummy->getDataSource()->update( converted.get() ); 00480 assert(dummy->getTypeInfo() == converted->getTypeInfo() ); 00481 // we need to use the PropertyBase API and not the DataSource API ! 00482 if (update) 00483 target->update(dummy); 00484 else 00485 target->refresh(dummy); 00486 log(Debug) << "Converted Property " 00487 << target->getType() << " "<< source->getName() << " to type " <<dummy->getType() 00488 << " from type " << source->getType() << endlog(); 00489 } 00490 } 00491 return true; 00492 } 00493 00494 bool refreshProperties(const PropertyBag& target, const PropertyBag& source, bool allprops) 00495 { 00496 Logger::In in("refreshProperties"); 00497 00498 // if the target is of different type than source, it is replaced by source. 00499 if ( target.getType() != "PropertyBag" && target.getType() != source.getType() ) { 00500 log(Error) << "Can not populate typed PropertyBag '"<< target.getType() <<"' from '"<<source.getType()<<"' (source and target type differed)."<<endlog(); 00501 return false; 00502 } 00503 00504 //iterate over source, update PropertyBases 00505 PropertyBag::const_iterator it( target.getProperties().begin() ); 00506 bool failure = false; 00507 while ( it != target.getProperties().end() ) 00508 { 00509 PropertyBase* srcprop; 00510 if ( (*it)->getName() == "" ) //&& target.getType() == "Sequence" ) 00511 srcprop = source.getItem( it - target.getProperties().begin() ); 00512 else 00513 srcprop = source.find( (*it)->getName() ); 00514 PropertyBase* tgtprop = *it; 00515 if (srcprop != 0) 00516 { 00517 if (updateOrRefreshProperty( srcprop, tgtprop, false) == false) 00518 return false; 00519 // ok. 00520 } else if (allprops) { 00521 log(Error) << "Could not find Property " 00522 << tgtprop->getType() << " "<< tgtprop->getName() 00523 << " in source."<< endlog(); 00524 failure = true; 00525 } 00526 ++it; 00527 } 00528 return !failure; 00529 } 00530 00531 bool refreshProperty(const PropertyBag& target, const PropertyBase& source) 00532 { 00533 PropertyBase* target_prop; 00534 // dynamic_cast ? 00535 if ( 0 != (target_prop = target.find( source.getName() ) ) ) 00536 { 00537 return target_prop->refresh( &source ); 00538 } 00539 return false; 00540 } 00541 00542 bool copyProperties(PropertyBag& target, const PropertyBag& source) 00543 { 00544 // Make a full deep copy. 00545 //iterate over source, clone all PropertyBases 00546 PropertyBag::const_iterator it( source.getProperties().begin() ); 00547 while ( it != source.getProperties().end() ) 00548 { 00549 // step 1 : clone a new instance (non deep copy) 00550 PropertyBase* temp = (*it)->create(); 00551 // step 2 : deep copy clone with original. 00552 temp->copy( *it ); 00553 // step 3 : add result to target bag. 00554 target.add( temp ); 00555 ++it; 00556 } 00557 return true; 00558 } 00559 00560 00561 bool updateProperties(PropertyBag& target, const PropertyBag& source) 00562 { 00563 // check type consistency... 00564 if ( target.getType() == "" || target.getType() == "type_less" ) 00565 target.setType("PropertyBag"); // RTT 1.2.0 00566 00567 // if the target is of different type than source, it is replaced by source. 00568 if ( target.getType() != "PropertyBag" && target.getType() != source.getType() ) { 00569 log(Error) << "Can not populate typed PropertyBag '"<< target.getType() <<"' from '"<<source.getType()<<"' (source and target type differed)."<<endlog(); 00570 return false; 00571 } 00572 00573 target.setType( source.getType() ); 00574 00575 // Make an updated if present, create if not present 00576 //iterate over source, update or clone PropertyBases 00577 00578 PropertyBag::Names allnames = source.list(); 00579 PropertyBag::Names::const_iterator endnames = std::unique(allnames.begin(), allnames.end()); 00580 PropertyBag::Names::const_iterator it( allnames.begin() ); 00581 while ( it != endnames ) 00582 { 00583 PropertyBag::Properties sources = source.getProperties(*it); 00584 PropertyBag::Properties mines = target.getProperties(*it); 00585 PropertyBag::iterator mit = mines.begin(); 00586 for( PropertyBag::const_iterator sit = sources.begin(); sit != sources.end(); ++sit ) { 00587 if ( mit != mines.end() ) { 00588 assert( (*sit)->getName() == (*mit)->getName()); 00589 if ( updateOrRefreshProperty( *sit, *mit, true) == false) 00590 return false; 00591 // ok. 00592 ++mit; 00593 } 00594 else 00595 { 00596 #ifndef NDEBUG 00597 Logger::log() << Logger::Debug; 00598 Logger::log() << "updateProperties: creating Property " 00599 << (*sit)->getType() << " "<< (*sit)->getName() 00600 << "." << Logger::endl; 00601 #endif 00602 // step 1: test for composing a typed property bag: 00603 PropertyBase* temp = 0; 00604 #if 0 00605 Property<PropertyBag>* tester = dynamic_cast<Property<PropertyBag>* >(*sit); 00606 if (tester && tester->value().getType() != "PropertyBag") { 00607 if (TypeInfo* ti = types::Types()->type(tester->value().getType())) { 00608 temp = ti->buildProperty( tester->getName(), tester->getDescription() ); 00609 assert(temp); 00610 bool res = temp->getTypeInfo()->composeType( tester->getDataSource(), temp->getDataSource() ); 00611 if (!res ) return false; 00612 } 00613 } 00614 #endif 00615 if (!temp) { 00616 // fallback : clone a new instance (non deep copy) 00617 temp = (*sit)->create(); 00618 // deep copy clone with original, will never fail. 00619 temp->update( (*sit) ); 00620 } 00621 // step 3 : add result to target bag. 00622 target.add( temp ); 00623 } 00624 } 00625 ++it; 00626 } 00627 return true; 00628 } 00629 00630 bool updateProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator) 00631 { 00632 Logger::In in("updateProperty"); 00633 // this code has been copied&modified from findProperty(). 00634 PropertyBase* source_walker; 00635 PropertyBase* target_walker; 00636 std::string token; 00637 std::string::size_type start = 0; 00638 if ( separator.length() != 0 && name.find(separator) == 0 ) // detect 'root' attribute 00639 start = separator.length(); 00640 std::string::size_type len = name.find(separator, start); 00641 if (len != std::string::npos) { 00642 token = name.substr(start,len-start); 00643 start = len + separator.length(); // reset start to next token. 00644 if ( start >= name.length() ) 00645 start = std::string::npos; 00646 } 00647 else { 00648 token = name.substr(start); 00649 start = std::string::npos; // do not look further. 00650 } 00651 source_walker = source.find(token); 00652 target_walker = target.find(token); 00653 if (source_walker != 0 ) 00654 { 00655 if ( target_walker == 0 ) { 00656 // if not present in target, create it ! 00657 target_walker = source_walker->create(); 00658 target.ownProperty( target_walker ); 00659 } 00660 Property<PropertyBag>* source_walker_bag; 00661 Property<PropertyBag>* target_walker_bag; 00662 source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker); 00663 target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker); 00664 if ( source_walker_bag != 0 && start != std::string::npos ) { 00665 if ( target_walker_bag == 0 ) { 00666 log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog(); 00667 return false; 00668 } 00669 return updateProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );// a bag so search recursively 00670 } 00671 else { 00672 // found it, update ! 00673 if (updateOrRefreshProperty( source_walker, target_walker, true) == false) 00674 return false; 00675 log(Debug) << "Found Property '"<<target_walker->getName() <<"': update done." << endlog(); 00676 return true; 00677 } 00678 } else { 00679 // error wrong path, not present in source ! 00680 log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog(); 00681 return false; 00682 } 00683 // not reached. 00684 return false; // failure 00685 } 00686 00687 bool refreshProperty(PropertyBag& target, const PropertyBag& source, const std::string& name, const std::string& separator) 00688 { 00689 Logger::In in("refreshProperty"); 00690 // this code has been copied&modified from findProperty(). 00691 PropertyBase* source_walker; 00692 PropertyBase* target_walker; 00693 std::string token; 00694 std::string::size_type start = 0; 00695 if ( separator.length() != 0 && name.find(separator) == 0 ) // detect 'root' attribute 00696 start = separator.length(); 00697 std::string::size_type len = name.find(separator, start); 00698 if (len != std::string::npos) { 00699 token = name.substr(start,len-start); 00700 start = len + separator.length(); // reset start to next token. 00701 if ( start >= name.length() ) 00702 start = std::string::npos; 00703 } 00704 else { 00705 token = name.substr(start); 00706 start = std::string::npos; // do not look further. 00707 } 00708 source_walker = source.find(token); 00709 target_walker = target.find(token); 00710 if (source_walker != 0 ) 00711 { 00712 if ( target_walker == 0 ) { 00713 log(Error) << "Property '"<<source_walker->getName()<<"' was not found in target !"<<endlog(); 00714 return false; 00715 } 00716 Property<PropertyBag>* source_walker_bag; 00717 Property<PropertyBag>* target_walker_bag; 00718 source_walker_bag = dynamic_cast<Property<PropertyBag>*>(source_walker); 00719 target_walker_bag = dynamic_cast<Property<PropertyBag>*>(target_walker); 00720 if ( source_walker_bag != 0 && start != std::string::npos ) { 00721 if ( target_walker_bag == 0 ) { 00722 log(Error) << "Property '"<<target_walker->getName()<<"' is not a PropertyBag !"<<endlog(); 00723 return false; 00724 } 00725 return refreshProperty( target_walker_bag->value(), source_walker_bag->rvalue(), name.substr( start ), separator );// a bag so search recursively 00726 } 00727 else { 00728 if (updateOrRefreshProperty( source_walker, target_walker, false) == false) 00729 return false; 00730 log(Debug) << "Found Property '"<<target_walker->getName() <<"': refresh done." << endlog(); 00731 return true; 00732 } 00733 } else { 00734 // error wrong path, not present in source ! 00735 log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog(); 00736 return false; 00737 } 00738 // not reached. 00739 return false; // failure 00740 } 00741 00742 void deleteProperties(PropertyBag& target) 00743 { 00744 //non-recursive delete. 00745 PropertyBag::const_iterator it( target.getProperties().begin() ); 00746 while ( it != target.getProperties().end() ) 00747 { 00748 // This loop is solely for deleting not owned properties. 00749 if (!target.ownsProperty( *it )) 00750 delete (*it); 00751 ++it; 00752 } 00753 target.clear(); 00754 } 00755 00756 void deletePropertyBag(PropertyBag& target) 00757 { 00758 //iterate over target, delete PropertyBases 00759 PropertyBag::const_iterator it( target.getProperties().begin() ); 00760 while ( it != target.getProperties().end() ) 00761 { 00762 // This loop is solely for deleting not owned properties and recursing 00763 Property<PropertyBag>* result = dynamic_cast< Property<PropertyBag>* >( *it ); 00764 if ( result != 0 ) 00765 deletePropertyBag( result->value() ); 00766 if (!target.ownsProperty( *it )) 00767 delete (*it); 00768 ++it; 00769 } 00770 // deletes owned properties. 00771 target.clear(); 00772 } 00773 00774 void flattenPropertyBag(PropertyBag& target, const std::string& separator) 00775 { 00776 //iterate over target, recursively flatten bags. 00777 Property<PropertyBag>* result; 00778 PropertyBag::const_iterator it( target.getProperties().begin() ); 00779 while ( it != target.getProperties().end() ) 00780 { 00781 result = dynamic_cast< Property<PropertyBag>* >( *it ); 00782 if ( result != 0 ) 00783 { 00784 flattenPropertyBag( result->value(), separator );// a bag so flatten recursively 00785 // copy all elements from result to target. 00786 PropertyBag::const_iterator flat_it( result->value().getProperties().begin() ) ; 00787 if ( flat_it != result->value().getProperties().end() ) 00788 { 00789 while (flat_it != result->value().getProperties().end() ) 00790 { 00791 (*flat_it)->setName( result->getName() + separator + (*flat_it)->getName() ); 00792 target.add( (*flat_it) ); 00793 result->value().remove( *flat_it ); 00794 flat_it = result->value().getProperties().begin(); 00795 } 00796 it = target.getProperties().begin(); // reset iterator 00797 continue; // do not increase it 00798 } 00799 // the bag is empty now, but it must stay in target. 00800 } 00801 ++it; 00802 } 00803 } 00804 00805 }