PropertyBag.cpp
Go to the documentation of this file.
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()
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); // invalidates 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         //iterate over orig, update or clone PropertyBases
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 ) // detect 'root' attribute
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();      // reset start to next token.
00317             if ( start >= nameSequence.length() )
00318                 start = std::string::npos;
00319         }
00320         else {
00321             token = nameSequence.substr(start);
00322             start = std::string::npos; // do not look further.
00323         }
00324         result = bag.find(token);
00325         if (result != 0 ) // get the base with this name
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 );// a bag so search recursively
00330             }
00331             else
00332                 return result; // not a bag, so it is a result.
00333         }
00334         return 0; // failure
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         // find top-level parent
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); // recurse
00400 
00401         // pname is parent
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         // recurse using new parentbag and rest.
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         // empty path
00419         if ( path.empty() || path == separator )
00420             return false;
00421         // single item path
00422         if ( path.find( separator ) == string::npos)
00423             return bag.removeProperty( bag.find(path) );
00424         // multi item path
00425         string prefix = path.substr( 0, path.rfind(separator));
00426         string pname  = path.substr( path.rfind(separator) + separator.length() );
00427         // '.item' form:
00428         if ( prefix.empty() )
00429             return bag.removeProperty( bag.find(pname) );
00430         // 'bag.item' form:
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         // no need to make new one, just update existing one
00450         if ( (update && target->update( source ) == false ) || (!update && target->refresh( source ) == false ) ) {
00451             // try conversion
00452             DataSourceBase::shared_ptr converted = target->getTypeInfo()->convert( source->getDataSource() );
00453             if ( !converted || converted == source->getDataSource() ) {
00454                 // no conversion, try composition:
00455                 converted = target->getDataSource();
00456                 if (target->getTypeInfo()->composeType( source->getDataSource(), converted ) ) {
00457                     // case where there is a type composition -> target was updated by composeType
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                     //if ( !target->getTypeInfo()->composeType( source->getDataSource(), target->getDataSource() ) )
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                 // conversion: update with converted value:
00472                 // case where there is a type conversion -> do the update of the target
00473                 // since 'converted' might be a non-Assignable DataSource, we need a work-around:
00474                 PropertyBase* dummy = target->getTypeInfo()->buildProperty("","");
00475                 dummy->getDataSource()->update( converted.get() );
00476                 assert(dummy->getTypeInfo() == converted->getTypeInfo() );
00477                 // we need to use the PropertyBase API and not the DataSource API !
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         // if the target is of different type than source, it is replaced by source.
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         //iterate over source, update PropertyBases
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() == "" ) //&& target.getType() == "Sequence" )
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                 // ok.
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         // dynamic_cast ?
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         // Make a full deep copy.
00541         //iterate over source, clone all PropertyBases
00542         PropertyBag::const_iterator it( source.getProperties().begin() );
00543         while ( it != source.getProperties().end() )
00544         {
00545             // step 1 : clone a new instance (non deep copy)
00546             PropertyBase* temp = (*it)->create();
00547             // step 2 : deep copy clone with original.
00548             temp->copy( *it );
00549             // step 3 : add result to target bag.
00550             target.ownProperty( temp );
00551             ++it;
00552         }
00553         return true;
00554     }
00555 
00556 
00557     bool updateProperties(PropertyBag& target, const PropertyBag& source)
00558     {
00559         // check type consistency...
00560         if ( target.getType() == "" || target.getType() == "type_less" )
00561             target.setType("PropertyBag"); // RTT 1.2.0
00562 
00563         // if the target is of different type than source, it is replaced by source.
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         // Make an updated if present, create if not present
00572         //iterate over source, update or clone PropertyBases
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                     // ok.
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                         // step 1: test for composing a typed property bag:
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                             // fallback : clone a new instance (non deep copy)
00613                             temp = (*sit)->create();
00614                             // deep copy clone with original, will never fail.
00615                             temp->update( (*sit) );
00616                         }
00617                         // step 3 : add result to target bag.
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         // this code has been copied&modified from findProperty().
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 ) // detect 'root' attribute
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();      // reset start to next token.
00640             if ( start >= name.length() )
00641                 start = std::string::npos;
00642         }
00643         else {
00644             token = name.substr(start);
00645             start = std::string::npos; // do not look further.
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                 // if not present in target, create it !
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 );// a bag so search recursively
00666             }
00667             else {
00668                 // found it, update !
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             // error wrong path, not present in source !
00676             log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
00677             return false;
00678         }
00679         // not reached.
00680         return false; // failure
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         // this code has been copied&modified from findProperty().
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 ) // detect 'root' attribute
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();      // reset start to next token.
00697             if ( start >= name.length() )
00698                 start = std::string::npos;
00699         }
00700         else {
00701             token = name.substr(start);
00702             start = std::string::npos; // do not look further.
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 );// a bag so search recursively
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             // error wrong path, not present in source !
00731             log(Error) << "Property '"<< token <<"' is not present in the source PropertyBag !"<<endlog();
00732             return false;
00733         }
00734         // not reached.
00735         return false; // failure
00736     }
00737 
00738     void deleteProperties(PropertyBag& target)
00739     {
00740         //non-recursive delete.
00741         PropertyBag::const_iterator it( target.getProperties().begin() );
00742         while ( it != target.getProperties().end() )
00743         {
00744             // This loop is solely for deleting not owned properties.
00745             if (!target.ownsProperty( *it ))
00746                 delete (*it);
00747             ++it;
00748         }
00749         target.clear();
00750     }
00751 
00752     void deletePropertyBag(PropertyBag& target)
00753     {
00754         //iterate over target, delete PropertyBases
00755         PropertyBag::const_iterator it( target.getProperties().begin() );
00756         while ( it != target.getProperties().end() )
00757         {
00758             // This loop is solely for deleting not owned properties and recursing
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         // deletes owned properties.
00767         target.clear();
00768     }
00769 
00770     void flattenPropertyBag(PropertyBag& target, const std::string& separator)
00771     {
00772         //iterate over target, recursively flatten bags.
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 );// a bag so flatten recursively
00781                 // copy all elements from result to target.
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(); // reset iterator
00793                     continue;                            // do not increase it
00794                 }
00795                 // the bag is empty now, but it must stay in target.
00796             }
00797             ++it;
00798         }
00799     }
00800 
00801 }


rtt
Author(s): RTT Developers
autogenerated on Fri Sep 9 2016 04:01:56