RSB  0.9.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Repository.h
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of the RSB project.
4  *
5  * Copyright (C) 2011 by Johannes Wienke <jwienke at techfak dot uni-bielefeld dot de>
6  *
7  * This file may be licensed under the terms of the
8  * GNU Lesser General Public License Version 3 (the ``LGPL''),
9  * or (at your option) any later version.
10  *
11  * Software distributed under the License is distributed
12  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
13  * express or implied. See the LGPL for the specific language
14  * governing rights and limitations.
15  *
16  * You should have received a copy of the LGPL along with this
17  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
18  * or write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * The development of this software was supported by:
22  * CoR-Lab, Research Institute for Cognition and Robotics
23  * Bielefeld University
24  *
25  * ============================================================ */
26 
27 #pragma once
28 
29 #include <string>
30 #include <stdexcept>
31 #include <set>
32 #include <iomanip>
33 
34 #include <boost/format.hpp>
35 
36 #include <rsc/runtime/Printable.h>
37 #include <rsc/runtime/TypeStringTools.h>
38 #include <rsc/runtime/NoSuchObject.h>
39 #include <rsc/logging/Logger.h>
40 
41 #include "Converter.h"
44 #include "rsb/rsbexports.h"
45 
46 namespace rsb {
47 namespace converter {
48 
58 template<class WireType>
59 class Repository: public rsc::runtime::Printable {
60 public:
62 
64  typedef std::pair<std::string, std::string> ConverterSignature;
65 
66  typedef std::map<std::string, std::string> ConverterSelectionMap;
67 
69  logger(rsc::logging::Logger::getLogger("rsb.converter.Repository")) {
70  }
71 
73  const ConverterSelectionMap& selection =
74  ConverterSelectionMap()) const {
75  RSCDEBUG(this->logger, "Building unambiguous map for serialization with selection "
76  << selection);
77 
78  boost::shared_ptr< UnambiguousConverterMap<WireType> >
80  for (typename ConverterMap::const_iterator it =
81  this->converters.begin(); it != this->converters.end(); ++it) {
82  std::string wireSchema = it->first.first;
83  std::string dataType = it->first.second;
84  RSCTRACE(this->logger, "Considering converter " << it->second);
85 
86  // The data-type is not mentioned in the explicit
87  // selection. Try to add the converter. This may throw in
88  // case of ambiguity.
89  if (selection.find(dataType) == selection.end()) {
90  RSCTRACE(this->logger, "No explicit selection for data-type "
91  << dataType);
92  try {
93  result->addConverter(dataType, it->second);
94  } catch (const std::invalid_argument& e) {
95  std::set<std::string> wireSchemas;
96  for (typename ConverterMap::const_iterator it_ =
97  this->converters.begin();
98  it_ != this->converters.end(); ++it_) {
99  if (dataType == it_->first.second)
100  wireSchemas.insert(it_->first.first);
101  }
102  throw std::runtime_error(
103  boost::str(
104  boost::format(
105  "Ambiguous converter set for wire-type `%1%' and data-type `%2%': candidate wire-schemas are %3%; hint: add a configuration option `transport.<name>.converter.cpp.<one of %3%> = %2%' to resolve the ambiguity (%4%).")
106  % rsc::runtime::typeName<WireType>()
107  % dataType % wireSchemas % e.what()));
108  }
109  }
110  // There is an entry for data-type in the explicit
111  // selection. Add the converter if the wire-schema matches.
112  else if (wireSchema == selection.find(dataType)->second) {
113  RSCDEBUG(this->logger, "Explicit selection "
114  << *selection.find(dataType)
115  << " chooses data wire-schema " << wireSchema
116  << "; adding the converter");
117  result->addConverter(dataType, it->second);
118  } else {
119  RSCDEBUG(this->logger, "Explicit selection "
120  << *selection.find(dataType)
121  << " chooses wire-schema "
122  << selection.find(dataType)->second
123  << " (not " << wireSchema
124  << "); not adding the converter");
125  }
126  }
127  return result;
128  }
129 
131  const ConverterSelectionMap& selection =
132  ConverterSelectionMap()) const {
133  RSCDEBUG(this->logger, "Building unambiguous map for deserialization with selection "
134  << selection);
135 
136  boost::shared_ptr< UnambiguousConverterMap<WireType> >
137  result(new UnambiguousConverterMap<WireType>());
138  for (typename ConverterMap::const_iterator it =
139  this->converters.begin(); it != this->converters.end(); ++it) {
140  std::string wireSchema = it->first.first;
141  std::string dataType = it->first.second;
142  RSCTRACE(this->logger, "Considering converter " << it->second);
143 
144  // The wire-schema is not mentioned in the explicit
145  // selection. Try to add the converter. This may throw in
146  // case of ambiguity.
147  if (selection.find(wireSchema) == selection.end()) {
148  RSCTRACE(this->logger, "No explicit selection for wire-schema "
149  << wireSchema);
150  try {
151  result->addConverter(wireSchema, it->second);
152  } catch (const std::invalid_argument& e) {
153  std::set<std::string> dataTypes;
154  for (typename ConverterMap::const_iterator it_ =
155  this->converters.begin();
156  it_ != this->converters.end(); ++it_) {
157  if (wireSchema == it_->first.first)
158  dataTypes.insert(it_->first.second);
159  }
160  throw std::runtime_error(
161  boost::str(
162  boost::format(
163  "Ambiguous converter set for wire-type `%1%' and wire-schema `%2%': candidate data-types are %3%; hint: add a configuration option `transport.<name>.converter.cpp.\"%2%\" = <one of %3%>' to resolve the ambiguity (%4%).")
164  % rsc::runtime::typeName<WireType>()
165  % wireSchema % dataTypes % e.what()));
166  }
167  }
168  // There is an entry for wire-schema in the explicit
169  // selection. Add the converter if the data-type matches.
170  else if (dataType == selection.find(wireSchema)->second) {
171  RSCDEBUG(this->logger, "Explicit selection "
172  << *selection.find(wireSchema)
173  << " chooses data-type " << dataType
174  << "; adding the converter");
175  result->addConverter(wireSchema, it->second);
176  } else {
177  RSCDEBUG(this->logger, "Explicit selection "
178  << *selection.find(wireSchema)
179  << " chooses data-type "
180  << selection.find(wireSchema)->second
181  << " (not " << dataType
182  << "); not adding the converter");
183  }
184  }
185  return result;
186  }
187 
199  void registerConverter(ConverterPtr converter, bool replace = false) {
200  RSCINFO(this->logger, "Registering converter " << converter);
201 
202  std::string wireSchema = converter->getWireSchema();
203  std::string dataType = converter->getDataType();
204  if (this->converters.find(std::make_pair(wireSchema, dataType))
205  != this->converters.end()
206  && !replace) {
207  // TODO use RSB exception; but do we have one for invalid argument?
208  throw std::invalid_argument(
209  boost::str(
210  boost::format(
211  "There already is a converter for wire-schema `%1%' and data-type `%2%'")
212  % wireSchema % dataType));
213  }
214  this->converters[std::make_pair(wireSchema, dataType)] = converter;
215  }
216 
217  ConverterPtr getConverter(const std::string& wireSchema,
218  const std::string& dataType) const {
219  typename ConverterMap::const_iterator it = this->converters.find(
220  std::make_pair(wireSchema, dataType));
221  if (it == this->converters.end()) {
222  throw rsc::runtime::NoSuchObject(
223  boost::str(
224  boost::format(
225  "Could not find a converter for wire-schema `%1%' and data-type `%2%'")
226  % wireSchema % dataType));
227  }
228  return it->second;
229  }
230 
231  ConverterPtr getConverter(const ConverterSignature& signature) const {
232  return getConverter(signature.first, signature.second);
233  }
234 
235  void clear() {
236  this->converters.clear();
237  }
238 
239  typedef boost::shared_ptr<Repository<WireType> > Ptr;
240 
241 private:
242  typedef std::map<ConverterSignature, ConverterPtr> ConverterMap;
243 
244  rsc::logging::LoggerPtr logger;
246 
247  std::string getClassName() const {
248  return "Repository<" + rsc::runtime::typeName<WireType>() + ">";
249  }
250 
251  void printContents(std::ostream& stream) const {
252  stream << std::endl;
253  for (typename ConverterMap::const_iterator it =
254  this->converters.begin(); it != this->converters.end(); ++it) {
255  stream << "\t" << std::setw(16) << std::left << it->first.first
256  << " <-> " << std::setw(16) << std::left << it->first.second
257  << std::endl
258  << "\t\t" << *it->second << std::endl;
259  }
260  }
261 };
262 
263 
286 
293 class RSB_EXPORT RepositoryCreater {
294 public:
295  virtual ~RepositoryCreater();
296 
302  virtual void* create() = 0;
303 };
304 
315 RSB_EXPORT void* converterRepositoryByName(const std::string &wireTypeName,
316  RepositoryCreater &creater);
317 
325 template<class WireType>
327 public:
329  }
330  void* create() {
331  return new Repository<WireType> ;
332  }
333 };
334 
336 
344 template<class WireType>
347  return typename Repository<WireType>::Ptr(
349  rsc::runtime::typeName<WireType>(), creater),
350  rsc::misc::NullDeleter());
351 }
352 
358 DEPRECATED(RSB_EXPORT Repository<std::string>::Ptr stringConverterRepository());
359 
360 }
361 }
Converter< WireType >::Ptr ConverterPtr
Definition: Repository.h:61
void printContents(std::ostream &stream) const
Definition: Repository.h:251
A RepositoryCreate which can be statically typed using a template argument for the desired wire type...
Definition: Repository.h:326
std::map< std::string, std::string > ConverterSelectionMap
Definition: Repository.h:66
Repository< string >::Ptr stringConverterRepository()
Definition: Repository.cpp:50
boost::shared_ptr< Repository< WireType > > Ptr
Definition: Repository.h:239
std::pair< std::string, std::string > ConverterSignature
WireSchema and DataType.
Definition: Repository.h:64
ConverterPtr getConverter(const std::string &wireSchema, const std::string &dataType) const
Definition: Repository.h:217
ConverterSelectionStrategy< WireType >::Ptr getConvertersForDeserialization(const ConverterSelectionMap &selection=ConverterSelectionMap()) const
Definition: Repository.h:130
Repository< WireType >::Ptr converterRepository()
Returns a Repository of Converter instances specifically for the given wire type. ...
Definition: Repository.h:345
rsc::logging::LoggerPtr logger
Definition: Repository.h:244
std::string getClassName() const
Definition: Repository.h:247
ConverterPtr getConverter(const ConverterSignature &signature) const
Definition: Repository.h:231
An internal factory object to create typed converter repositories.
Definition: Repository.h:293
Objects this class store mappings of one of the followings forms.
void registerConverter(ConverterPtr converter, bool replace=false)
Registers converter in the collection.
Definition: Repository.h:199
boost::shared_ptr< Converter< WireType > > Ptr
Definition: Converter.h:101
boost::shared_ptr< ConverterSelectionStrategy< WireType > > Ptr
DEPRECATED(RSB_EXPORT Repository< std::string >::Ptr stringConverterRepository())
Maintains a collection of converters for a specific wire format.
Definition: Repository.h:59
void * create()
Factory method to create a new Repository.
Definition: Repository.h:330
void * converterRepositoryByName(const string &wireTypeName, RepositoryCreater &creater)
Returns a repository for a converters of a certain wire type by a look up based on a name for the wir...
Definition: Repository.cpp:41
std::map< ConverterSignature, ConverterPtr > ConverterMap
Definition: Repository.h:242
ConverterSelectionStrategy< WireType >::Ptr getConvertersForSerialization(const ConverterSelectionMap &selection=ConverterSelectionMap()) const
Definition: Repository.h:72