factory.cpp 5.2 KB
Newer Older
1
2
3
4
// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
// JRL, CNRS/AIST.
//
// This file is part of dynamic-graph.
5
6
7
// dynamic-graph is free software:
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
8
//
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27
28
29
30

#include <boost/foreach.hpp>

#include "dynamic-graph/debug.h"
#include "dynamic-graph/factory.h"
31
32
33
34

using namespace std;
using namespace dynamicgraph;

35
36
namespace dynamicgraph
{
37
38
39
40
41
42
43
  FactoryStorage* FactoryStorage::getInstance ()
  {
    if (instance_ == 0) {
      instance_ = new FactoryStorage;
    }
    return instance_;
  }
Guilhem Saurel's avatar
Guilhem Saurel committed
44

45
46
47
48
49
50
  void FactoryStorage::destroy()
  {
    delete instance_;
    instance_ = NULL;
  }

Thomas Moulard's avatar
Thomas Moulard committed
51
52
  FactoryStorage::FactoryStorage  ()
    : entityMap  ()
53
  {}
54

Thomas Moulard's avatar
Thomas Moulard committed
55
  FactoryStorage::~FactoryStorage  ()
56
  {
57
    instance_ = 0;
58
59
    dgDEBUGINOUT (25);
  }
60

61
62
63
64
65
66
67
68
69
70
  void
  FactoryStorage::registerEntity(const std::string& entname,
				 FactoryStorage::EntityConstructor_ptr ent)
  {
    dgDEBUGIN (25);
    if (existEntity (entname))
      {
	DG_THROW ExceptionFactory
	  (ExceptionFactory::OBJECT_CONFLICT,
	   "Another entity class already defined with the same name. ",
71
	   "(while adding entity class <%s> inside the factory).",
Thomas Moulard's avatar
Thomas Moulard committed
72
	   entname.c_str  ());
73
74
	dgERRORF ("Another entity class already defined with the same name. "
		  "(while adding entity class <%s> inside the factory).",
Thomas Moulard's avatar
Thomas Moulard committed
75
		  entname.c_str  ());
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
      }
    else
      {
	if (!ent)
	  {
	    //FIXME: we should have a better error code for that.
	    DG_THROW ExceptionFactory
	      (ExceptionFactory::OBJECT_CONFLICT,
	       "Bad entity constructor.");
	  }

	dgDEBUG (30) << "Register entity <"<< entname
		     << "> in the factory." <<std::endl;
	entityMap[entname] = ent;
      }
    dgDEBUGOUT (25);
  }
93

94
95
96
97
98
99
100
101
102
  void
  FactoryStorage::deregisterEntity (const std::string& entname)
  {
    dgDEBUGIN (25);
    if (!existEntity(entname))
      {
	DG_THROW ExceptionFactory( ExceptionFactory::OBJECT_CONFLICT,
				   "Entity class not defined yet. ",
				   "(while removing entity class <%s>).",
Thomas Moulard's avatar
Thomas Moulard committed
103
				   entname.c_str () );
104
105
106
	dgERRORF(ExceptionFactory::OBJECT_CONFLICT,
		 "Entity class not defined yet. "
		 "(while removing entity class <%s>).",
Thomas Moulard's avatar
Thomas Moulard committed
107
		 entname.c_str () );
108
109
110
111
112
113
114
115
116
      }
    else
      {
	dgDEBUG (30) << "Deregister entity <"<< entname
		     << "> from the factory." <<std::endl;
	entityMap.erase(entname);
      }
    dgDEBUGOUT (25);
  }
117

118
119
120
121
122
123
124
125
  Entity*
  FactoryStorage::newEntity (const std::string& classname,
			     const std::string& objname) const
  {
    dgDEBUG (15) << "New <" << classname << ">Entity <"
		 << objname << ">" << std::endl;

    EntityMap::const_iterator entPtr = entityMap.find (classname);
Thomas Moulard's avatar
Thomas Moulard committed
126
    if (entPtr == entityMap.end  ())
127
128
129
130
131
      {
	DG_THROW ExceptionFactory
	  (ExceptionFactory::UNREFERED_OBJECT,
	   "Unknown entity.",
	   " (while calling new_entity <%s>)",
Thomas Moulard's avatar
Thomas Moulard committed
132
	   classname.c_str  ());
133
134
135
      }
    return entPtr->second (objname);
  }
136
137


138
139
140
141
142
143
  // This checks efficiently if a key exists in an STL map using the
  // approach suggested by Scott Meyer's Effective STL (item 24).
  bool
  FactoryStorage::existEntity (const std::string& name) const
  {
    EntityMap::const_iterator lb = entityMap.lower_bound (name);
Thomas Moulard's avatar
Thomas Moulard committed
144
145
    return lb != entityMap.end  ()
      && !(entityMap.key_comp  () (name, lb->first));
146
  }
147

148
149
150
151
152
153
154
155
  //FIXME: this should be removed at some point.
  void
  FactoryStorage::listEntities (std::vector<std::string>& outList) const
  {
    typedef std::pair<std::string, EntityConstructor_ptr> iter_t;
    BOOST_FOREACH (const iter_t& entity, entityMap)
      outList.push_back(entity.first);
  }
156

157
158
159
160
161
  EntityRegisterer::EntityRegisterer
  (const std::string& entityClassName, FactoryStorage::EntityConstructor_ptr maker)
    : entityName (entityClassName)
  {
    dgDEBUGIN (15);
162
    FactoryStorage::getInstance()->registerEntity (entityClassName, maker);
163
164
165
    dgDEBUGOUT (15);
  }

Thomas Moulard's avatar
Thomas Moulard committed
166
  EntityRegisterer::~EntityRegisterer ()
167
168
  {
    dgDEBUGIN(15);
169
    FactoryStorage::getInstance()->deregisterEntity (entityName);
170
171
172
173
174
    dgDEBUGOUT (15);
  }


  // The global factory.
175
  FactoryStorage* FactoryStorage::instance_ = NULL;
176
} // end of namespace dynamicgraph.