/* -*- 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 */ #ifndef COMPONENT_MANAGER_H #define COMPONENT_MANAGER_H #include #include #include #include "callback.h" #include "object.h" #include "fatal-error.h" #include "ptr.h" #include "empty.h" #include "default-value.h" namespace { // anonymous namespace for implementation code. template struct ObjectMaker; } namespace ns3 { /** * \brief Unique Identifier for class constructors. * * Instances of this type must be allocated through * the ns3::MakeClassId class. */ class ClassId { public: /** * \returns the symbolic name associated to this class id * * This name is the name which was associated to this class id * by the ns3::Ns3UnknownManager::RegisterConstructor methods. * This name is also the name which is expected to be input * to ns3::UnknownManager::LookupByName. */ std::string GetName (void) const; protected: ClassId (std::string name); private: ClassId (uint32_t classId); friend class ComponentManager; friend bool operator == (const ClassId &a, const ClassId &b); uint32_t m_classId; }; /** * \brief a class used to create ClassIds * * */ template class MakeClassId : public ClassId { public: /** * \param name name of ClassId * * Create a ClassId with specified name. */ MakeClassId (std::string name); /** * \param name name of ClassId * \param iid interface id * * Create a ClassId with specified name. Register iid * as a supported interface. */ MakeClassId (std::string name, InterfaceId iid); /** * \param name name of ClassId * \param iid0 interface id * \param iid1 interface id * * Create a ClassId with specified name. Register iid0 and iid1 * as supported interfaces. */ MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1); /** * \param name name of ClassId * \param iid0 interface id * \param iid1 interface id * \param iid2 interface id * * Create a ClassId with specified name. Register iid0, iid1 * and iid2 as supported interfaces. */ MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1, InterfaceId iid2); /** * \param name name of ClassId * \param iid0 interface id * \param iid1 interface id * \param iid2 interface id * \param iid3 interface id * * Create a ClassId with specified name. Register iid0, iid1 * iid2, and iid3 as supported interfaces. */ MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1, InterfaceId iid2, InterfaceId iid3); /** * \param name name of ClassId * \param iid0 interface id * \param iid1 interface id * \param iid2 interface id * \param iid3 interface id * \param iid4 interface id * * Create a ClassId with specified name. Register iid0, iid1 * iid2, iid3, and iid4 as supported interfaces. */ MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1, InterfaceId iid2, InterfaceId iid3, InterfaceId iid4); private: typedef ObjectMaker MakerType; static Callback,T1,T2,T3,T4,T5> m_callback; void Register (InterfaceId array [], uint32_t n); }; /** * \brief Create any Interface * * This class keeps track of a set of ClassId, each * of which uniquely identifies the constructor of an * object which derives from the Interface base class. * This class can also create an instance of any of * the objects tracked through any of their tracked * constructor/ClassId. */ class ComponentManager { public: /** * \param name the symbolic name to lookup * \returns the ClassId associated to the input name. */ static ClassId LookupByName (std::string name); static ClassId LookupByName (std::string name, bool *ok); /** * \param iid interface id to lookup * \returns the list of ClassId which can be used to * create objects which support the requested * interface. * * Note that this method will not necessarily return the * complete list of objects which support a given interface * since dynamic aggregation of objects is not under * the control of this class. */ static std::vector LookupByInterfaceId (InterfaceId iid); /** * \param classId class id of the constructor to invoke. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId. This method invokes the default constructor. */ static Ptr Create (ClassId classId); /** * \param classId class id of the constructor to invoke. * \param a1 argument to pass to the constructor. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId. */ template static Ptr Create (ClassId classId, T1 a1); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to the constructor. * \param a2 second argument to pass to the constructor. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to the constructor. * \param a2 second argument to pass to the constructor. * \param a3 third argument to pass to the constructor. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2, T3 a3); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to the constructor. * \param a2 second argument to pass to the constructor. * \param a3 third argument to pass to the constructor. * \param a4 fourth argument to pass to the constructor. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to the constructor. * \param a2 second argument to pass to the constructor. * \param a3 third argument to pass to the constructor. * \param a4 fourth argument to pass to the constructor. * \param a5 fifth argument to pass to the constructor. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); /** * \param classId class id of the constructor to invoke. * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId, call QueryInterface on it, and return the * result. */ template static Ptr Create (ClassId classId); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to constructor * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId, call QueryInterface on it, and return the * result. */ template static Ptr Create (ClassId classId, T1 a1); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to constructor * \param a2 second argument to pass to constructor * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId, call QueryInterface on it, and return the * result. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to constructor * \param a2 second argument to pass to constructor * \param a3 third argument to pass to constructor * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId, call QueryInterface on it, and return the * result. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2, T3 a3); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to constructor * \param a2 second argument to pass to constructor * \param a3 third argument to pass to constructor * \param a4 fourth argument to pass to constructor * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId, call QueryInterface on it, and return the * result. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4); /** * \param classId class id of the constructor to invoke. * \param a1 first argument to pass to constructor * \param a2 second argument to pass to constructor * \param a3 third argument to pass to constructor * \param a4 fourth argument to pass to constructor * \param a5 fifth argument to pass to constructor * \return a pointer to the instance created. * * Create an instance of the object identified by its * ClassId, call QueryInterface on it, and return the * result. */ template static Ptr Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); private: friend void RegisterCallback (ClassId classId, CallbackBase *callback, std::vector supportedInterfaces); static void Register (ClassId classId, CallbackBase *callback, std::vector supportedInterfaces); template static Callback,T1,T2,T3,T4,T5> DoGetCallback (ClassId classId); struct ClassIdEntry { ClassIdEntry (ClassId classId); ClassId m_classId; CallbackBase *m_callback; std::vector m_supportedInterfaces; }; typedef std::vector List; static List *GetList (void); static CallbackBase *Lookup (ClassId classId); }; /** * \brief a DefaultValue class to handle ClassIds * * This class provides the necessary glue to allow * the Bind function and the command-line arguments * to control the type of an object to create. */ class ClassIdDefaultValue : public DefaultValueBase { public: /** * \param name the name of this default value. * \param help the help text associated to this default value * \param iid the interface id which all objects created * through this "default value" must support. * \param defaultValue the name of the object to create * by default. */ ClassIdDefaultValue (std::string name, std::string help, InterfaceId iid, std::string defaultValue); /** * \returns the ClassId of the object selected by the user. */ ClassId GetValue (void) const; /** * \param classId the new ClassId selected. * * Override the currently-selected value. */ void SetValue (ClassId classId); /** * \param name the new object selected. * * Override the currently-selected value. */ void SetValue (std::string name); private: virtual bool DoParseValue (const std::string &value); virtual std::string DoGetType (void) const; virtual std::string DoGetDefaultValue (void) const; std::string m_defaultName; std::string m_name; InterfaceId m_interfaceId; }; } // namespace ns3 namespace { template struct ObjectMaker { static ns3::Ptr MakeObject (void) { return ns3::CreateObject (); } }; template struct ObjectMaker { static ns3::Ptr MakeObject (T1 a1) { return ns3::CreateObject (a1); } }; template struct ObjectMaker { static ns3::Ptr MakeObject (T1 a1, T2 a2) { return ns3::CreateObject (a1, a2); } }; template struct ObjectMaker { static ns3::Ptr MakeObject (T1 a1, T2 a2, T3 a3) { return ns3::CreateObject (a1, a2, a3); } }; template struct ObjectMaker { static ns3::Ptr MakeObject (T1 a1, T2 a2, T3 a3, T4 a4) { return ns3::CreateObject (a1, a2, a3, a4); } }; template struct ObjectMaker { static ns3::Ptr MakeObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { return ns3::CreateObject (a1, a2, a3, a4, a5); } }; } // anonymous namespace namespace ns3 { void RegisterCallback (ClassId classId, ns3::CallbackBase *callback, std::vector supportedInterfaces); template void MakeClassId::Register (InterfaceId array [], uint32_t n) { std::vector supportedInterfaces; for (uint32_t i = 0; i < n; i++) { supportedInterfaces.push_back (array[i]); } RegisterCallback (*this, &m_callback, supportedInterfaces); } template MakeClassId::MakeClassId (std::string name) : ClassId (name) { InterfaceId array[] = {}; Register (array, sizeof (array)/sizeof(InterfaceId)); } template MakeClassId::MakeClassId (std::string name, InterfaceId iid) : ClassId (name) { InterfaceId array[] = {iid}; Register (array, sizeof (array)/sizeof(InterfaceId)); } template MakeClassId::MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1) : ClassId (name) { InterfaceId array[] = {iid0, iid1}; Register (array, sizeof (array)/sizeof(InterfaceId)); } template MakeClassId::MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1, InterfaceId iid2) : ClassId (name) { InterfaceId array[] = {iid0, iid1, iid2}; Register (array, sizeof (array)/sizeof(InterfaceId)); } template MakeClassId::MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1, InterfaceId iid2, InterfaceId iid3) : ClassId (name) { InterfaceId array[] = {iid0, iid1, iid2, iid3}; Register (array, sizeof (array)/sizeof(InterfaceId)); } template MakeClassId::MakeClassId (std::string name, InterfaceId iid0, InterfaceId iid1, InterfaceId iid2, InterfaceId iid3, InterfaceId iid4) : ClassId (name) { InterfaceId array[] = {iid0, iid1, iid2, iid3, iid4}; Register (array, sizeof (array)/sizeof(InterfaceId)); } template Callback,T1,T2,T3,T4,T5> MakeClassId::m_callback = MakeCallback (&MakeClassId::MakerType::MakeObject); template Callback,T1,T2,T3,T4,T5> ComponentManager::DoGetCallback (ClassId classId) { CallbackBase *callback = Lookup (classId); if (callback == 0) { NS_FATAL_ERROR ("Invalid Class Id."); } Callback,T1,T2,T3,T4,T5> reference; reference.Assign (*callback); return reference; } template Ptr ComponentManager::Create (ClassId classId, T1 a1) { Callback,T1> callback = DoGetCallback (classId); return callback (a1); } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2) { Callback,T1,T2> callback = DoGetCallback (classId); return callback (a1, a2); } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3) { Callback,T1,T2,T3> callback = DoGetCallback (classId); return callback (a1, a2, a3); } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4) { Callback,T1,T2,T3,T4> callback = DoGetCallback (classId); return callback (a1, a2, a3, a4); } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { Callback,T1,T2,T3,T4,T5> callback = DoGetCallback (classId); return callback (a1, a2, a3, a4, a5); } template Ptr ComponentManager::Create (ClassId classId) { Ptr obj = Create (classId); Ptr i = obj->QueryInterface (); return i; } template Ptr ComponentManager::Create (ClassId classId, T1 a1) { Ptr obj = Create (classId, a1); Ptr i = obj->QueryInterface (); return i; } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2) { Ptr obj = Create (classId, a1, a2); Ptr i = obj->QueryInterface (); return i; } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3) { Ptr obj = Create (classId, a1, a2, a3); Ptr i = obj->QueryInterface (); return i; } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4) { Ptr obj = Create (classId, a1, a2, a3, a4); Ptr i = obj->QueryInterface (); return i; } template Ptr ComponentManager::Create (ClassId classId, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { Ptr obj = Create (classId, a1, a2, a3, a4, a5); Ptr i = obj->QueryInterface (); return i; } } // namespace ns3 #endif /* COMPONENT_MANAGER_H */