Skip to content
Snippets Groups Projects
factory.cpp 3.85 KiB
Newer Older
// Copyright 2010, François Bleibel, Thomas Moulard, Olivier Stasse,
// JRL, CNRS/AIST.
//

#include <boost/foreach.hpp>

#include "dynamic-graph/debug.h"
#include "dynamic-graph/factory.h"

using namespace std;
using namespace dynamicgraph;

namespace dynamicgraph
{
  FactoryStorage* FactoryStorage::getInstance()
  {
    if (instance_ == 0)
      {
        instance_ = new FactoryStorage;
      }
    return instance_;
Bergé's avatar
Bergé committed

void FactoryStorage::destroy()
{
Bergé's avatar
Bergé committed
  delete instance_;
  instance_ = NULL;
}

FactoryStorage::FactoryStorage() : entityMap() {}

FactoryStorage::~FactoryStorage()
{
Bergé's avatar
Bergé committed
  instance_ = 0;
  dgDEBUGINOUT(25);
}

void FactoryStorage::
registerEntity
(const std::string& entname, FactoryStorage::EntityConstructor_ptr ent)
{
Bergé's avatar
Bergé committed
  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 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;
Bergé's avatar
Bergé committed
    }
  dgDEBUGOUT(25);
}

void FactoryStorage::deregisterEntity(const std::string& entname)
{
Bergé's avatar
Bergé committed
  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);
    }
Bergé's avatar
Bergé committed
  dgDEBUGOUT(25);
}
Entity* FactoryStorage::newEntity
(const std::string& classname, const std::string& objname) const
{
  dgDEBUG(15) << "New <" << classname << ">Entity <"
              << objname << ">" << std::endl;
Bergé's avatar
Bergé committed
  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());
    }
Bergé's avatar
Bergé committed
  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
{
Bergé's avatar
Bergé committed
  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
{
Bergé's avatar
Bergé committed
  typedef std::pair<std::string, EntityConstructor_ptr> iter_t;
  BOOST_FOREACH (const iter_t& entity, entityMap)
    outList.push_back(entity.first);
}

EntityRegisterer::EntityRegisterer
(const std::string& entityClassName,
 FactoryStorage::EntityConstructor_ptr maker)
    : entityName(entityClassName)
{
Bergé's avatar
Bergé committed
  dgDEBUGIN(15);
  FactoryStorage::getInstance()->registerEntity(entityClassName, maker);
  dgDEBUGOUT(15);
}

EntityRegisterer::~EntityRegisterer()
{
Bergé's avatar
Bergé committed
  dgDEBUGIN(15);
  FactoryStorage::getInstance()->deregisterEntity(entityName);
  dgDEBUGOUT(15);
}

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