Orocos Real-Time Toolkit
2.5.0
|
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 if (decomposed) { 00081 // decomposed is or another type, or a PropertyBag 00082 internal::AssignableDataSource<PropertyBag>::shared_ptr bag = internal::AssignableDataSource<PropertyBag>::narrow( decomposed.get() ); 00083 if ( bag ) { 00084 // get it and copy it. 00085 targetbag = bag->rvalue(); 00086 return true; 00087 } else { 00088 // it converted to something else than a bag. 00089 // In cases where decomposeType() returned dsb itself, we stop the decomposition here. 00090 //log(Debug) << "propertyDecomposition: decomposeType() of "<< dsb->getTypeName() << " did not return a PropertyBag but a " << decomposed->getTypeName() << endlog(); 00091 return false; 00092 } 00093 } 00094 00095 vector<string> parts = dsb->getMemberNames(); 00096 if ( parts.empty() ) { 00097 log(Debug) << "propertyDecomposition: "<< dsb->getTypeName() << " does not have any members." << endlog(); 00098 return false; 00099 } 00100 00101 targetbag.setType( dsb->getTypeName() ); 00102 00103 // needed for recursion. 00104 auto_ptr< Property<PropertyBag> > recurse_bag( new Property<PropertyBag>("recurse_bag","Part") ); 00105 // First at the explicitly listed parts: 00106 for(vector<string>::iterator it = parts.begin(); it != parts.end(); ++it ) { 00107 DataSourceBase::shared_ptr part = dsb->getMember( *it ); 00108 if (!part) { 00109 log(Error) <<"propertyDecomposition: Inconsistent type info for "<< dsb->getTypeName() << ": reported to have part '"<<*it<<"' but failed to return it."<<endlog(); 00110 continue; 00111 } 00112 if ( !part->isAssignable() ) { 00113 // For example: the case for size() and capacity() in SequenceTypeInfo 00114 log(Debug)<<"propertyDecomposition: Part "<< *it << ":"<< part->getTypeName() << " is not changeable."<<endlog(); 00115 continue; 00116 } 00117 // finally recurse or add it to the target bag: 00118 PropertyBase* newpb = part->getTypeInfo()->buildProperty(*it,"Part",part); 00119 if ( !newpb ) { 00120 log(Error)<< "Decomposition failed because Part '"<<*it<<"' is not known to type system."<<endlog(); 00121 continue; 00122 } 00123 if ( !recurse || !propertyDecomposition( newpb, recurse_bag->value(), true) ) { 00124 assert( recurse_bag->value().empty() ); 00125 targetbag.ownProperty( newpb ); // leaf 00126 } else { 00127 recurse_bag->setName(*it); 00128 // setType() is done by recursive of self. 00129 targetbag.ownProperty( recurse_bag.release() ); //recursed. 00130 recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Part") ); 00131 delete newpb; // since we recursed, the recurse_bag now 'embodies' newpb. 00132 } 00133 } 00134 00135 // Prepare recurse_bag for storing composite items: 00136 recurse_bag->setDescription("Item"); 00137 00138 // Next get the numbered parts: 00139 DataSource<int>::shared_ptr size = DataSource<int>::narrow( dsb->getMember("size").get() ); 00140 if (size) { 00141 int msize = size->get(); 00142 for (int i=0; i < msize; ++i) { 00143 string indx = boost::lexical_cast<string>( i ); 00144 DataSourceBase::shared_ptr item = dsb->getMember(indx); 00145 if (item) { 00146 if ( !item->isAssignable() ) { 00147 // For example: the case for size() and capacity() in SequenceTypeInfo 00148 log(Warning)<<"propertyDecomposition: Item '"<< indx << "' of type "<< dsb->getTypeName() << " is not changeable."<<endlog(); 00149 continue; 00150 } 00151 // finally recurse or add it to the target bag: 00152 PropertyBase* newpb = item->getTypeInfo()->buildProperty( "Element" + indx,"Sequence Element",item); 00153 if ( !recurse || !propertyDecomposition( newpb, recurse_bag->value()) ) { 00154 targetbag.ownProperty( newpb ); // leaf 00155 } else { 00156 delete newpb; 00157 recurse_bag->setName( "Element" + indx ); 00158 // setType() is done by recursive of self. 00159 targetbag.ownProperty( recurse_bag.release() ); //recursed. 00160 recurse_bag.reset( new Property<PropertyBag>("recurse_bag","Item") ); 00161 } 00162 } 00163 } 00164 } 00165 if (targetbag.empty() ) 00166 log(Debug) << "propertyDecomposition: "<< dsb->getTypeName() << " returns an empty property bag." << endlog(); 00167 return true; 00168 } 00169 00170 }}