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 "objectfactory_part.h"
24 #include <vector>
25 #include <stdexcept>
26 #include <typeinfo>
27 #include "mbsim/utils/utils.h"
28 #include <mbsim/mbsim_event.h>
29 #include <mbxmlutilshelper/utils.h>
30 #include "fmatvec/atom.h"
31 #ifdef HAVE_BOOST_CORE_DEMANGLE_HPP // not available for older boost versions
32 # include <boost/core/demangle.hpp>
33 #else
34 namespace boost {
35  namespace core {
36  inline std::string demangle(const std::string &name) {
37  return name;
38  }
39  }
40 }
41 #endif
42 
43 #define COMMA ,
44 
45 namespace MBSim {
46 
47 /* A tree of DOMEvalException's which store the tree of failed objects
48  * creations of the object factory */
50  public:
51  DOMEvalExceptionStack(const xercesc::DOMElement *element) : MBXMLUtils::DOMEvalException("", element) {}
52  DOMEvalExceptionStack(const DOMEvalExceptionStack &src) : MBXMLUtils::DOMEvalException(src), exVec(src.exVec) {}
53  ~DOMEvalExceptionStack() throw() {}
54  void add(const std::string &type, const std::shared_ptr<MBXMLUtils::DOMEvalException> &ex);
55  const char* what() const throw();
56  std::vector<std::pair<std::string, std::shared_ptr<MBXMLUtils::DOMEvalException> > > &getExceptionVector();
57  protected:
58  std::vector<std::pair<std::string, std::shared_ptr<MBXMLUtils::DOMEvalException> > > exVec;
59  mutable std::string whatStr;
60  void generateWhat(std::stringstream &str, const std::string &indent) const;
61 };
62 
63 /* Just to distinguish a wrong type (not castable) error of the object factory
64  * from others */
66  public:
67  DOMEvalExceptionWrongType(const std::string &type, const xercesc::DOMElement *element) :
68  MBXMLUtils::DOMEvalException(type, element) {}
70  ~DOMEvalExceptionWrongType() throw() {}
71 };
72 
77 
78  friend void registerClass_internal(const MBXMLUtils::FQN &name, const AllocateBase *alloc, const DeallocateBase *dealloc);
79  friend void deregisterClass_internal(const MBXMLUtils::FQN &name, const AllocateBase *alloc);
80 
81  public:
82 
86  template<class ContainerType>
87  static ContainerType* createAndInit(const xercesc::DOMElement *element) {
88  // just check if ContainerType is derived from fmatvec::Atom if not throw a compile error
89  static_assert(std::is_convertible<ContainerType*, fmatvec::Atom*>::value,
90  "In MBSim::ObjectFactory::create<ContainerType>(...) ContainerType must be derived from fmatvec::Atom.");
91  // throw error if NULL is supplied as element
92  if(element==NULL)
93  throw MBSimError("Internal error: NULL argument specified.");
94  // get all allocate functions for the given name
95  MBXMLUtils::FQN fqn=MBXMLUtils::E(element)->getTagName();
96  NameMapIt nameIt=instance().registeredType.find(fqn);
97  if(nameIt==instance().registeredType.end())
98  throw MBXMLUtils::DOMEvalException("Internal error: No objects of name {"+fqn.first+"}"+fqn.second+" registred", element);
99  DOMEvalExceptionStack allErrors(static_cast<xercesc::DOMElement*>(element->getParentNode()));
100  // try to create and init a object which each of the allocate function
101  for(AllocDeallocVectorIt allocDeallocIt=nameIt->second.begin(); allocDeallocIt!=nameIt->second.end(); ++allocDeallocIt) {
102  // create element
103  fmatvec::Atom *ele=(*allocDeallocIt->first)();
104  // try to cast the element to ContainerType
105  ContainerType *ret=dynamic_cast<ContainerType*>(ele);
106  if(!ret) {
107  // cast not possible -> deallocate again and try next
108  allErrors.add(boost::core::demangle(typeid(*ele).name()),
109  std::make_shared<DOMEvalExceptionWrongType>(
110  boost::core::demangle(typeid(ContainerType).name()), element));
111  (*allocDeallocIt->second)(ele);
112  continue;
113  }
114  try {
115  ret->initializeUsingXML(const_cast<xercesc::DOMElement*>(element));
116  return ret;
117  }
118  catch(DOMEvalExceptionStack &ex) {
119  allErrors.add(boost::core::demangle(typeid(*ele).name()), std::make_shared<DOMEvalExceptionStack>(ex));
120  }
121  catch(MBXMLUtils::DOMEvalException &ex) {
122  allErrors.add(boost::core::demangle(typeid(*ele).name()), std::make_shared<MBXMLUtils::DOMEvalException>(ex));
123  }
124  catch(std::exception &ex) { // handles also MBSimError
125  allErrors.add(boost::core::demangle(typeid(*ele).name()),
126  std::make_shared<MBXMLUtils::DOMEvalException>(ex.what(), element));
127  }
128  catch(...) {
129  allErrors.add(boost::core::demangle(typeid(*ele).name()),
130  std::make_shared<MBXMLUtils::DOMEvalException>("Unknwon exception", element));
131  }
132  (*allocDeallocIt->second)(ele);
133  }
134  // if all failed -> return errors of all trys
135  throw allErrors;
136  }
137 
138  private:
139 
140  // convinence typedefs
141  typedef std::pair<const AllocateBase*, const DeallocateBase*> AllocDeallocPair;
142  typedef std::vector<AllocDeallocPair> AllocDeallocVector;
143  typedef AllocDeallocVector::iterator AllocDeallocVectorIt;
144  typedef std::map<MBXMLUtils::FQN, AllocDeallocVector> NameMap;
145  typedef NameMap::iterator NameMapIt;
146 
147  // private ctor
148  ObjectFactory() {}
149 
150  // create an singleton instance of the object factory.
151  // only declaration here and defition and explicit instantation for all fmatvec::Atom in objectfactory.cc (required for Windows)
152  static ObjectFactory& instance();
153 
154  // a vector of all registered types
155  NameMap registeredType;
156 };
157 
158 // a wrapper to allocate an object of type CreateType
159 template<class CreateType>
160 struct Allocate : public AllocateBase {
161  // create a new object of type CreateType using new
162  fmatvec::Atom* operator()() const override {
163  return new CreateType;
164  }
165  // check if this Allocator allocates the same object as other.
166  // This is the case if the type of this template class matches
167  // the type of other.
168  bool operator==(const AllocateBase& other) const override {
169  return typeid(*this)==typeid(other);
170  }
171 };
172 
173 // a wrapper to deallocate an object created by allocate
174 struct Deallocate : public DeallocateBase {
175  // deallocate a object using delete
176  void operator()(fmatvec::Atom *obj) const override {
177  delete obj;
178  }
179 };
180 
181 // a wrapper to get an singleton object of type CreateType (Must have the same signature as allocate()
182 template<class CreateType>
183 struct GetSingleton : public AllocateBase {
184  // create a new singelton object of type CreateType using CreateType::getInstance
185  fmatvec::Atom* operator()() const override {
186  return CreateType::getInstance();
187  }
188  // check if this Allocator returns the same object as other.
189  // This is the case if the type of this template class matches
190  // the type of other.
191  bool operator==(const AllocateBase& other) const override {
192  return typeid(*this)==typeid(other);
193  }
194 };
195 
196 // a wrapper to "deallocate" an singleton object (Must have the same signature as deallocate()
198  // deallocate a singleton object -> just do nothing
199  void operator()(fmatvec::Atom *obj) const override {
200  // just do nothing for singletons
201  }
202 };
203 
207 template<class CreateType>
209 
210  public:
211 
213  ObjectFactoryRegisterClassHelper(const MBXMLUtils::FQN &name_) : name(name_) {
214  MBSim::registerClass_internal(name, new Allocate<CreateType>(), new Deallocate());
215  }
216 
219  MBSim::deregisterClass_internal(name, new Allocate<CreateType>());
220  }
221 
222  private:
223  MBXMLUtils::FQN name;
224 
225 };
226 
230 template<class CreateType>
232 
233  public:
234 
237  MBSim::registerClass_internal(name, new GetSingleton<CreateType>(), new DeallocateSingleton());
238  }
239 
242  MBSim::deregisterClass_internal(name, new GetSingleton<CreateType>());
243  }
244 
245  private:
246  MBXMLUtils::FQN name;
247 
248 };
249 
250 // fix local xml name (remove template and namespace)
251 std::string fixXMLLocalName(std::string name);
252 
253 }
254 
255 #define MBSIM_OBJECTFACTORY_CONCAT1(X, Y) X##Y
256 #define MBSIM_OBJECTFACTORY_CONCAT(X, Y) MBSIM_OBJECTFACTORY_CONCAT1(X, Y)
257 #define MBSIM_OBJECTFACTORY_APPENDLINE(X) MBSIM_OBJECTFACTORY_CONCAT(X, __LINE__)
258 
262 #define MBSIM_OBJECTFACTORY_REGISTERCLASS(NS, Class) \
263  static MBSim::ObjectFactoryRegisterClassHelper<Class> \
264  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(NS%MBSim::fixXMLLocalName(#Class));
265 
269 #define MBSIM_OBJECTFACTORY_REGISTERCLASSASSINGLETON(NS, Class) \
270  static MBSim::ObjectFactoryRegisterClassHelperAsSingleton<Class> \
271  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariableAsSingleTon)(NS%MBSim::fixXMLLocalName(#Class));
272 
275 #define MBSIM_OBJECTFACTORY_REGISTERCLASS_AND_INSTANTIATE(NS, Class) \
276  template class Class; \
277  static MBSim::ObjectFactoryRegisterClassHelper<Class> \
278  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(NS%MBSim::fixXMLLocalName(#Class));
279 
282 #define MBSIM_OBJECTFACTORY_REGISTERCLASSASSINGLETON_AND_INSTANTIATE(NS, Class) \
283  template class Class; \
284  static MBSim::ObjectFactoryRegisterClassHelperAsSingleton<Class> \
285  MBSIM_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariableAsSingleTon)(NS%MBSim::fixXMLLocalName(#Class));
286 
287 #endif
Definition: objectfactory.h:49
Definition: objectfactory.h:208
~ObjectFactoryRegisterClassHelper()
Definition: objectfactory.h:218
void operator()(fmatvec::Atom *obj) const override
Implement this function to deallocate the object obj.
Definition: objectfactory.h:199
Definition: objectfactory_part.h:48
Definition: objectfactory.h:183
Definition: objectfactory.h:160
ObjectFactoryRegisterClassHelper(const MBXMLUtils::FQN &name_)
Definition: objectfactory.h:213
Definition: objectfactory.h:197
~ObjectFactoryRegisterClassHelperAsSingleton()
Definition: objectfactory.h:241
bool operator==(const AllocateBase &other) const override
Definition: objectfactory.h:191
fmatvec::Atom * operator()() const override
Implement this function to allocate a new object.
Definition: objectfactory.h:185
Definition: objectfactory.h:174
Definition: objectfactory.h:76
Definition: objectfactory_part.h:37
Definition: objectfactory.h:65
static ContainerType * createAndInit(const xercesc::DOMElement *element)
Definition: objectfactory.h:87
fmatvec::Atom * operator()() const override
Implement this function to allocate a new object.
Definition: objectfactory.h:162
basic error class for mbsim
Definition: mbsim_event.h:38
ObjectFactoryRegisterClassHelperAsSingleton(const MBXMLUtils::FQN &name_)
Definition: objectfactory.h:236
void operator()(fmatvec::Atom *obj) const override
Implement this function to deallocate the object obj.
Definition: objectfactory.h:176
bool operator==(const AllocateBase &other) const override
Definition: objectfactory.h:168

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML