All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
objectfactory.h
1 /* Copyright (C) 2004-2010 MBSim Development Team
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16  *
17  * Contact: friedrich.at.gc@googlemail.com
18  */
19 
20 #ifndef _MBSIM_OBJECTFACTORY_H_
21 #define _MBSIM_OBJECTFACTORY_H_
22 
23 #include <vector>
24 #include <stdexcept>
25 #include <typeinfo>
26 #ifdef HAVE_BOOST_TYPE_TRAITS_HPP
27 # include <boost/static_assert.hpp>
28 # include <boost/type_traits.hpp>
29 #endif
30 #include "mbsim/utils/utils.h"
31 #include <mbsim/mbsim_event.h>
32 #include <mbxmlutilshelper/utils.h>
33 #include "fmatvec/atom.h"
34 #ifdef HAVE_BOOST_CORE_DEMANGLE_HPP // not available for older boost versions
35 # include <boost/core/demangle.hpp>
36 #else
37 namespace boost {
38  namespace core {
39  inline std::string demangle(const std::string &name) {
40  return name;
41  }
42  }
43 }
44 #endif
45 
46 #define COMMA ,
47 
48 namespace MBSim {
49 
50 /* A tree of DOMEvalException's which store the tree of failed objects
51  * creations of the object factory */
52 class DOMEvalExceptionStack : public MBXMLUtils::DOMEvalException {
53  public:
54  DOMEvalExceptionStack(const xercesc::DOMElement *element) : MBXMLUtils::DOMEvalException("", element) {}
55  DOMEvalExceptionStack(const DOMEvalExceptionStack &src) : MBXMLUtils::DOMEvalException(src), exVec(src.exVec) {}
56  ~DOMEvalExceptionStack() throw() {}
57  void add(const std::string &type, const boost::shared_ptr<MBXMLUtils::DOMEvalException> &ex);
58  const char* what() const throw();
59  std::vector<std::pair<std::string, boost::shared_ptr<MBXMLUtils::DOMEvalException> > > &getExceptionVector();
60  protected:
61  std::vector<std::pair<std::string, boost::shared_ptr<MBXMLUtils::DOMEvalException> > > exVec;
62  mutable std::string whatStr;
63  void generateWhat(std::stringstream &str, const std::string &indent) const;
64 };
65 
66 /* Just to distinguish a wrong type (not castable) error of the object factory
67  * from others */
68 class DOMEvalExceptionWrongType : public MBXMLUtils::DOMEvalException {
69  public:
70  DOMEvalExceptionWrongType(const std::string &type, const xercesc::DOMElement *element) :
71  MBXMLUtils::DOMEvalException(type, element) {}
72  DOMEvalExceptionWrongType(const DOMEvalExceptionWrongType &src) : MBXMLUtils::DOMEvalException(src) {}
73  ~DOMEvalExceptionWrongType() throw() {}
74 };
75 
80 
81  public:
82 
86  template<class CreateType>
87  static void registerXMLName(const MBXMLUtils::FQN &name) {
88  registerXMLName(name, &allocate<CreateType>, &deallocate);
89  }
90 
94  template<class CreateType>
95  static void registerXMLNameAsSingleton(const MBXMLUtils::FQN &name) {
96  registerXMLName(name, &getSingleton<CreateType>, &deallocateSingleton);
97  }
98 
102  template<class CreateType>
103  static void deregisterXMLName(const MBXMLUtils::FQN &name) {
104  deregisterXMLName(name, &allocate<CreateType>);
105  }
106 
110  template<class CreateType>
111  static void deregisterXMLNameAsSingleton(const MBXMLUtils::FQN &name) {
112  deregisterXMLName(name, &getSingleton<CreateType>);
113  }
114 
118  template<class ContainerType>
119  static ContainerType* createAndInit(const xercesc::DOMElement *element) {
120 #ifdef HAVE_BOOST_TYPE_TRAITS_HPP
121  // just check if ContainerType is derived from fmatvec::Atom if not throw a compile error if boost is avaliable
122  // if boost is not avaliable a runtime error will occure later. (so it does not care if boost is not available)
123  BOOST_STATIC_ASSERT_MSG((boost::is_convertible<ContainerType*, fmatvec::Atom*>::value),
124  "In MBSim::ObjectFactory::create<ContainerType>(...) ContainerType must be derived from fmatvec::Atom.");
125 #endif
126  // throw error if NULL is supplied as element
127  if(element==NULL)
128  throw MBSimError("Internal error: NULL argument specified.");
129  // get all allocate functions for the given name
130  MBXMLUtils::FQN fqn=MBXMLUtils::E(element)->getTagName();
131  NameMapIt nameIt=instance().registeredType.find(fqn);
132  if(nameIt==instance().registeredType.end())
133  throw MBXMLUtils::DOMEvalException("Internal error: No objects of name {"+fqn.first+"}"+fqn.second+" registred", element);
134  DOMEvalExceptionStack allErrors(static_cast<xercesc::DOMElement*>(element->getParentNode()));
135  // try to create and init a object which each of the allocate function
136  for(AllocDeallocVectorIt allocDeallocIt=nameIt->second.begin(); allocDeallocIt!=nameIt->second.end(); ++allocDeallocIt) {
137  // create element
138  fmatvec::Atom *ele=allocDeallocIt->first();
139  // try to cast the element to ContainerType
140  ContainerType *ret=dynamic_cast<ContainerType*>(ele);
141  if(!ret) {
142  // cast not possible -> deallocate again and try next
143  allErrors.add(boost::core::demangle(typeid(*ele).name()),
144  boost::make_shared<DOMEvalExceptionWrongType>(
145  boost::core::demangle(typeid(ContainerType).name()), element));
146  allocDeallocIt->second(ele);
147  continue;
148  }
149  try {
150  ret->initializeUsingXML(const_cast<xercesc::DOMElement*>(element));
151  return ret;
152  }
153  catch(DOMEvalExceptionStack &ex) {
154  allErrors.add(boost::core::demangle(typeid(*ele).name()), boost::make_shared<DOMEvalExceptionStack>(ex));
155  }
156  catch(MBXMLUtils::DOMEvalException &ex) {
157  allErrors.add(boost::core::demangle(typeid(*ele).name()), boost::make_shared<MBXMLUtils::DOMEvalException>(ex));
158  }
159  catch(std::exception &ex) { // handles also MBSimError
160  allErrors.add(boost::core::demangle(typeid(*ele).name()),
161  boost::make_shared<MBXMLUtils::DOMEvalException>(ex.what(), element));
162  }
163  catch(...) {
164  allErrors.add(boost::core::demangle(typeid(*ele).name()),
165  boost::make_shared<MBXMLUtils::DOMEvalException>("Unknwon exception", element));
166  }
167  allocDeallocIt->second(ele);
168  }
169  // if all failed -> return errors of all trys
170  throw allErrors;
171  }
172 
173  private:
174 
175  // a pointer to a function allocating an object
176  typedef fmatvec::Atom* (*AllocateFkt)();
177  // a pointer to a function deallocating an object
178  typedef void (*DeallocateFkt)(fmatvec::Atom *obj);
179 
180  // convinence typedefs
181  typedef std::vector<std::pair<AllocateFkt, DeallocateFkt> > AllocDeallocVector;
182  typedef AllocDeallocVector::iterator AllocDeallocVectorIt;
183  typedef std::map<MBXMLUtils::FQN, AllocDeallocVector> NameMap;
184  typedef NameMap::iterator NameMapIt;
185 
186  // private ctor
187  ObjectFactory() {}
188 
189  static void registerXMLName(const MBXMLUtils::FQN &name, AllocateFkt alloc, DeallocateFkt dealloc);
190 
191  static void deregisterXMLName(const MBXMLUtils::FQN &name, AllocateFkt alloc);
192 
193  // create an singleton instance of the object factory.
194  // only declaration here and defition and explicit instantation for all fmatvec::Atom in objectfactory.cc (required for Windows)
195  static ObjectFactory& instance();
196 
197  // a vector of all registered types
198  NameMap registeredType;
199 
200  // a wrapper to allocate an object of type CreateType
201  template<class CreateType>
202  static fmatvec::Atom* allocate() {
203  return new CreateType;
204  }
205 
206  // a wrapper to deallocate an object created by allocate
207  static void deallocate(fmatvec::Atom *obj) {
208  delete obj;
209  }
210 
211  // a wrapper to get an singleton object of type CreateType (Must have the same signature as allocate()
212  template<class CreateType>
213  static fmatvec::Atom* getSingleton() {
214  return CreateType::getInstance();
215  }
216 
217  // a wrapper to "deallocate" an singleton object (Must have the same signature as deallocate()
218  static void deallocateSingleton(fmatvec::Atom *obj) {
219  // just do nothing for singletons
220  }
221 
222 };
223 
227 template<class CreateType>
229 
230  public:
231 
233  ObjectFactoryRegisterXMLNameHelper(const MBXMLUtils::FQN &name_) : name(name_) {
234  ObjectFactory::template registerXMLName<CreateType>(name);
235  };
236 
239  ObjectFactory::template deregisterXMLName<CreateType>(name);
240  };
241 
242  private:
243  MBXMLUtils::FQN name;
244 
245 };
246 
250 template<class CreateType>
252 
253  public:
254 
256  ObjectFactoryRegisterXMLNameHelperAsSingleton(const MBXMLUtils::FQN &name_) : name(name_) {
257  ObjectFactory::template registerXMLNameAsSingleton<CreateType>(name);
258  };
259 
262  ObjectFactory::template deregisterXMLNameAsSingleton<CreateType>(name);
263  };
264 
265  private:
266  MBXMLUtils::FQN name;
267 
268 };
269 
270 }
271 
272 #define MBSIM_OBJECTFACTORY_CONCAT1(X, Y) X##Y
273 #define MBSIM_OBJECTFACTORY_CONCAT(X, Y) MBSIM_OBJECTFACTORY_CONCAT1(X, Y)
274 #define MBSIM_OBJECTFACTORY_APPENDLINE(X) MBSIM_OBJECTFACTORY_CONCAT(X, __LINE__)
275 
279 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAME(ThisType, name) \
280  static MBSim::ObjectFactoryRegisterXMLNameHelper<ThisType> \
281  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(name);
282 
286 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAMEASSINGLETON(ThisType, name) \
287  static MBSim::ObjectFactoryRegisterXMLNameHelperAsSingleton<ThisType> \
288  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariableAsSingleTon)(name);
289 
292 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAME_AND_INSTANTIATE(ThisType, name) \
293  template class ThisType; \
294  static MBSim::ObjectFactoryRegisterXMLNameHelper<ThisType> \
295  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(name);
296 
299 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAMEASSINGLETON_AND_INSTANTIATE(ThisType, name) \
300  template class ThisType; \
301  static MBSim::ObjectFactoryRegisterXMLNameHelperAsSingleton<ThisType> \
302  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariableAsSingleTon)(name);
303 
304 #endif
static void deregisterXMLNameAsSingleton(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:111
~ObjectFactoryRegisterXMLNameHelper()
Definition: objectfactory.h:238
Definition: objectfactory.h:228
Definition: objectfactory.h:52
static void registerXMLNameAsSingleton(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:95
ObjectFactoryRegisterXMLNameHelper(const MBXMLUtils::FQN &name_)
Definition: objectfactory.h:233
~ObjectFactoryRegisterXMLNameHelperAsSingleton()
Definition: objectfactory.h:261
static void registerXMLName(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:87
ObjectFactoryRegisterXMLNameHelperAsSingleton(const MBXMLUtils::FQN &name_)
Definition: objectfactory.h:256
Definition: objectfactory.h:79
Definition: objectfactory.h:68
static ContainerType * createAndInit(const xercesc::DOMElement *element)
Definition: objectfactory.h:119
static void deregisterXMLName(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:103
basic error class for mbsim
Definition: mbsim_event.h:38

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML