Skip to content
Snippets Groups Projects
factory.cpp 5.11 KiB
Newer Older
// 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;

namespace dynamicgraph
{
  FactoryStorage::FactoryStorage ()
    : entityMap ()
  {}
  FactoryStorage::~FactoryStorage ()
  {
    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);
  }
  // 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));
  //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);
  }
  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;
  }



  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.