All Classes Namespaces Functions Variables Typedefs Enumerations Pages
objectfactory.h
1 /* Copyright (C) 2004-2010 OpenMBV 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 _OPENMBV_OBJECTFACTORY_H_
21 #define _OPENMBV_OBJECTFACTORY_H_
22 
23 #include <map>
24 #include <stdexcept>
25 #include <typeinfo>
26 #include <mbxmlutilshelper/dom.h>
27 #include <xercesc/dom/DOMElement.hpp>
28 #ifdef HAVE_BOOST_TYPE_TRAITS_HPP
29 # include <boost/static_assert.hpp>
30 # include <boost/type_traits.hpp>
31 #endif
32 
33 namespace OpenMBV {
34 
35 class Object;
36 
41 
42  public:
43 
47  template<class CreateType>
48  static void registerXMLName(const MBXMLUtils::FQN &name) {
49  registerXMLName(name, &allocate<CreateType>);
50  }
51 
55  template<class ContainerType>
56  static boost::shared_ptr<ContainerType> create(const xercesc::DOMElement *element) {
57 #ifdef HAVE_BOOST_TYPE_TRAITS_HPP
58  // just check if ContainerType is derived from Object if not throw a compile error if boost is avaliable
59  // if boost is not avaliable a runtime error will occure later. (so it does not care if boost is not available)
60  BOOST_STATIC_ASSERT_MSG((boost::is_convertible<ContainerType*, Object*>::value),
61  "In OpenMBV::ObjectFactory::create<ContainerType>(...) ContainerType must be derived from Object.");
62 #endif
63  // return NULL if no input is supplied
64  if(element==NULL) return boost::shared_ptr<ContainerType>();
65  // loop over all all registred types corresponding to element->ValueStr()
66  std::pair<MapIt, MapIt> range=instance().registeredType.equal_range(MBXMLUtils::E(element)->getTagName());
67  for(MapIt it=range.first; it!=range.second; it++) {
68  // allocate a new object using the allocate function pointer
69  boost::shared_ptr<Object> ele=it->second();
70  // try to cast ele up to ContainerType
71  boost::shared_ptr<ContainerType> ret=boost::dynamic_pointer_cast<ContainerType>(ele);
72  // if possible, return it
73  if(ret)
74  return ret;
75  }
76  // no matching element found: throw error
77  throw std::runtime_error("No class named "+MBXMLUtils::X()%element->getTagName()+" found which is of type "+
78  typeid(ContainerType).name()+".");
79  }
80 
82  template<class CreateType>
83  static boost::shared_ptr<CreateType> create() {
84  return boost::shared_ptr<CreateType>(new CreateType, &deleter<CreateType>);
85  }
86 
88  template<class CreateType>
89  static boost::shared_ptr<CreateType> create(const boost::shared_ptr<CreateType> &t) {
90  return boost::shared_ptr<CreateType>(new CreateType(*t.get()), &deleter<CreateType>);
91  }
92 
93  private:
94 
95  // a pointer to a function allocating an object
96  typedef boost::shared_ptr<Object> (*allocateFkt)();
97 
98  // convinence typedefs
99  typedef std::multimap<MBXMLUtils::FQN, allocateFkt> Map;
100  typedef typename Map::iterator MapIt;
101 
102  // private ctor
103  ObjectFactory() {}
104 
105  static void registerXMLName(const MBXMLUtils::FQN &name, allocateFkt alloc);
106 
107  // create an singleton instance of the object factory.
108  // only declaration here and defition and explicit instantation for all Object in objectfactory.cc (required for Windows)
109  static ObjectFactory& instance();
110 
111  // a multimap of all registered types
112  Map registeredType;
113 
114  // a wrapper to allocate an object of type CreateType: used by create(xercesc::DOMElement *)
115  template<class CreateType>
116  static boost::shared_ptr<Object> allocate() {
117  return boost::shared_ptr<CreateType>(new CreateType, &deleter<CreateType>);
118  }
119 
120  // a wrapper to deallocate an object of type T: all dtors are protected but ObjectFactory is a friend of all classes
121  template<class T>
122  static void deleter(T *t) { delete t; }
123 
124 };
125 
129 template<class CreateType>
131 
132  public:
133 
135  ObjectFactoryRegisterXMLNameHelper(const MBXMLUtils::FQN &name) {
136  ObjectFactory::registerXMLName<CreateType>(name);
137  };
138 
139 };
140 
141 }
142 
143 #define OPENMBV_OBJECTFACTORY_CONCAT1(X, Y) X##Y
144 #define OPENMBV_OBJECTFACTORY_CONCAT(X, Y) OPENMBV_OBJECTFACTORY_CONCAT1(X, Y)
145 #define OPENMBV_OBJECTFACTORY_APPENDLINE(X) OPENMBV_OBJECTFACTORY_CONCAT(X, __LINE__)
146 
149 #define OPENMBV_OBJECTFACTORY_REGISTERXMLNAME(ThisType, name) \
150  static OpenMBV::ObjectFactoryRegisterXMLNameHelper<ThisType> \
151  OPENMBV_OBJECTFACTORY_APPENDLINE(objectFactoryRegistrationDummyVariable)(name);
152 
153 #endif
Definition: objectfactory.h:40
static void registerXMLName(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:48
ObjectFactoryRegisterXMLNameHelper(const MBXMLUtils::FQN &name)
Definition: objectfactory.h:135
Definition: objectfactory.h:130
static boost::shared_ptr< ContainerType > create(const xercesc::DOMElement *element)
Definition: objectfactory.h:56
static boost::shared_ptr< CreateType > create(const boost::shared_ptr< CreateType > &t)
Definition: objectfactory.h:89
static boost::shared_ptr< CreateType > create()
Definition: objectfactory.h:83

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML