PropertyDecomposition.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  PropertyDecomposition.cpp
00003 
00004                         PropertyDecomposition.cpp -  description
00005                            -------------------
00006     begin                : Tue September 07 2010
00007     copyright            : (C) 2010 The SourceWorks
00008     email                : peter@thesourceworks.com
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 
00046 #include "PropertyDecomposition.hpp"
00047 #include "../internal/DataSource.hpp"
00048 #include <vector>
00049 #include <string>
00050 #include <memory>
00051 #include <boost/lexical_cast.hpp>
00052 #include "../Logger.hpp"
00053 #include "TypeInfo.hpp"
00054 #include "../Property.hpp"
00055 
00056 
00057 using namespace std;
00058 using namespace RTT;
00059 using namespace RTT::detail;
00060 
00061 namespace RTT { namespace types {
00062 
00063 bool propertyDecomposition( base::PropertyBase* source, PropertyBag& targetbag, bool recurse )
00064 {
00065     if (!source)
00066         return false;
00067     DataSourceBase::shared_ptr dsb = source->getDataSource();
00068     if (!dsb)
00069         return false;
00070     return typeDecomposition( dsb, targetbag, recurse);
00071 }
00072 
00073 bool typeDecomposition( base::DataSourceBase::shared_ptr dsb, PropertyBag& targetbag, bool recurse)
00074 {
00075     if (!dsb)
00076         return false;
00077 
00078     // try user's custom type decomposition first:
00079     DataSourceBase::shared_ptr decomposed = dsb->getTypeInfo()->decomposeType(dsb);
00080     // In cases where decomposeType() returned dsb itself, we stop the decomposition here.
00081     if (decomposed == dsb)
00082         return false;
00083     if (decomposed) {
00084         // decomposed is or another type, or a PropertyBag
00085         internal::AssignableDataSource<PropertyBag>::shared_ptr bag = internal::AssignableDataSource<PropertyBag>::narrow( decomposed.get() );
00086         if ( bag ) {
00087             // get it and copy it.
00088             targetbag = bag->rvalue();
00089             return true;
00090         } else {
00091             // it converted to something else than a bag.
00092             //log(Debug) << "propertyDecomposition: decomposeType() of "<<  dsb->getTypeName() << " did not return a PropertyBag but a " << decomposed->getTypeName() << endlog();
00093             return false;
00094         }
00095     }
00096 
00097     vector<string> parts = dsb->getMemberNames();
00098     if ( parts.empty() ) {
00099         log(Debug) << "propertyDecomposition: "<<  dsb->getTypeName() << " does not have any members." << endlog();
00100         return false;
00101     }
00102 
00103     targetbag.setType( dsb->getTypeName() );
00104 
00105     // needed for recursion.
00106     auto_ptr< Property<PropertyBag> > recurse_bag( new Property<PropertyBag>("recurse_bag","Part") );
00107     // First at the explicitly listed parts:
00108     for(vector<string>::iterator it = parts.begin(); it != parts.end(); ++it ) {
00109         DataSourceBase::shared_ptr part = dsb->getMember( *it );
00110         if (!part) {
00111             log(Error) <<"propertyDecomposition: Inconsistent type info for "<< dsb->getTypeName() << ": reported to have part '"<<*it<<"' but failed to return it."<<endlog();
00112             continue;
00113         }
00114         if ( !part->isAssignable() ) {
00115             // For example: the case for size() and capacity() in SequenceTypeInfo
00116             log(Debug)<<"propertyDecomposition: Part "<< *it << ":"<< part->getTypeName() << " is not changeable."<<endlog();
00117             continue;
00118         }
00119         // finally recurse or add it to the target bag:
00120         PropertyBase* newpb = part->getTypeInfo()->buildProperty(*it,"Part",part);
00121         if ( !newpb ) {
00122             log(Error)<< "Decomposition failed because Part '"<<*it<<"' is not known to type system."<<endlog();
00123             continue;
00124         }
00125         if ( !recurse )
00126             targetbag.ownProperty( newpb ); // leaf
00127         else if ( !propertyDecomposition( newpb, recurse_bag->value(), true) ) {
00128             //recurse_bag is empty
00129             assert( recurse_bag->rvalue().empty() );
00130             base::DataSourceBase::shared_ptr clone = newpb->getDataSource();
00131             base::DataSourceBase::shared_ptr converted = clone->getTypeInfo()->decomposeType(clone);
00132             if ( converted && converted != clone ) {
00133                 // converted contains another type
00134                 targetbag.add( converted->getTypeInfo()->buildProperty(*it, "", converted) );
00135             } else {
00136                 // use the original
00137                 targetbag.add( newpb );
00138             }
00139         } else {
00140             assert( recurse_bag->rvalue().size() >= 1 ); 
00141             recurse_bag->setName(*it);
00142             // setType() is done by recursive of self.
00143             targetbag.ownProperty( recurse_bag.release() ); //recursed.
00144             recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Part") );
00145             delete newpb; // since we recursed, the recurse_bag now 'embodies' newpb.
00146         }
00147     }
00148 
00149     // Prepare recurse_bag for storing composite items:
00150     recurse_bag->setDescription("Item");
00151 
00152     // Next get the numbered parts:
00153     DataSource<int>::shared_ptr size = DataSource<int>::narrow( dsb->getMember("size").get() );
00154     if (size) {
00155         int msize = size->get();
00156         for (int i=0; i < msize; ++i) {
00157             string indx = boost::lexical_cast<string>( i );
00158             DataSourceBase::shared_ptr item = dsb->getMember(indx);
00159             if (item) {
00160                 if ( !item->isAssignable() ) {
00161                     // For example: the case for size() and capacity() in SequenceTypeInfo
00162                     log(Warning)<<"propertyDecomposition: Item '"<< indx << "' of type "<< dsb->getTypeName() << " is not changeable."<<endlog();
00163                     continue;
00164                 }
00165                 // finally recurse or add it to the target bag:
00166                 PropertyBase* newpb = item->getTypeInfo()->buildProperty( "Element" + indx,"Sequence Element",item);
00167                 if ( !recurse || !propertyDecomposition( newpb, recurse_bag->value()) ) {
00168                     targetbag.ownProperty( newpb ); // leaf
00169                 } else {
00170                     delete newpb;
00171                     recurse_bag->setName( "Element" + indx );
00172                     // setType() is done by recursive of self.
00173                     targetbag.ownProperty( recurse_bag.release() ); //recursed.
00174                     recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Item") );
00175                 }
00176             }
00177         }
00178     }
00179     if (targetbag.empty() )
00180         log(Debug) << "propertyDecomposition: "<<  dsb->getTypeName() << " returns an empty property bag." << endlog();
00181     return true;
00182 }
00183 
00184 }}


rtt
Author(s): RTT Developers
autogenerated on Wed Aug 26 2015 16:15:51