1 |
|
|
// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse, |
2 |
|
|
// JRL, CNRS/AIST. |
3 |
|
|
// |
4 |
|
|
|
5 |
|
|
#include "dynamic-graph/factory.h" |
6 |
|
|
|
7 |
|
|
#include <boost/foreach.hpp> |
8 |
|
|
|
9 |
|
|
#include "dynamic-graph/debug.h" |
10 |
|
|
|
11 |
|
|
using namespace std; |
12 |
|
|
using namespace dynamicgraph; |
13 |
|
|
|
14 |
|
|
namespace dynamicgraph { |
15 |
|
54 |
FactoryStorage *FactoryStorage::getInstance() { |
16 |
✓✓ |
54 |
if (instance_ == 0) { |
17 |
✓✗ |
11 |
instance_ = new FactoryStorage; |
18 |
|
|
} |
19 |
|
54 |
return instance_; |
20 |
|
|
} |
21 |
|
|
|
22 |
|
1 |
void FactoryStorage::destroy() { |
23 |
✓✗ |
1 |
delete instance_; |
24 |
|
1 |
instance_ = NULL; |
25 |
|
1 |
} |
26 |
|
|
|
27 |
|
11 |
FactoryStorage::FactoryStorage() : entityMap() {} |
28 |
|
|
|
29 |
|
2 |
FactoryStorage::~FactoryStorage() { |
30 |
|
1 |
instance_ = 0; |
31 |
|
|
dgDEBUGINOUT(25); |
32 |
|
1 |
} |
33 |
|
|
|
34 |
|
16 |
void FactoryStorage::registerEntity(const std::string &entname, |
35 |
|
|
FactoryStorage::EntityConstructor_ptr ent) { |
36 |
|
|
dgDEBUGIN(25); |
37 |
✓✓ |
16 |
if (existEntity(entname)) { |
38 |
|
|
DG_THROW ExceptionFactory( |
39 |
|
|
ExceptionFactory::OBJECT_CONFLICT, |
40 |
|
|
"Another entity class already defined with the same name. ", |
41 |
|
|
"(while adding entity class <%s> inside the factory).", |
42 |
✓✗✓✗
|
2 |
entname.c_str()); |
43 |
|
|
dgERRORF( |
44 |
|
|
"Another entity class already defined with the same name. " |
45 |
|
|
"(while adding entity class <%s> inside the factory).", |
46 |
|
|
entname.c_str()); |
47 |
|
|
} else { |
48 |
✗✓ |
14 |
if (!ent) { |
49 |
|
|
// FIXME: we should have a better error code for that. |
50 |
|
|
DG_THROW ExceptionFactory(ExceptionFactory::OBJECT_CONFLICT, |
51 |
|
|
"Bad entity constructor."); |
52 |
|
|
} |
53 |
|
|
|
54 |
|
|
dgDEBUG(30) << "Register entity <" << entname << "> in the factory." |
55 |
|
|
<< std::endl; |
56 |
|
14 |
entityMap[entname] = ent; |
57 |
|
|
} |
58 |
|
|
dgDEBUGOUT(25); |
59 |
|
14 |
} |
60 |
|
|
|
61 |
|
16 |
void FactoryStorage::deregisterEntity(const std::string &entname) { |
62 |
|
|
dgDEBUGIN(25); |
63 |
✓✓ |
16 |
if (!existEntity(entname)) { |
64 |
|
|
DG_THROW ExceptionFactory( |
65 |
|
|
ExceptionFactory::OBJECT_CONFLICT, "Entity class not defined yet. ", |
66 |
✓✗✓✗
|
3 |
"(while removing entity class <%s>).", entname.c_str()); |
67 |
|
|
dgERRORF(ExceptionFactory::OBJECT_CONFLICT, |
68 |
|
|
"Entity class not defined yet. " |
69 |
|
|
"(while removing entity class <%s>).", |
70 |
|
|
entname.c_str()); |
71 |
|
|
} else { |
72 |
|
|
dgDEBUG(30) << "Deregister entity <" << entname << "> from the factory." |
73 |
|
|
<< std::endl; |
74 |
|
13 |
entityMap.erase(entname); |
75 |
|
|
} |
76 |
|
|
dgDEBUGOUT(25); |
77 |
|
13 |
} |
78 |
|
|
|
79 |
|
17 |
Entity *FactoryStorage::newEntity(const std::string &classname, |
80 |
|
|
const std::string &objname) const { |
81 |
|
|
dgDEBUG(15) << "New <" << classname << ">Entity <" << objname << ">" |
82 |
|
|
<< std::endl; |
83 |
|
|
|
84 |
✓✗ |
17 |
EntityMap::const_iterator entPtr = entityMap.find(classname); |
85 |
✓✓ |
17 |
if (entPtr == entityMap.end()) { |
86 |
|
|
DG_THROW ExceptionFactory( |
87 |
|
|
ExceptionFactory::UNREFERED_OBJECT, "Unknown entity.", |
88 |
✓✗✓✗
|
1 |
" (while calling new_entity <%s>)", classname.c_str()); |
89 |
|
|
} |
90 |
✓✓ |
31 |
return entPtr->second(objname); |
91 |
|
|
} |
92 |
|
|
|
93 |
|
|
// This checks efficiently if a key exists in an STL map using the |
94 |
|
|
// approach suggested by Scott Meyer's Effective STL (item 24). |
95 |
|
35 |
bool FactoryStorage::existEntity(const std::string &name) const { |
96 |
✓✗ |
35 |
EntityMap::const_iterator lb = entityMap.lower_bound(name); |
97 |
✓✓✓✗ ✓✓ |
35 |
return lb != entityMap.end() && !(entityMap.key_comp()(name, lb->first)); |
98 |
|
|
} |
99 |
|
|
|
100 |
|
|
// FIXME: this should be removed at some point. |
101 |
|
|
void FactoryStorage::listEntities(std::vector<std::string> &outList) const { |
102 |
|
|
typedef std::pair<std::string, EntityConstructor_ptr> iter_t; |
103 |
|
|
BOOST_FOREACH (const iter_t &entity, entityMap) |
104 |
|
|
outList.push_back(entity.first); |
105 |
|
|
} |
106 |
|
|
|
107 |
|
12 |
EntityRegisterer::EntityRegisterer(const std::string &entityClassName, |
108 |
|
12 |
FactoryStorage::EntityConstructor_ptr maker) |
109 |
|
12 |
: entityName(entityClassName) { |
110 |
|
|
dgDEBUGIN(15); |
111 |
✓✗✓✗
|
12 |
FactoryStorage::getInstance()->registerEntity(entityClassName, maker); |
112 |
|
|
dgDEBUGOUT(15); |
113 |
|
12 |
} |
114 |
|
|
|
115 |
|
12 |
EntityRegisterer::~EntityRegisterer() { |
116 |
|
|
dgDEBUGIN(15); |
117 |
|
12 |
FactoryStorage::getInstance()->deregisterEntity(entityName); |
118 |
|
|
dgDEBUGOUT(15); |
119 |
|
12 |
} |
120 |
|
|
|
121 |
|
|
// The global factory. |
122 |
|
|
FactoryStorage *FactoryStorage::instance_ = NULL; |
123 |
|
|
} // end of namespace dynamicgraph. |