Orocos Real-Time Toolkit  2.6.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         MutexLock lock(type_lock);
00075         map_t::const_iterator i = data.find( name );
00076         if ( i == data.end() ) {
00077             // try alternate name replace / with dots:
00078             string tkname = "/" + boost::replace_all_copy(boost::replace_all_copy(name, string("."), "/"), "<","</");
00079             i = data.find( tkname );
00080             if ( i == data.end())
00081                 return 0;
00082         }
00083         // found
00084         return i->second;
00085     }
00086 
00087     TypeInfoRepository::~TypeInfoRepository()
00088     {
00089         // because of aliases, we only want unique pointers:
00090         vector<TypeInfo*> todelete = values(data);
00091         sort(todelete.begin(), todelete.end());
00092         vector<TypeInfo*>::iterator begin, last = unique( todelete.begin(), todelete.end() );
00093         begin = todelete.begin();
00094         for( ; begin != last; ++begin )
00095             delete *begin;
00096         delete DataSourceTypeInfo<UnknownType>::TypeInfoObject;
00097         DataSourceTypeInfo<UnknownType>::TypeInfoObject = 0;
00098     }
00099 
00100     TypeInfo* TypeInfoRepository::getTypeById(TypeInfo::TypeId type_id) const {
00101       if (!type_id)
00102           return 0;
00103       MutexLock lock(type_lock);
00104       // Ask each type for its type id name.
00105       map_t::const_iterator i = data.begin();
00106       for (; i != data.end(); ++i){
00107         if (i->second->getTypeId() && *(i->second->getTypeId()) == *type_id)
00108           return i->second;
00109       }
00110       return 0;
00111     }
00112 
00113     TypeInfo* TypeInfoRepository::getTypeById(const char * type_id_name) const {
00114       // Ask each type for its type id name.
00115       MutexLock lock(type_lock);
00116       map_t::const_iterator i = data.begin();
00117       for (; i != data.end(); ++i){
00118         if (i->second->getTypeId() && i->second->getTypeId()->name() == type_id_name)
00119           return i->second;
00120       }
00121       return 0;
00122     }
00123 
00124     bool TypeInfoRepository::addType(TypeInfo* t)
00125     {
00126         if (!t)
00127             return false;
00128         MutexLock lock(type_lock);
00129         if (data.count(t->getTypeName() ) ) {
00130             log(Error) << "Can't register a new TypeInfo object for '"<<t->getTypeName() << "': one already exists."<<endlog();
00131             return false;
00132         }
00133 
00134         data[t->getTypeName()] = t;
00135         return true;
00136     }
00137 
00138     bool TypeInfoRepository::addType(TypeInfoGenerator* t)
00139     {
00140         if (!t)
00141             return false;
00142         std::string tname = t->getTypeName();
00143         TypeInfo* ti = t->getTypeInfoObject();
00144 
00145         {
00146             MutexLock lock(type_lock);
00147             if (ti && data.count(tname) && data[tname] != ti ) {
00148                 log(Error) << "Refusing to add type information for '" << tname << "': the name is already in use by another type."<<endlog();
00149                 return false;
00150             }
00151         }
00152         // Check for first registration, or alias:
00153         if ( ti == 0 )
00154             ti = new TypeInfo(tname);
00155         else
00156             ti->addAlias(tname);
00157 
00158         if ( t->installTypeInfoObject( ti ) ) {
00159             delete t;
00160         }
00161         MutexLock lock(type_lock);
00162         // keep track of this type:
00163         data[ tname ] = ti;
00164 
00165         log(Debug) << "Registered Type '"<<tname <<"' to the Orocos Type System."<<Logger::endl;
00166         for(Transports::iterator it = transports.begin(); it != transports.end(); ++it)
00167             if ( (*it)->registerTransport( tname, ti) )
00168                 log(Info) << "Registered new '"<< (*it)->getTransportName()<<"' transport for " << tname <<endlog();
00169         return true;
00170     }
00171 
00172     std::vector<std::string> TypeInfoRepository::getTypes() const
00173     {
00174         MutexLock lock(type_lock);
00175         return keys( data );
00176     }
00177 
00178     string TypeInfoRepository::toDot( const string& type ) const
00179     {
00180         if (type.empty())
00181             return type;
00182         // try alternate name replace / with dots:
00183         string dotname = boost::replace_all_copy(boost::replace_all_copy(type, string("/"), "."), "<.","<");
00184         if ( dotname[0] == '.')
00185             dotname = dotname.substr(1);
00186         return dotname;
00187     }
00188 
00189     std::vector<std::string> TypeInfoRepository::getDottedTypes() const
00190     {
00191         MutexLock lock(type_lock);
00192         vector<string> result = keys( data );
00193         for( vector<string>::iterator it = result.begin(); it != result.end(); ++it)
00194             *it = toDot(*it);
00195         return result;
00196     }
00197 
00198     void TypeInfoRepository::registerTransport( TransportPlugin* tr )
00199     {
00200         MutexLock lock(type_lock);
00201         transports.reserve( transports.size() + 1 );
00202         transports.push_back( tr );
00203         // inform transport of existing types.
00204         map_t::const_iterator i = data.begin();
00205         for( ; i != data.end(); ++i )
00206             if ( tr->registerTransport( i->first , i->second ) )
00207                 log(Info) << "Registered new '"<< tr->getTransportName()<<"' transport for " << i->first <<endlog();
00208         // give chance to register fallback protocol:
00209         if ( tr->registerTransport("unknown_t", DataSourceTypeInfo<UnknownType>::getTypeInfo() ) == false )
00210             log(Debug) << "Transport " << tr->getTransportName() << " did not install a fallback handler for 'unknown_t'." <<endlog();
00211     }
00212 
00213     void TypeInfoRepository::logTypeInfo() const
00214     {
00215         // dump the names of all known types
00216         log(Debug) << "Types known to the Orocos Type System."<<Logger::endl;
00217         MutexLock lock(type_lock);
00218         for(map_t::const_iterator it = data.begin(); it != data.end(); ++it)
00219         {
00220             std::vector<int>    transports;
00221             transports = it->second->getTransportNames();
00222             log(Debug) << "-- " << it->first
00223                           << " (" << (*it).second->getTypeName() << ") protocols [";
00224             for (std::vector<int>::const_iterator   iter=transports.begin();
00225                  iter != transports.end();
00226                  ++iter)
00227             {
00228                 Logger::log() << *iter;
00229             }
00230             Logger::log() << "]" << Logger::endl;
00231         }
00232         // dump the names of all known transports
00233         log(Debug) << "Transports known to the Orocos Type System."<<Logger::endl;
00234         for(Transports::const_iterator it = transports.begin(); it != transports.end(); ++it)
00235         {
00236             log(Debug) << "-- " << (*it)->getTransportName() << Logger::endl;
00237         }
00238     }
00239 
00240 
00241 }