From 20d8b91c039b3d55ba5715f265bbea2dd295beb4 Mon Sep 17 00:00:00 2001
From: Thomas Moulard <thomas.moulard@gmail.com>
Date: Fri, 24 Dec 2010 01:20:20 +0100
Subject: [PATCH] Clean and document factoryStorage.

---
 include/CMakeLists.txt          |   1 +
 include/dynamic-graph/factory.h | 333 +++++++++++++++++++-----------
 include/dynamic-graph/fwd.hh    |  28 +++
 src/dgraph/factory.cpp          | 346 ++++++++++++++++----------------
 4 files changed, 423 insertions(+), 285 deletions(-)
 create mode 100644 include/dynamic-graph/fwd.hh

diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 008cc9f..f9166fe 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -30,6 +30,7 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/import-default-paths.h
 
 # Headers list.
 SET(${PROJECT_NAME}_HEADERS
+fwd.hh
 contiifstream.h
 debug.h
 
diff --git a/include/dynamic-graph/factory.h b/include/dynamic-graph/factory.h
index 309d9a7..7d22f26 100644
--- a/include/dynamic-graph/factory.h
+++ b/include/dynamic-graph/factory.h
@@ -1,114 +1,41 @@
-/*
- * Copyright 2010,
- * François Bleibel,
- * Olivier Stasse,
- *
- * CNRS/AIST
- *
- * This file is part of dynamic-graph.
- * dynamic-graph is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- * dynamic-graph is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.  You should
- * have received a copy of the GNU Lesser General Public License along
- * with dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __FACTORY_HH__
-#define __FACTORY_HH__
-
-/* --------------------------------------------------------------------- */
-/* --- INCLUDE --------------------------------------------------------- */
-/* --------------------------------------------------------------------- */
-
-/* --- STD --- */
-#include <map>
-#include <string>
-#include <vector>
-/* --- DYNAMIC-GRAPH --- */
-#include <dynamic-graph/exception-factory.h>
-#include <dynamic-graph/dynamic-graph-api.h>
-
-namespace dynamicgraph {
-
-class Entity;
-
-/* --------------------------------------------------------------------- */
-/* --- FACTORY ---------------------------------------------------------- */
-/* --------------------------------------------------------------------- */
-
-/*! \class FactoryStorage
- *  \ingroup dgraph
- *  \brief The Factory class is responsible for creating Entity objects.
- *
- *  Entities can register themselves through the helper class EntityRegisterer.
- *  This object also provides access to command-line functions.
- *
- *
- */
-class DYNAMIC_GRAPH_DLLAPI FactoryStorage
-{
- public:
-
-  typedef Entity* (*EntityConstructor_ptr)( const std::string& );
-
- protected:
-  typedef std::map< std::string,EntityConstructor_ptr > EntityMap;
-
-  EntityMap entityMap;
-
- public:
-
-  ~FactoryStorage( void );
-
-  void registerEntity( const std::string& entname,EntityConstructor_ptr ent );
-  void deregisterEntity( const std::string& entname );
-  Entity* newEntity( const std::string& name,const std::string& objname );
-  bool existEntity( const std::string& name, EntityMap::iterator& entPtr );
-  bool existEntity( const std::string& name );
-  /// Return the list of Entity class names registered in the factory.
-  /// Class names are appended at end of output vector.
-  void listEntities(std::vector <std::string>& outList);
-  void  commandLine( const std::string& cmdLine,std::istringstream& cmdArgs,
-		     std::ostream& os );
-};
-
-DYNAMIC_GRAPH_DLLAPI extern FactoryStorage g_factory;
-
-/* --- REGISTERER ----------------------------------------------------------- */
-/* --- REGISTERER ----------------------------------------------------------- */
-/* --- REGISTERER ----------------------------------------------------------- */
-
-/* -------------------------------------------------------------------------- */
-/* --- ENTITY REGISTERER ---------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-/*! A helper class to register an entity.
- *
- */
-class DYNAMIC_GRAPH_DLLAPI EntityRegisterer
-{
- private:
-  EntityRegisterer( void );
-  std::string entityName;
-
- public:
-  EntityRegisterer( const std::string& entityClassName,
-		       FactoryStorage::EntityConstructor_ptr maker);
-
-  ~EntityRegisterer( void );
-};
-}  // namespace dynamicgraph
-
-/*! This macro should be used to automatically register an entity
- * of classType to the g_factory. It is then possible to create it
- * with the g_factory.
- */
-#define DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(CLASSTYPE, CLASSNAME)	\
+// -*- c++-mode -*-
+// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
+// JRL, CNRS/AIST.
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// dynamic-graph is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DYNAMIC_GRAPH_FACTORY_HH
+# define DYNAMIC_GRAPH_FACTORY_HH
+# include <map>
+# include <string>
+# include <vector>
+
+# include <boost/noncopyable.hpp>
+
+# include <dynamic-graph/fwd.hh>
+# include <dynamic-graph/exception-factory.h>
+# include <dynamic-graph/dynamic-graph-api.h>
+
+
+/// \brief Automatically register a class to the global factory
+/// by relying on the static initialization.
+///
+/// \param CLASSTYPE the Entity type to be registered
+/// \param CLASSNAME the name of the Entity to be registered (this must
+///        be a std::string or a type implicitly castable into a std::string
+///        such as classic C string delimited by double quotes).
+# define DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(CLASSTYPE, CLASSNAME)	\
   const std::string CLASSTYPE::CLASS_NAME = CLASSNAME;			\
   extern "C" {								\
     ::dynamicgraph::Entity*						\
@@ -122,8 +49,188 @@ class DYNAMIC_GRAPH_DLLAPI EntityRegisterer
   }									\
   struct e_n_d__w_i_t_h__s_e_m_i_c_o_l_o_n
 
-#endif /* #ifndef __FACTORY_HH__ */
-
 
+namespace dynamicgraph
+{
+  /// \ingroup dgraph
+  ///
+  /// \brief Provides a way to create Entity objects from their class
+  /// name.
+  ///
+  /// The dynamic graph frameworks relies on entities (see Entity)
+  /// which defines atomic processing units. This class provides a
+  /// robust way to enumerate and instantiate these entities.
+  /// Each entity has a name (its type name) and can be instantiated.
+  /// Each instance also has a name.
+  ///
+  /// For instance one can define a C++ class called MyEntity which
+  /// inherits from dynamicgraph::Entity. This type can be registered
+  /// into the factory to teach the framework that:
+  /// - this entity exists
+  /// - this entity can be instantiated (and how to instantiate it).
+  ///
+  /// To achieve this, one must pass an entity name and a function pointer.
+  ///
+  /// The entity name will identify the class <b>at run-time</b>
+  /// (be careful: this may not be equivalent to the C++ class name
+  /// even if it is recommended to do so).
+  ///
+  /// The function pointer must point on a function taking a string as
+  /// input and returning an instance of the Entity (the concrete
+  /// subclass, not directly the upper Entity class).
+  ///
+  /// The instances returned by this function <b>must</b> be
+  /// dynamically allocated and the caller <b>must</b> get the
+  /// ownership of the instance (i.e. it will free it when required).
+  ///
+  /// To finish, please note that the instance name indicates to the
+  /// entity how the instance itself is called at run-time.  This name
+  /// does not need to be unique and no check is done on it.  It is
+  /// the caller responsibility to make sure that the instance name is
+  /// appropriate and to check for uniqueness if required.
+  ///
+  ///
+  /// This class should <b>never</b> be used directly.  Use the
+  /// g_factory global variable instead.  The rationale is that each
+  /// unique name must identify a unique Entity. The use of a single
+  /// instance of this class enforces this behavior, instantiating one
+  /// yourself would break this property.
+  class DYNAMIC_GRAPH_DLLAPI FactoryStorage : private boost::noncopyable
+  {
+  public:
+    /// \brief Function pointer providing an entity instance from its
+    /// name.
+    typedef Entity* (*EntityConstructor_ptr) (const std::string&);
+
+    /// \brief Constructor the factory.
+    ///
+    /// After the initialization, no entities will be available.
+    /// registerEntity has to be used to add new entities to the
+    /// object.
+    explicit FactoryStorage ();
+
+    ~FactoryStorage ();
+
+    /// \brief Add a new entity to the factory.
+    ///
+    /// It is not allowed to have several entities using the same
+    /// name. If this is the case, an ExceptionFactory exception will
+    /// be raised with the code OBJECT_CONFLICT.
+    ///
+    /// If the function pointer is null, an ExceptionFactory exception
+    /// will be raised with the code OBJECT_CONFLICT.
+    ///
+    /// \param entname the name used to subscribe the entity.
+    /// \param pointer to a function allocating an entity from an
+    /// instance name.
+    void registerEntity (const std::string& entname,
+			 EntityConstructor_ptr ent);
+
+    /// \brief Delete an entity from the factory.
+    ///
+    /// If the provided entity name does not exist in the factory,
+    /// an ExceptionFactory exception will be raised with the code
+    /// OBJECT_CONFLICT.
+    ///
+    /// \param entname the entity name (as passed to registerEntity before)
+    void deregisterEntity (const std::string& entname);
+
+    /// \brief Instantiate (and allocate) an entity.
+    ///
+    /// An instance called objname of the entity which type is classname
+    /// will be allocated by this method.
+    ///
+    /// It is <b>the caller</b> responsibility to free the
+    /// returned object.
+    ///
+    /// If the class name does not exist, an ExceptionFactory
+    /// exception will be raised with the code UNREFERED_OBJECT.
+    ///
+    /// The instance name (objname) is passed to the Entity
+    /// constructor and it is the caller responsibility to avoid
+    /// instance name conflicts if necessary.
+    ///
+    /// \param classname the name of the Entity type
+    /// \param objname the instance name
+    /// \return Dynamically allocated instance of classname.
+    Entity* newEntity (const std::string& classname,
+		       const std::string& objname) const;
+
+    /// \brief Check if an Entity associated with a particular name
+    /// has already been registered.
+    ///
+    /// \param name entity name
+    /// \return Do the entity exist?
+    bool existEntity (const std::string& name) const;
+
+    /// \brief List the available entities.
+    ///
+    /// Available entities are appended to the method argument.
+    ///
+    /// \param list Available entities will be appended to list.
+    void listEntities (std::vector <std::string>& list) const;
+
+    /// \brief Define FactoryStorage commands.
+    ///
+    /// Define two equivalent commands:
+    /// - list
+    /// - listEntities
+    /// listing the available entities.
+    void commandLine (const std::string& cmdLine,
+		      std::istringstream& cmdArgs,
+		      std::ostream& os);
+
+  private:
+    /// \brief Entity map type.
+    ///
+    /// This maps entity names to functions pointers which can be
+    /// used to instantiate an Entity.
+    typedef std::map<std::string, EntityConstructor_ptr> EntityMap;
+
+    /// \brief The entity map storing information about how to
+    /// instantiate an Entity.
+    EntityMap entityMap;
+  };
+
+  /// \brief Global factory.
+  ///
+  /// This global variable is the only valid instance of the
+  /// FactoryStorage class.
+  ///
+  /// This unique instance is to make sure that only only one entity
+  /// list is built.
+  ///
+  /// This global variable must be used to search for entities and
+  /// to instantiate them.
+  ///
+  /// Please use the DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN macro if
+  /// possible to register an entity to this factory.
+  DYNAMIC_GRAPH_DLLAPI extern FactoryStorage g_factory;
+
+
+  /// \brief This class automatically register an Entity to the
+  /// global factory at initialization and unregister it during
+  /// instance destruction.
+  ///
+  /// This class is mainly used by the
+  /// DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN macro and is of little interest
+  /// by itself.
+  class DYNAMIC_GRAPH_DLLAPI EntityRegisterer : private boost::noncopyable
+  {
+  public:
+    /// \brief Register entity to the global factory.
+    explicit EntityRegisterer (const std::string& entityClassName,
+			       FactoryStorage::EntityConstructor_ptr maker);
+
+    /// \brief Unregister entity to the global factory.
+    ~EntityRegisterer ();
+  private:
+    /// \brief Name of the entity registered when the instance has
+    /// been initialized.
+    const std::string entityName;
+  };
+}  // namespace dynamicgraph
 
+#endif //! DYNAMIC_GRAPH_FACTORY_HH
 
+//  LocalWords:  unregister
diff --git a/include/dynamic-graph/fwd.hh b/include/dynamic-graph/fwd.hh
new file mode 100644
index 0000000..4740300
--- /dev/null
+++ b/include/dynamic-graph/fwd.hh
@@ -0,0 +1,28 @@
+// Copyright 2010, Thomas Moulard, JRL, CNRS/AIST
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// dynamic-graph is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DYNAMIC_GRAPH_FWD_HH
+# define DYNAMIC_GRAPH_FWD_HH
+
+namespace dynamicgraph
+{
+  class Entity;
+
+  class FactoryStorage;
+  class EntityRegisterer;
+
+} // end of namespace dynamicgraph.
+
+#endif //! DYNAMIC_GRAPH_FWD_HH
diff --git a/src/dgraph/factory.cpp b/src/dgraph/factory.cpp
index 637c029..cb8ca88 100644
--- a/src/dgraph/factory.cpp
+++ b/src/dgraph/factory.cpp
@@ -1,188 +1,190 @@
-/*
- * Copyright 2010,
- * François Bleibel,
- * Olivier Stasse,
- *
- * CNRS/AIST
- *
- * This file is part of dynamic-graph.
- * dynamic-graph is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- * dynamic-graph is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Lesser General Public License for more details.  You should
- * have received a copy of the GNU Lesser General Public License along
- * with dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* --------------------------------------------------------------------- */
-/* --- INCLUDE --------------------------------------------------------- */
-/* --------------------------------------------------------------------- */
-
-/* --- DYNAMIC-GRAPH --- */
-#include <dynamic-graph/debug.h>
-#include <dynamic-graph/factory.h>
+// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
+// JRL, CNRS/AIST.
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+//
+// dynamic-graph is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Lesser Public License for more details.  You should have
+// received a copy of the GNU Lesser General Public License along with
+// dynamic-graph. If not, see <http://www.gnu.org/licenses/>.
+
+#include <boost/foreach.hpp>
+
+#include "dynamic-graph/debug.h"
+#include "dynamic-graph/factory.h"
 
 using namespace std;
 using namespace dynamicgraph;
 
-/* --------------------------------------------------------------------- */
-/* --- CLASS ----------------------------------------------------------- */
-/* --------------------------------------------------------------------- */
+namespace dynamicgraph
+{
+  FactoryStorage::FactoryStorage ()
+    : entityMap ()
+  {}
 
+  FactoryStorage::~FactoryStorage ()
+  {
+    dgDEBUGINOUT (25);
+  }
 
-FactoryStorage::
-~FactoryStorage( void )
-{
-  dgDEBUGINOUT(25);
-}
+  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. ",
+	   "(while adding entity class <%s> inside the g_factory).",
+	   entname.c_str ());
+	dgERRORF ("Another entity class already defined with the same name. "
+		  "(while adding entity class <%s> inside the factory).",
+		  entname.c_str ());
+      }
+    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);
+  }
 
+  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>).",
+				   entname.c_str() );
+	dgERRORF(ExceptionFactory::OBJECT_CONFLICT,
+		 "Entity class not defined yet. "
+		 "(while removing entity class <%s>).",
+		 entname.c_str() );
+      }
+    else
+      {
+	dgDEBUG (30) << "Deregister entity <"<< entname
+		     << "> from the factory." <<std::endl;
+	entityMap.erase(entname);
+      }
+    dgDEBUGOUT (25);
+  }
 
+  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);
+    if (entPtr == entityMap.end ())
+      {
+	DG_THROW ExceptionFactory
+	  (ExceptionFactory::UNREFERED_OBJECT,
+	   "Unknown entity.",
+	   " (while calling new_entity <%s>)",
+	   classname.c_str ());
+      }
+    return entPtr->second (objname);
+  }
 
-/* --------------------------------------------------------------------- */
-void FactoryStorage::
-registerEntity( const std::string& entname,FactoryStorage::EntityConstructor_ptr ent )
-{
-  dgDEBUGIN(25);
-  EntityMap::iterator entkey;
-  if( existEntity(entname,entkey) ) // key does exist
-    {
-//       DG_THROW ExceptionFactory( ExceptionFactory::OBJECT_CONFLICT,
-// 				 "Another entity class already defined with the same name. ",
-// 				 "(while adding entity class <%s> inside the g_factory).",
-// 				 entname.c_str() );
-      dgERRORF("Another entity class already defined with the same name. "
-		"(while adding entity class <%s> inside the factory).",
-		entname.c_str() );
-    }
-  else
-    {
-       dgDEBUG(30) << "Register entity <"<< entname
-		    << "> in the factory." <<std::endl;
-      entityMap[entname] = ent;
-    }
-  dgDEBUGOUT(25);
-}
-
-void FactoryStorage::
-deregisterEntity( const std::string& entname )
-{
-  dgDEBUGIN(25);
-  EntityMap::iterator entkey;
-  if(! existEntity(entname,entkey) ) // key does not exist
-    {
-      DG_THROW ExceptionFactory( ExceptionFactory::OBJECT_CONFLICT,
-				     "Entity class not defined yet. ",
-				     "(while removing entity class <%s>).",
-				     entname.c_str() );
-      dgERRORF(ExceptionFactory::OBJECT_CONFLICT,
-		"Entity class not defined yet. "
-		"(while removing entity class <%s>).",
-		entname.c_str() );
-    }
-  else
-    {
-       dgDEBUG(30) << "Deregister entity <"<< entname
-		    << "> from the factory." <<std::endl;
-       entityMap.erase( entkey );
-    }
-  dgDEBUGOUT(25);
-}
-
-Entity* FactoryStorage::
-newEntity( const std::string& classname,const std::string& objname )
-{
-  dgDEBUG(15) << "New <"<<classname<<">Entity <"<<objname<<">"<<std::endl;
-  EntityMap::iterator entPtr;
-  if(! existEntity(classname,entPtr) )
-    {
-      DG_THROW ExceptionFactory( ExceptionFactory::UNREFERED_OBJECT,
-				     "Unknown entity."," (while calling new_entity <%s>)",
-				     classname.c_str() );
-    }
-  return entPtr->second(objname);
-}
-
-bool FactoryStorage::
-existEntity( const std::string& name, EntityMap::iterator& entPtr )
-{
-  entPtr = entityMap .find( name );
-  return ( entPtr != entityMap.end() );
-}
-bool FactoryStorage::
-existEntity( const std::string& name )
-{
-  EntityMap::iterator entPtr;return existEntity( name,entPtr );
-}
 
-void FactoryStorage::
-listEntities(std::vector <std::string>& outList)
-{
-  for (EntityMap::iterator it = entityMap.begin();
-       it != entityMap.end(); it++) {
-    outList.push_back(it->first);
+  // 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);
+    return lb != entityMap.end ()
+      && !(entityMap.key_comp () (name, lb->first));
   }
-}
-
-/* --------------------------------------------------------------------- */
-/* --- REGISTERERS ----------------------------------------------------- */
-/* --------------------------------------------------------------------- */
-EntityRegisterer::
-EntityRegisterer( const std::string& entityClassName,
-		     FactoryStorage::EntityConstructor_ptr maker)
-  :entityName( entityClassName )
-{
-  dgDEBUGIN(15);
-  g_factory.registerEntity(entityClassName,maker);
-  dgDEBUGOUT(15);
-}
 
-EntityRegisterer::
-~EntityRegisterer( void )
-{
-  dgDEBUGIN(15);
+  //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);
+  }
 
-  g_factory.deregisterEntity(entityName);
+  void
+  FactoryStorage::commandLine(const std::string& cmdLine,
+			      std::istringstream& cmdArgs,
+			      std::ostream& os)
+  {
+    if (cmdLine == "help")
+      {
+	os << "factory ";
+
+	std::string cmd2;
+	cmdArgs >> cmd2;
+
+	if (!cmdArgs.good ())
+	  os
+	    << " <arg>\t\t\t\taccess to the factory (help <arg> for more detail)"
+	    << std::endl;
+	else if (cmd2 == "list")
+	  os << "list\t\t:List all available entities." << std::endl;
+	else if (cmd2 == "listEntities")
+	  os <<"listEntities\t:List available entities." << std::endl;
+      }
+    else if (cmdLine == "list")
+      commandLine("listEntities",cmdArgs,os);
+    else if (cmdLine == "listEntities")
+      {
+	os <<" List of available entities:" << std::endl;
+
+	typedef std::pair<std::string, EntityConstructor_ptr> iter_t;
+	BOOST_FOREACH (const iter_t& entity, entityMap)
+	  os << "  - " << entity.first << std::endl;
+      }
+    return;
+  }
 
-  dgDEBUGOUT(15);
-}
 
 
-/* --------------------------------------------------------------------- */
-/* ---  COMMAND LINE ---------------------------------------------------- */
-/* --------------------------------------------------------------------- */
-void FactoryStorage::
-commandLine( const std::string& cmdLine,std::istringstream& cmdArgs,
-	     std::ostream& os )
-{
-  if( cmdLine == "help" )
-    {
-      os<< "factory ";
-      string cmd2; cmdArgs >> cmd2;
-      if(! cmdArgs.good())
-	os << " <arg>\t\t\t\taccess to the factory (help <arg> for more detail)" <<endl;
-      else if( cmd2 == "list" )
-	os << "list\t\t:List all available entities." << endl;
-      else if( cmd2 == "listEntities" )
-	os <<"listEntities\t:List available entities." << endl;
-    }
-  else if( cmdLine == "list" )
-    {
-      commandLine("listEntities",cmdArgs,os);
-    }
-  else if( cmdLine == "listEntities" )
-    {
-      os <<" List of available entities:" << endl;
-      for( EntityMap::iterator iter = entityMap.begin();iter!=entityMap.end();++iter )
-	{ os << "  - " << iter->first << endl; }
-    }
-  return;
-}
-
-namespace dynamicgraph {
-	//! The global g_factory object.
-	FactoryStorage g_factory;
-}
+
+
+
+  EntityRegisterer::EntityRegisterer
+  (const std::string& entityClassName, FactoryStorage::EntityConstructor_ptr maker)
+    : entityName (entityClassName)
+  {
+    dgDEBUGIN (15);
+    g_factory.registerEntity (entityClassName, maker);
+    dgDEBUGOUT (15);
+  }
+
+  EntityRegisterer::~EntityRegisterer()
+  {
+    dgDEBUGIN(15);
+    g_factory.deregisterEntity (entityName);
+    dgDEBUGOUT (15);
+  }
+
+
+  // The global factory.
+  FactoryStorage g_factory;
+} // end of namespace dynamicgraph.
-- 
GitLab