src/core/component-manager.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 30 Aug 2007 13:58:15 +0200
changeset 1399 5945e92014e2
parent 732 df256f32b6ae
child 2230 9f13ac3291e0
permissions -rw-r--r--
move printing to client code

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2007 INRIA
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program 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 Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
 */
#include "component-manager.h"
#include "uid-manager.h"
#include "singleton.h"

namespace ns3 {

// we redefine a UidManager type for the class id singleton below.
// otherwise, we would have to share the same id singleton instance
// with the Iids.
class CidManager : public UidManager
{};

ClassId::ClassId (std::string name)
  : m_classId (Singleton<CidManager>::Get ()->Allocate (name))
{}

ClassId::ClassId (uint32_t classId)
  : m_classId (classId)
{}

std::string 
ClassId::GetName (void) const
{
  return Singleton<CidManager>::Get ()->LookupByUid (m_classId);
}

bool operator == (const ClassId &a, const ClassId &b)
{
  return a.m_classId == b.m_classId;
}

ComponentManager::ClassIdEntry::ClassIdEntry (ClassId classId)
  : m_classId (classId)
{}

Ptr<Object>
ComponentManager::Create (ClassId classId)
{
  Callback<Ptr<Object> > callback = DoGetCallback<empty,empty,empty,empty,empty> (classId);
  return callback ();
}

CallbackBase *
ComponentManager::Lookup (ClassId classId)
{
  List *list = Singleton<List>::Get ();
  for (List::const_iterator i = list->begin (); i != list->end (); i++)
    {
      if (i->m_classId == classId)
	{
	  return i->m_callback;
	}
    }
  return 0;
}

ClassId 
ComponentManager::LookupByName (std::string name)
{
  return ClassId (Singleton<CidManager>::Get ()->LookupByName (name));
}
ClassId 
ComponentManager::LookupByName (std::string name, bool *ok)
{
  uint32_t cid = Singleton<CidManager>::Get ()->LookupByName (name);
  if (cid == 0)
    {
      *ok = false;
    }
  else
    {
      *ok = true;
    }
  return ClassId (cid);
}
std::vector<ClassId> 
ComponentManager::LookupByInterfaceId (InterfaceId iid)
{
  std::vector<ClassId> classIdList;
  List *list = Singleton<List>::Get ();
  for (List::const_iterator i = list->begin (); i != list->end (); i++)
    {
      for (std::vector<const InterfaceId *>::const_iterator j = i->m_supportedInterfaces.begin ();
           j != i->m_supportedInterfaces.end (); j++)
        {
          if (*(*j) == iid)
            {
              classIdList.push_back (i->m_classId);
              break;
            }
        }
    }
  unique (classIdList.begin (), classIdList.end ());
  return classIdList;
}

void
ComponentManager::Register (ClassId classId, CallbackBase *callback, 
                            std::vector<const InterfaceId *> supportedInterfaces)
{
  List *list = Singleton<List>::Get ();
  struct ClassIdEntry entry = ClassIdEntry (classId);
  entry.m_callback = callback;
  bool foundObject = false;
  for (std::vector<const InterfaceId *>::iterator i = supportedInterfaces.begin ();
       i != supportedInterfaces.end (); i++)
    {
      if (*i == &Object::iid)
        {
          foundObject = true;
        }
    }
  if (!foundObject)
    {
      supportedInterfaces.push_back (&Object::iid);
    }
  entry.m_supportedInterfaces = supportedInterfaces;
  list->push_back (entry);
}

void
RegisterCallback (ClassId classId, CallbackBase *callback, std::vector<const InterfaceId *> supportedInterfaces)
{
  return ComponentManager::Register (classId, callback, supportedInterfaces);
}


ClassIdDefaultValue::ClassIdDefaultValue (std::string name, 
                                          std::string help,
                                          const InterfaceId &iid,
                                          std::string defaultValue)
  : DefaultValueBase (name, help),
    m_defaultName (defaultValue),
    m_name (defaultValue),
    m_interfaceId (&iid)
{
  DefaultValueList::Add (this);
}
ClassId 
ClassIdDefaultValue::GetValue (void) const
{
  return ComponentManager::LookupByName (m_name);
}
void 
ClassIdDefaultValue::SetValue (ClassId classId)
{
  m_name = classId.GetName ();
}
void 
ClassIdDefaultValue::SetValue (std::string name)
{
  m_name = name;
}
bool 
ClassIdDefaultValue::DoParseValue (const std::string &value)
{
  bool ok;
  ClassId classId = ComponentManager::LookupByName (value, &ok);
  if (!ok)
    {
      return false;
    }
  std::vector<ClassId> classIdList = ComponentManager::LookupByInterfaceId (*m_interfaceId);
  for (std::vector<ClassId>::const_iterator i = classIdList.begin ();
       i != classIdList.end (); i++)
    {
      if (*i == classId)
        {
          m_name = value;
          return true;
        }
    }
  return false;
}

std::string 
ClassIdDefaultValue::DoGetType (void) const
{
  std::vector<ClassId> classIdList = ComponentManager::LookupByInterfaceId (*m_interfaceId);
  std::ostringstream oss;
  oss << "(";
  for (std::vector<ClassId>::const_iterator i = classIdList.begin ();
       i != classIdList.end (); i++)
    {
      if (i != classIdList.begin ())
        {
          oss << "|";
        }
      oss << i->GetName ();
    }
  oss << ")";
  return oss.str ();
}

std::string 
ClassIdDefaultValue::DoGetDefaultValue (void) const
{
  return m_name;
}




} // namespace ns3

#ifdef RUN_SELF_TESTS

#include "test.h"
#include "object.h"

namespace {


class B : public ns3::Object
{
public:
  static const ns3::InterfaceId iid;
  B ();
};

const ns3::InterfaceId B::iid = MakeInterfaceId ("B", Object::iid);

B::B ()
{
  SetInterfaceId (B::iid);
}


class A : public ns3::Object
{
public:
  static const ns3::ClassId cidZero;
  static const ns3::ClassId cidOneBool;
  static const ns3::ClassId cidOneUi32;
  static const ns3::ClassId cidOther;
  static const ns3::InterfaceId iid;

  A ();
  A (bool);
  A (uint32_t);

  bool m_zeroInvoked;
  bool m_oneBoolInvoked;
  bool m_oneUi32Invoked;

  bool m_bool;
  int m_ui32;
};

const ns3::ClassId A::cidZero = ns3::MakeClassId<A> ("A", A::iid);
const ns3::ClassId A::cidOneBool = ns3::MakeClassId <A,bool> ("ABool", A::iid);
const ns3::ClassId A::cidOneUi32 = ns3::MakeClassId <A,uint32_t> ("AUi32", A::iid);
const ns3::InterfaceId A::iid = ns3::MakeInterfaceId ("A", Object::iid);

A::A ()
  : m_zeroInvoked (true),
    m_oneBoolInvoked (false),
    m_oneUi32Invoked (false)
{
  SetInterfaceId (A::iid);
  ns3::Ptr<B> b = ns3::Create<B> ();
  AddInterface (b);
}

A::A (bool bo)
  : m_zeroInvoked (false),
    m_oneBoolInvoked (true),
    m_oneUi32Invoked (false),
    m_bool (bo)
{
  SetInterfaceId (A::iid);
  ns3::Ptr<B> b = ns3::Create<B> ();
  AddInterface (b);
}

A::A (uint32_t i)
  : m_zeroInvoked (false),
    m_oneBoolInvoked (false),
    m_oneUi32Invoked (true),
    m_ui32 (i)
{
  SetInterfaceId (A::iid);
  ns3::Ptr<B> b = ns3::Create<B> ();
  AddInterface (b);
}

class X : public A
{
public:
  static const ns3::InterfaceId iid;
};
class C : public X
{
public:
  static const ns3::InterfaceId iid;
};
class D : public C
{
public:
  static const ns3::InterfaceId iid;
  static const ns3::ClassId cid;
};

const ns3::InterfaceId X::iid = ns3::MakeInterfaceId ("X", A::iid);
const ns3::InterfaceId C::iid = ns3::MakeInterfaceId ("C", X::iid);
const ns3::InterfaceId D::iid = ns3::MakeInterfaceId ("D", C::iid);
const ns3::ClassId D::cid = ns3::MakeClassId<D> ("D", A::iid, X::iid, C::iid, D::iid);

}

namespace ns3 {

class ComponentManagerTest : public Test
{
public:
  ComponentManagerTest ();
  virtual bool RunTests (void);
};

ComponentManagerTest::ComponentManagerTest ()
  : Test ("ComponentManager")
{}
bool 
ComponentManagerTest::RunTests (void)
{
  bool ok = true;

  Ptr<A> a = 0;
  a = ComponentManager::Create<A> (A::cidZero, A::iid);
  if (a == 0 ||
      !a->m_zeroInvoked)
    {
      ok = false;
    }

  a = ComponentManager::Create<A,bool> (A::cidOneBool, A::iid, true);
  if (a == 0 ||
      !a->m_oneBoolInvoked ||
      !a->m_bool)
    {
      ok = false;
    }

  a = ComponentManager::Create<A,bool> (A::cidOneBool, A::iid, false);
  if (a == 0 ||
      !a->m_oneBoolInvoked ||
      a->m_bool)
    {
      ok = false;
    }

  a = ComponentManager::Create<A,uint32_t> (A::cidOneUi32, A::iid, 10);
  if (a == 0 ||
      !a->m_oneUi32Invoked ||
      a->m_ui32 != 10)
    {
      ok = false;
    }

  a = ComponentManager::Create<A> (A::cidOneUi32, A::iid, (uint32_t)10);
  if (a == 0 ||
      !a->m_oneUi32Invoked ||
      a->m_ui32 != 10)
    {
      ok = false;
    }

  Ptr<B> b = ComponentManager::Create<B,uint32_t> (A::cidOneUi32, B::iid, 10);
  if (b == 0)
    {
      ok = false;
    }

  return ok;
}


static ComponentManagerTest g_unknownManagerTest;

} // namespace ns3

#endif /* RUN_SELF_TESTS */