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 
35 #define COMMA ,
36 
37 namespace MBSim {
38 
39 /* A tree of DOMEvalException's which store the tree of failed objects
40  * creations of the object factory */
41 class DOMEvalExceptionStack : public MBXMLUtils::DOMEvalException {
42  public:
43  DOMEvalExceptionStack(const xercesc::DOMElement *element) : MBXMLUtils::DOMEvalException("", element) {}
44  DOMEvalExceptionStack(const DOMEvalExceptionStack &src) : MBXMLUtils::DOMEvalException(src), exVec(src.exVec) {}
45  ~DOMEvalExceptionStack() throw() {}
46  void add(const std::string &type, const boost::shared_ptr<MBXMLUtils::DOMEvalException> &ex);
47  const char* what() const throw();
48  std::vector<std::pair<std::string, boost::shared_ptr<MBXMLUtils::DOMEvalException> > > &getExceptionVector();
49  protected:
50  std::vector<std::pair<std::string, boost::shared_ptr<MBXMLUtils::DOMEvalException> > > exVec;
51  mutable std::string whatStr;
52  void generateWhat(std::stringstream &str, const std::string &indent) const;
53 };
54 
55 /* Just to distinguish a wrong type (not castable) error of the object factory
56  * from others */
57 class DOMEvalExceptionWrongType : public MBXMLUtils::DOMEvalException {
58  public:
59  DOMEvalExceptionWrongType(const std::string &type, const xercesc::DOMElement *element) :
60  MBXMLUtils::DOMEvalException(type, element) {}
61  DOMEvalExceptionWrongType(const DOMEvalExceptionWrongType &src) : MBXMLUtils::DOMEvalException(src) {}
62  ~DOMEvalExceptionWrongType() throw() {}
63 };
64 
69 
70  public:
71 
75  template<class CreateType>
76  static void registerXMLName(const MBXMLUtils::FQN &name) {
77  registerXMLName(name, &allocate<CreateType>, &deallocate);
78  }
79 
83  template<class CreateType>
84  static void registerXMLNameAsSingleton(const MBXMLUtils::FQN &name) {
85  registerXMLName(name, &getSingleton<CreateType>, &deallocateSingleton);
86  }
87 
91  template<class CreateType>
92  static void deregisterXMLName(const MBXMLUtils::FQN &name) {
93  deregisterXMLName(name, &allocate<CreateType>);
94  }
95 
99  template<class CreateType>
100  static void deregisterXMLNameAsSingleton(const MBXMLUtils::FQN &name) {
101  deregisterXMLName(name, &getSingleton<CreateType>);
102  }
103 
107  template<class ContainerType>
108  static ContainerType* createAndInit(const xercesc::DOMElement *element) {
109 #ifdef HAVE_BOOST_TYPE_TRAITS_HPP
110  // just check if ContainerType is derived from fmatvec::Atom if not throw a compile error if boost is avaliable
111  // if boost is not avaliable a runtime error will occure later. (so it does not care if boost is not available)
112  BOOST_STATIC_ASSERT_MSG((boost::is_convertible<ContainerType*, fmatvec::Atom*>::value),
113  "In MBSim::ObjectFactory::create<ContainerType>(...) ContainerType must be derived from fmatvec::Atom.");
114 #endif
115  // throw error if NULL is supplied as element
116  if(element==NULL)
117  throw MBSimError("Internal error: NULL argument specified.");
118  // get all allocate functions for the given name
119  MBXMLUtils::FQN fqn=MBXMLUtils::E(element)->getTagName();
120  NameMapIt nameIt=instance().registeredType.find(fqn);
121  if(nameIt==instance().registeredType.end())
122  throw MBXMLUtils::DOMEvalException("Internal error: No objects of name {"+fqn.first+"}"+fqn.second+" registred", element);
123  DOMEvalExceptionStack allErrors(static_cast<xercesc::DOMElement*>(element->getParentNode()));
124  // try to create and init a object which each of the allocate function
125  for(AllocDeallocVectorIt allocDeallocIt=nameIt->second.begin(); allocDeallocIt!=nameIt->second.end(); ++allocDeallocIt) {
126  // create element
127  fmatvec::Atom *ele=allocDeallocIt->first();
128  // try to cast the element to ContainerType
129  ContainerType *ret=dynamic_cast<ContainerType*>(ele);
130  if(!ret) {
131  // cast not possible -> deallocate again and try next
132  allErrors.add(MBXMLUtils::demangleSymbolName(typeid(*ele).name()),
133  boost::make_shared<DOMEvalExceptionWrongType>(
134  MBXMLUtils::demangleSymbolName(typeid(ContainerType).name()), element));
135  allocDeallocIt->second(ele);
136  continue;
137  }
138  try {
139  ret->initializeUsingXML(const_cast<xercesc::DOMElement*>(element));
140  return ret;
141  }
142  catch(DOMEvalExceptionStack &ex) {
143  allErrors.add(MBXMLUtils::demangleSymbolName(typeid(*ele).name()), boost::make_shared<DOMEvalExceptionStack>(ex));
144  }
145  catch(MBXMLUtils::DOMEvalException &ex) {
146  allErrors.add(MBXMLUtils::demangleSymbolName(typeid(*ele).name()), boost::make_shared<MBXMLUtils::DOMEvalException>(ex));
147  }
148  catch(std::exception &ex) { // handles also MBSimError
149  allErrors.add(MBXMLUtils::demangleSymbolName(typeid(*ele).name()),
150  boost::make_shared<MBXMLUtils::DOMEvalException>(ex.what(), element));
151  }
152  catch(...) {
153  allErrors.add(MBXMLUtils::demangleSymbolName(typeid(*ele).name()),
154  boost::make_shared<MBXMLUtils::DOMEvalException>("Unknwon exception", element));
155  }
156  allocDeallocIt->second(ele);
157  }
158  // if all failed -> return errors of all trys
159  throw allErrors;
160  }
161 
162  private:
163 
164  // a pointer to a function allocating an object
165  typedef fmatvec::Atom* (*AllocateFkt)();
166  // a pointer to a function deallocating an object
167  typedef void (*DeallocateFkt)(fmatvec::Atom *obj);
168 
169  // convinence typedefs
170  typedef std::vector<std::pair<AllocateFkt, DeallocateFkt> > AllocDeallocVector;
171  typedef AllocDeallocVector::iterator AllocDeallocVectorIt;
172  typedef std::map<MBXMLUtils::FQN, AllocDeallocVector> NameMap;
173  typedef NameMap::iterator NameMapIt;
174 
175  // private ctor
176  ObjectFactory() {}
177 
178  static void registerXMLName(const MBXMLUtils::FQN &name, AllocateFkt alloc, DeallocateFkt dealloc);
179 
180  static void deregisterXMLName(const MBXMLUtils::FQN &name, AllocateFkt alloc);
181 
182  // create an singleton instance of the object factory.
183  // only declaration here and defition and explicit instantation for all fmatvec::Atom in objectfactory.cc (required for Windows)
184  static ObjectFactory& instance();
185 
186  // a vector of all registered types
187  NameMap registeredType;
188 
189  // a wrapper to allocate an object of type CreateType
190  template<class CreateType>
191  static fmatvec::Atom* allocate() {
192  return new CreateType;
193  }
194 
195  // a wrapper to deallocate an object created by allocate
196  static void deallocate(fmatvec::Atom *obj) {
197  delete obj;
198  }
199 
200  // a wrapper to get an singleton object of type CreateType (Must have the same signature as allocate()
201  template<class CreateType>
202  static fmatvec::Atom* getSingleton() {
203  return CreateType::getInstance();
204  }
205 
206  // a wrapper to "deallocate" an singleton object (Must have the same signature as deallocate()
207  static void deallocateSingleton(fmatvec::Atom *obj) {
208  // just do nothing for singletons
209  }
210 
211 };
212 
216 template<class CreateType>
218 
219  public:
220 
222  ObjectFactoryRegisterXMLNameHelper(const MBXMLUtils::FQN &name_) : name(name_) {
223  ObjectFactory::template registerXMLName<CreateType>(name);
224  };
225 
228  ObjectFactory::template deregisterXMLName<CreateType>(name);
229  };
230 
231  private:
232  MBXMLUtils::FQN name;
233 
234 };
235 
239 template<class CreateType>
241 
242  public:
243 
245  ObjectFactoryRegisterXMLNameHelperAsSingleton(const MBXMLUtils::FQN &name_) : name(name_) {
246  ObjectFactory::template registerXMLNameAsSingleton<CreateType>(name);
247  };
248 
251  ObjectFactory::template deregisterXMLNameAsSingleton<CreateType>(name);
252  };
253 
254  private:
255  MBXMLUtils::FQN name;
256 
257 };
258 
259 }
260 
261 #define MBSIM_OBJECTFACTORY_CONCAT1(X, Y) X##Y
262 #define MBSIM_OBJECTFACTORY_CONCAT(X, Y) MBSIM_OBJECTFACTORY_CONCAT1(X, Y)
263 #define MBSIM_OBJECTFACTORY_APPENDLINE(X) MBSIM_OBJECTFACTORY_CONCAT(X, __LINE__)
264 
268 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAME(ThisType, name) \
269  static MBSim::ObjectFactoryRegisterXMLNameHelper<ThisType> \
270  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(name);
271 
275 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAMEASSINGLETON(ThisType, name) \
276  static MBSim::ObjectFactoryRegisterXMLNameHelperAsSingleton<ThisType> \
277  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariableAsSingleTon)(name);
278 
281 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAME_AND_INSTANTIATE(ThisType, name) \
282  template class ThisType; \
283  static MBSim::ObjectFactoryRegisterXMLNameHelper<ThisType> \
284  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(name);
285 
288 #define MBSIM_OBJECTFACTORY_REGISTERXMLNAMEASSINGLETON_AND_INSTANTIATE(ThisType, name) \
289  template class ThisType; \
290  static MBSim::ObjectFactoryRegisterXMLNameHelperAsSingleton<ThisType> \
291  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariableAsSingleTon)(name);
292 
293 #endif
static void deregisterXMLNameAsSingleton(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:100
~ObjectFactoryRegisterXMLNameHelper()
Definition: objectfactory.h:227
Definition: objectfactory.h:217
Definition: objectfactory.h:41
static void registerXMLNameAsSingleton(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:84
ObjectFactoryRegisterXMLNameHelper(const MBXMLUtils::FQN &name_)
Definition: objectfactory.h:222
~ObjectFactoryRegisterXMLNameHelperAsSingleton()
Definition: objectfactory.h:250
static void registerXMLName(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:76
ObjectFactoryRegisterXMLNameHelperAsSingleton(const MBXMLUtils::FQN &name_)
Definition: objectfactory.h:245
Definition: objectfactory.h:68
Definition: objectfactory.h:57
static ContainerType * createAndInit(const xercesc::DOMElement *element)
Definition: objectfactory.h:108
static void deregisterXMLName(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:92
basic error class for mbsim
Definition: mbsim_event.h:38

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML