Orocos Real-Time Toolkit  2.5.0
TypeInfoRepository.cpp
00001 /***************************************************************************
00002   tag: The SourceWorks  Tue Sep 7 00:55:18 CEST 2010  TypeInfoRepository.cpp
00003 
00004                         TypeInfoRepository.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 "TypeInfoRepository.hpp"
00040 
00041 #include "rtt-config.h"
00042 
00043 #include "../Logger.hpp"
00044 #include "TypeTransporter.hpp"
00045 #include "TransportPlugin.hpp"
00046 #include "../internal/mystd.hpp"
00047 #include "../internal/DataSourceTypeInfo.hpp"
00048 #include <boost/algorithm/string.hpp>
00049 
00050 namespace RTT
00051 {
00052     using namespace std;
00053     using namespace detail;
00054 
00055     namespace {
00056         boost::shared_ptr<TypeInfoRepository> typerepos;
00057     }
00058 
00059     TypeInfoRepository::TypeInfoRepository()
00060     {
00061     }
00062 
00063     boost::shared_ptr<TypeInfoRepository> TypeInfoRepository::Instance()
00064     {
00065         if ( typerepos )
00066             return typerepos;
00067         typerepos.reset( new TypeInfoRepository() );
00068 
00069         return typerepos;
00070     }
00071 
00072     TypeInfo* TypeInfoRepository::type( const std::string& name ) const
00073     {
00074         map_t::const_iterator i = data.find( name );
00075         if ( i == data.end() ) {
00076             // try alternate name replace / with dots:
00077             string tkname = "/" + boost::replace_all_copy(boost::replace_all_copy(name, string("."), "/"), "<","</");
00078             i = data.find( tkname );
00079             if ( i == data.end())
00080                 return 0;
00081         }
00082         // found
00083         return i->second;
00084     }
00085 
00086     TypeInfoRepository::~TypeInfoRepository()
00087     {
00088         // because of aliases, we only want unique pointers:
00089         vector<TypeInfo*> todelete = values(data);
00090         sort(todelete.begin(), todelete.end());
00091         vector<TypeInfo*>::iterator begin, last = unique( todelete.begin(), todelete.end() );
00092         begin = todelete.begin();
00093         for( ; begin != last; ++begin )
00094             delete *begin;
00095         delete DataSourceTypeInfo<UnknownType>::TypeInfoObject;
00096         DataSourceTypeInfo<UnknownType>::TypeInfoObject = 0;
00097     }
00098 
00099     TypeInfo* TypeInfoRepository::getTypeById(TypeInfo::TypeId type_id) const {
00100       if (!type_id)
00101           return 0;
00102       // Ask each type for its type id name.
00103       map_t::const_iterator i = data.begin();
00104       for (; i != data.end(); ++i){
00105         if (i->second->getTypeId() && *(i->second->getTypeId()) == *type_id)
00106           return i->second;
00107       }
00108       return 0;
00109     }
00110 
00111     TypeInfo* TypeInfoRepository::getTypeById(const char * type_id_name) const {
00112       // Ask each type for its type id name.
00113       map_t::const_iterator i = data.begin();
00114       for (; i != data.end(); ++i){
00115         if (i->second->getTypeId() && i->second->getTypeId()->name() == type_id_name)
00116           return i->second;
00117       }
00118       return 0;
00119     }
00120 
00121     bool TypeInfoRepository::addType(TypeInfo* t)
00122     {
00123         std::string tname = t->getTypeName();
00124         // keep track of this type:
00125         if ( !t->installTypeInfoObject() ) {
00126             // log reason why in installTypeInfoObject().
00127             delete t;
00128             return false;
00129         }
00130         // keep track of this type:
00131         data[ tname ] = t;
00132 
00133         log(Debug) << "Registered Type '"<<tname <<"' to the Orocos Type System."<<Logger::endl;
00134         for(Transports::iterator it = transports.begin(); it != transports.end(); ++it)
00135             if ( (*it)->registerTransport( tname, t) )
00136                 log(Info) << "Registered new '"<< (*it)->getTransportName()<<"' transport for " << tname <<endlog();
00137         return true;
00138     }
00139 
00140     bool TypeInfoRepository::aliasType(const string& alias, TypeInfo* source)
00141     {
00142         if (source) {
00143             if (data.count(alias) && data[alias] != source)
00144                 delete data[alias];
00145             data[alias] = source;
00146         } else {
00147             log(Error) << "Could not alias type name "<< alias <<" with (null) type info object."<<endlog();
00148             return false;
00149         }
00150         return true;
00151     }
00152 
00153     std::vector<std::string> TypeInfoRepository::getTypes() const
00154     {
00155         return keys( data );
00156     }
00157 
00158     string TypeInfoRepository::toDot( const string& type ) const
00159     {
00160         if (type.empty())
00161             return type;
00162         // try alternate name replace / with dots:
00163         string dotname = boost::replace_all_copy(boost::replace_all_copy(type, string("/"), "."), "<.","<");
00164         if ( dotname[0] == '.')
00165             dotname = dotname.substr(1);
00166         return dotname;
00167     }
00168 
00169     std::vector<std::string> TypeInfoRepository::getDottedTypes() const
00170     {
00171         vector<string> result = keys( data );
00172         for( vector<string>::iterator it = result.begin(); it != result.end(); ++it)
00173             *it = toDot(*it);
00174         return result;
00175     }
00176 
00177     void TypeInfoRepository::registerTransport( TransportPlugin* tr )
00178     {
00179         transports.reserve( transports.size() + 1 );
00180         transports.push_back( tr );
00181         // inform transport of existing types.
00182         map_t::const_iterator i = data.begin();
00183         for( ; i != data.end(); ++i )
00184             if ( tr->registerTransport( i->first , i->second ) )
00185                 log(Info) << "Registered new '"<< tr->getTransportName()<<"' transport for " << i->first <<endlog();
00186         // give chance to register fallback protocol:
00187         if ( tr->registerTransport("unknown_t", DataSourceTypeInfo<UnknownType>::getTypeInfo() ) == false )
00188         log(Debug) << "Transport " << tr->getTransportName() << " did not install a fallback handler for 'unknown_t'." <<endlog();
00189     }
00190 
00191     void TypeInfoRepository::logTypeInfo() const
00192     {
00193         // dump the names of all known types
00194         log(Debug) << "Types known to the Orocos Type System."<<Logger::endl;
00195         for(map_t::const_iterator it = data.begin(); it != data.end(); ++it)
00196         {
00197             std::vector<int>    transports;
00198             transports = it->second->getTransportNames();
00199             log(Debug) << "-- " << it->first
00200                           << " (" << (*it).second->getTypeName() << ") protocols [";
00201             for (std::vector<int>::const_iterator   iter=transports.begin();
00202                  iter != transports.end();
00203                  ++iter)
00204             {
00205                 Logger::log() << *iter;
00206             }
00207             Logger::log() << "]" << Logger::endl;
00208         }
00209         // dump the names of all known transports
00210         log(Debug) << "Transports known to the Orocos Type System."<<Logger::endl;
00211         for(Transports::const_iterator it = transports.begin(); it != transports.end(); ++it)
00212         {
00213             log(Debug) << "-- " << (*it)->getTransportName() << Logger::endl;
00214         }
00215     }
00216 
00217 
00218 }