00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 TypeInfo.cpp 00003 00004 TypeInfo.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 00039 #include "TypeInfo.hpp" 00040 #include "TypeConstructor.hpp" 00041 #include "../internal/DataSourceTypeInfo.hpp" 00042 #include "../internal/ConnFactory.hpp" 00043 #include "TypeTransporter.hpp" 00044 00045 #include "rtt-config.h" 00046 00047 #include "../Logger.hpp" 00048 #include "../base/AttributeBase.hpp" 00049 00050 namespace RTT 00051 { 00052 using namespace std; 00053 using namespace detail; 00054 using namespace internal; 00055 00056 TypeInfo::~TypeInfo() 00057 { 00058 // cleanup transporters 00059 for (Transporters::iterator i = transporters.begin(); i != transporters.end(); ++i) 00060 delete *i; 00061 00062 // cleanup constructors 00063 for (Constructors::iterator i= constructors.begin(); i != constructors.end(); ++i) 00064 delete (*i); 00065 } 00066 00067 std::vector<std::string> TypeInfo::getTypeNames() const 00068 { 00069 return mtypenames; 00070 } 00071 00072 void TypeInfo::addAlias(const std::string& alias) { 00073 // only alias new names: 00074 if ( !alias.empty() && find(mtypenames.begin(), mtypenames.end(), alias) == mtypenames.end() ) 00075 mtypenames.push_back(alias); 00076 } 00077 00078 bool TypeInfo::isType(const std::string& name) { 00079 return (find(mtypenames.begin(), mtypenames.end(), name) != mtypenames.end() ); 00080 } 00081 00082 base::AttributeBase* TypeInfo::buildVariable(std::string name, int hint) const 00083 { 00084 return mdsf ? mdsf->buildVariable(name, hint) : 0; 00085 } 00086 00087 DataSourceBase::shared_ptr TypeInfo::construct(const std::vector<DataSourceBase::shared_ptr>& args) const 00088 { 00089 00090 DataSourceBase::shared_ptr ds; 00091 // build default constructible: 00092 if ( args.empty() ) { 00093 AttributeBase* ab = this->buildVariable("constructor"); 00094 ds = ab->getDataSource(); 00095 delete ab; 00096 return ds; 00097 } 00098 00099 // return same type if equal: 00100 if ( args.size() == 1 && args.front()->getTypeInfo() == this ) 00101 return args.front(); 00102 00103 Constructors::const_iterator i= constructors.begin(); 00104 while (i != constructors.end() ) { 00105 ds = (*i)->build( args ); 00106 if ( ds ) 00107 return ds; 00108 ++i; 00109 } 00110 // returns empty data source to indicate not constructible 00111 return ds; 00112 } 00113 00114 void TypeInfo::addConstructor(TypeConstructor* tb) { 00115 constructors.push_back(tb); 00116 } 00117 00118 DataSourceBase::shared_ptr TypeInfo::convert(DataSourceBase::shared_ptr arg) const 00119 { 00120 DataSourceBase::shared_ptr ds; 00121 Constructors::const_iterator i= constructors.begin(); 00122 if ( arg->getTypeInfo() == this ) 00123 return arg; 00124 //log(Info) << getTypeName() << ": trying to convert from " << arg->getTypeName()<<endlog(); 00125 while (i != constructors.end() ) { 00126 ds = (*i)->convert( arg ); 00127 if ( ds ) { 00128 return ds; 00129 } 00130 ++i; 00131 } 00132 // if no conversion happend, return arg again. 00133 return arg; 00134 } 00135 00136 bool TypeInfo::addProtocol(int protocol_id, TypeTransporter* tt) 00137 { 00138 if (transporters.size() < static_cast<size_t>(protocol_id + 1)) 00139 transporters.resize(protocol_id + 1); 00140 if ( transporters[protocol_id] ) { 00141 log(Debug) << "A protocol with id "<<protocol_id<<" was already added for type "<< getTypeName()<<endlog(); 00142 delete tt; 00143 return false; 00144 } 00145 transporters[protocol_id] = tt; 00146 return true; 00147 } 00148 00149 TypeTransporter* TypeInfo::getProtocol(int protocol_id) const 00150 { 00151 // if the protocol is unknown to this type, return the protocol of the 'unknown type' 00152 // type, which is a fallback such that we won't have to return zero, but can 00153 // gracefully fall-back. 00154 // In order to not endlessly recurse, we check if we aren't the UnknownType ! 00155 if ( protocol_id + 1 > int(transporters.size()) || transporters[protocol_id] == 0) { 00156 if ( DataSourceTypeInfo<UnknownType>::getTypeInfo() != this ) 00157 return DataSourceTypeInfo<UnknownType>::getTypeInfo()->getProtocol( protocol_id ); 00158 else { 00159 log(Warning) << "The protocol with id "<<protocol_id<<" did not register a fall-back handler for unknown types!"<<endlog(); 00160 log(Warning) << " triggered by: "<< getTypeName() << " which does not have a transport."<<endlog(); 00161 return 0; // That transport did not register a fall-back ! 00162 } 00163 } 00164 return transporters[protocol_id]; 00165 } 00166 00167 bool TypeInfo::hasProtocol(int protocol_id) const 00168 { 00169 // if the protocol is unknown to this type, return the protocol of the 'unknown type' 00170 // type, which is a fallback such that we won't have to return zero, but can 00171 // gracefully fall-back. 00172 // In order to not endlessly recurse, we check if we aren't the UnknownType ! 00173 if ( protocol_id + 1 > int(transporters.size()) || transporters[protocol_id] == 0) { 00174 return false; 00175 } 00176 return true; 00177 } 00178 00179 std::vector<int> TypeInfo::getTransportNames() const 00180 { 00181 std::vector<int> ret; 00182 for (size_t i=0; i<transporters.size(); ++i) 00183 { 00184 // dump only protocols with an actual transporter 00185 // NB the transporter does not have a name, so you have to manually 00186 // match the protocol number to an actual transport 00187 if (0 != transporters[i]) 00188 { 00189 ret.push_back(i); 00190 } 00191 } 00192 return ret; 00193 } 00194 00195 00196 base::InputPortInterface* TypeInfo::inputPort(std::string const& name) const 00197 { 00198 return mconnf ? mconnf->inputPort(name) : 0; 00199 } 00200 00201 base::OutputPortInterface* TypeInfo::outputPort(std::string const& name) const 00202 { 00203 return mconnf ? mconnf->outputPort(name) : 0; 00204 } 00205 00206 base::ChannelElementBase::shared_ptr TypeInfo::buildDataStorage(ConnPolicy const& policy) const 00207 { 00208 return mconnf ? mconnf->buildDataStorage(policy) : base::ChannelElementBase::shared_ptr(); 00209 } 00210 base::ChannelElementBase::shared_ptr TypeInfo::buildChannelOutput(base::InputPortInterface& port) const 00211 { 00212 return mconnf ? mconnf->buildChannelOutput(port) : base::ChannelElementBase::shared_ptr(); 00213 } 00214 base::ChannelElementBase::shared_ptr TypeInfo::buildChannelInput(base::OutputPortInterface& port) const 00215 { 00216 return mconnf ? mconnf->buildChannelInput(port) : base::ChannelElementBase::shared_ptr(); 00217 } 00218 00219 }