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

#include "dynamic-graph/factory.h"

#include <boost/foreach.hpp>

#include "dynamic-graph/debug.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.");
Bergé's avatar
Bergé committed
    }

    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)
Bergé's avatar
Bergé committed
    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.