src/core/object.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sun, 02 Mar 2008 21:00:37 +0100
changeset 2531 b451b5fc8b57
parent 2529 d5f8bee5fcbd
child 2542 a9b88fdc09d6
permissions -rw-r--r--
implement context-based trace connection
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2007 INRIA, Gustavo Carneiro
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
    19  *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    20  */
    21 #include "object.h"
    22 #include "assert.h"
    23 #include "singleton.h"
    24 #include "trace-resolver.h"
    25 #include "attribute.h"
    26 #include "trace-source-accessor.h"
    27 #include "log.h"
    28 #include "string.h"
    29 #include <vector>
    30 #include <sstream>
    31 
    32 NS_LOG_COMPONENT_DEFINE ("Object");
    33 
    34 /*********************************************************************
    35  *         Helper code
    36  *********************************************************************/
    37 
    38 namespace {
    39 
    40 class IidManager
    41 {
    42 public:
    43   IidManager ();
    44   uint16_t AllocateUid (std::string name);
    45   void SetParent (uint16_t uid, uint16_t parent);
    46   void SetTypeName (uint16_t uid, std::string typeName);
    47   void SetGroupName (uint16_t uid, std::string groupName);
    48   void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
    49   uint16_t GetUid (std::string name) const;
    50   std::string GetName (uint16_t uid) const;
    51   uint16_t GetParent (uint16_t uid) const;
    52   std::string GetTypeName (uint16_t uid) const;
    53   std::string GetGroupName (uint16_t uid) const;
    54   ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
    55   bool HasConstructor (uint16_t uid);
    56   uint32_t GetRegisteredN (void);
    57   uint16_t GetRegistered (uint32_t i);
    58   void AddAttribute (uint16_t uid, 
    59                      std::string name,
    60                      std::string help, 
    61                      uint32_t flags,
    62                      ns3::Attribute initialValue,
    63                      ns3::Ptr<const ns3::AttributeAccessor> spec,
    64                      ns3::Ptr<const ns3::AttributeChecker> checker);
    65   uint32_t GetAttributeListN (uint16_t uid) const;
    66   std::string GetAttributeName (uint16_t uid, uint32_t i) const;
    67   uint32_t GetAttributeFlags (uint16_t uid, uint32_t i) const;
    68   ns3::Attribute GetAttributeInitialValue (uint16_t uid, uint32_t i) const;
    69   ns3::Ptr<const ns3::AttributeAccessor> GetAttributeAccessor (uint16_t uid, uint32_t i) const;
    70   ns3::Ptr<const ns3::AttributeChecker> GetAttributeChecker (uint16_t uid, uint32_t i) const;
    71   void AddTraceSource (uint16_t uid,
    72                        std::string name, 
    73                        std::string help,
    74                        ns3::Ptr<const ns3::TraceSourceAccessor> accessor);
    75   uint32_t GetTraceSourceN (uint16_t uid) const;
    76   std::string GetTraceSourceName (uint16_t uid, uint32_t i) const;
    77   std::string GetTraceSourceHelp (uint16_t uid, uint32_t i) const;
    78   ns3::Ptr<const ns3::TraceSourceAccessor> GetTraceSourceAccessor (uint16_t uid, uint32_t i) const;
    79 
    80 private:
    81   struct ConstructorInformation {
    82     ns3::CallbackBase cb;
    83     uint32_t nArguments;
    84   };
    85   struct AttributeInformation {
    86     std::string name;
    87     std::string help;
    88     uint32_t flags;
    89     ns3::Attribute initialValue;
    90     ns3::Ptr<const ns3::AttributeAccessor> param;
    91     ns3::Ptr<const ns3::AttributeChecker> checker;
    92   };
    93   struct TraceSourceInformation {
    94     std::string name;
    95     std::string help;
    96     ns3::Ptr<const ns3::TraceSourceAccessor> accessor;
    97   };
    98   struct IidInformation {
    99     std::string name;
   100     uint16_t parent;
   101     std::string typeName;
   102     std::string groupName;
   103     std::vector<struct ConstructorInformation> constructors;
   104     std::vector<struct AttributeInformation> attributes;
   105     std::vector<struct TraceSourceInformation> traceSources;
   106   };
   107   typedef std::vector<struct IidInformation>::const_iterator Iterator;
   108 
   109   struct IidManager::IidInformation *LookupInformation (uint16_t uid) const;
   110 
   111   std::vector<struct IidInformation> m_information;
   112 };
   113 
   114 IidManager::IidManager ()
   115 {}
   116 
   117 uint16_t 
   118 IidManager::AllocateUid (std::string name)
   119 {
   120   uint16_t j = 1;
   121   for (Iterator i = m_information.begin (); i != m_information.end (); i++)
   122     {
   123       if (i->name == name)
   124         {
   125           NS_FATAL_ERROR ("Trying to allocate twice the same uid: " << name);
   126           return 0;
   127         }
   128       j++;
   129     }
   130   struct IidInformation information;
   131   information.name = name;
   132   information.parent = 0;
   133   information.typeName = "";
   134   information.groupName = "";
   135   m_information.push_back (information);
   136   uint32_t uid = m_information.size ();
   137   NS_ASSERT (uid <= 0xffff);
   138   return uid;
   139 }
   140 
   141 struct IidManager::IidInformation *
   142 IidManager::LookupInformation (uint16_t uid) const
   143 {
   144   NS_ASSERT (uid <= m_information.size ());
   145   return const_cast<struct IidInformation *> (&m_information[uid-1]);
   146 }
   147 
   148 void 
   149 IidManager::SetParent (uint16_t uid, uint16_t parent)
   150 {
   151   NS_ASSERT (parent <= m_information.size ());
   152   struct IidInformation *information = LookupInformation (uid);
   153   information->parent = parent;
   154 }
   155 void 
   156 IidManager::SetTypeName (uint16_t uid, std::string typeName)
   157 {
   158   struct IidInformation *information = LookupInformation (uid);
   159   information->typeName = typeName;
   160 }
   161 void 
   162 IidManager::SetGroupName (uint16_t uid, std::string groupName)
   163 {
   164   struct IidInformation *information = LookupInformation (uid);
   165   information->groupName = groupName;
   166 }
   167 
   168 void 
   169 IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
   170 {
   171   struct IidInformation *information = LookupInformation (uid);
   172   struct ConstructorInformation constructor;
   173   constructor.cb = callback;
   174   constructor.nArguments = nArguments;
   175   for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
   176        i != information->constructors.end (); i++)
   177     {
   178       if (i->nArguments == nArguments)
   179         {
   180           NS_FATAL_ERROR ("registered two constructors on the same type with the same number of arguments.");
   181           break;
   182         }
   183     }
   184   information->constructors.push_back (constructor);
   185 }
   186 
   187 uint16_t 
   188 IidManager::GetUid (std::string name) const
   189 {
   190   uint32_t j = 1;
   191   for (Iterator i = m_information.begin (); i != m_information.end (); i++)
   192     {
   193       if (i->name == name)
   194         {
   195           NS_ASSERT (j <= 0xffff);
   196           return j;
   197         }
   198       j++;
   199     }
   200   return 0;
   201 }
   202 std::string 
   203 IidManager::GetName (uint16_t uid) const
   204 {
   205   struct IidInformation *information = LookupInformation (uid);
   206   return information->name;
   207 }
   208 uint16_t 
   209 IidManager::GetParent (uint16_t uid) const
   210 {
   211   struct IidInformation *information = LookupInformation (uid);
   212   return information->parent;
   213 }
   214 std::string 
   215 IidManager::GetTypeName (uint16_t uid) const
   216 {
   217   struct IidInformation *information = LookupInformation (uid);
   218   return information->typeName;
   219 }
   220 std::string 
   221 IidManager::GetGroupName (uint16_t uid) const
   222 {
   223   struct IidInformation *information = LookupInformation (uid);
   224   return information->groupName;
   225 }
   226 
   227 ns3::CallbackBase 
   228 IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
   229 {
   230   struct IidInformation *information = LookupInformation (uid);
   231   for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
   232        i != information->constructors.end (); i++)
   233     {
   234       if (i->nArguments == nArguments)
   235         {
   236           return i->cb;
   237         } 
   238     }
   239   NS_FATAL_ERROR ("Requested constructor with "<<nArguments<<" arguments not found");
   240   return ns3::CallbackBase ();
   241 }
   242 
   243 bool 
   244 IidManager::HasConstructor (uint16_t uid)
   245 {
   246   struct IidInformation *information = LookupInformation (uid);
   247   return !information->constructors.empty ();
   248 }
   249 
   250 uint32_t 
   251 IidManager::GetRegisteredN (void)
   252 {
   253   return m_information.size ();
   254 }
   255 uint16_t 
   256 IidManager::GetRegistered (uint32_t i)
   257 {
   258   return i + 1;
   259 }
   260 
   261 void 
   262 IidManager::AddAttribute (uint16_t uid, 
   263                           std::string name,
   264                           std::string help, 
   265                           uint32_t flags,
   266                           ns3::Attribute initialValue,
   267                           ns3::Ptr<const ns3::AttributeAccessor> spec,
   268                           ns3::Ptr<const ns3::AttributeChecker> checker)
   269 {
   270   struct IidInformation *information = LookupInformation (uid);
   271   for (std::vector<struct AttributeInformation>::const_iterator j = information->attributes.begin ();
   272        j != information->attributes.end (); j++)
   273     {
   274       if (j->name == name)
   275         {
   276           NS_FATAL_ERROR ("Registered the same attribute twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
   277           return;
   278         }
   279     }
   280   struct AttributeInformation param;
   281   param.name = name;
   282   param.help = help;
   283   param.flags = flags;
   284   param.initialValue = initialValue;
   285   param.param = spec;
   286   param.checker = checker;
   287   information->attributes.push_back (param);
   288 }
   289 
   290 
   291 uint32_t 
   292 IidManager::GetAttributeListN (uint16_t uid) const
   293 {
   294   struct IidInformation *information = LookupInformation (uid);
   295   return information->attributes.size ();
   296 }
   297 std::string 
   298 IidManager::GetAttributeName (uint16_t uid, uint32_t i) const
   299 {
   300   struct IidInformation *information = LookupInformation (uid);
   301   NS_ASSERT (i < information->attributes.size ());
   302   return information->attributes[i].name;
   303 }
   304 uint32_t
   305 IidManager::GetAttributeFlags (uint16_t uid, uint32_t i) const
   306 {
   307   struct IidInformation *information = LookupInformation (uid);
   308   NS_ASSERT (i < information->attributes.size ());
   309   return information->attributes[i].flags;
   310 }
   311 ns3::Attribute 
   312 IidManager::GetAttributeInitialValue (uint16_t uid, uint32_t i) const
   313 {
   314   struct IidInformation *information = LookupInformation (uid);
   315   NS_ASSERT (i < information->attributes.size ());
   316   return information->attributes[i].initialValue;
   317 }
   318 ns3::Ptr<const ns3::AttributeAccessor>
   319 IidManager::GetAttributeAccessor (uint16_t uid, uint32_t i) const
   320 {
   321   struct IidInformation *information = LookupInformation (uid);
   322   NS_ASSERT (i < information->attributes.size ());
   323   return information->attributes[i].param;
   324 }
   325 ns3::Ptr<const ns3::AttributeChecker>
   326 IidManager::GetAttributeChecker (uint16_t uid, uint32_t i) const
   327 {
   328   struct IidInformation *information = LookupInformation (uid);
   329   NS_ASSERT (i < information->attributes.size ());
   330   return information->attributes[i].checker;
   331 }
   332 
   333 void 
   334 IidManager::AddTraceSource (uint16_t uid,
   335                             std::string name, 
   336                             std::string help,
   337                             ns3::Ptr<const ns3::TraceSourceAccessor> accessor)
   338 {
   339   struct IidInformation *information  = LookupInformation (uid);
   340   struct TraceSourceInformation source;
   341   source.name = name;
   342   source.help = help;
   343   source.accessor = accessor;
   344   information->traceSources.push_back (source);
   345 }
   346 uint32_t 
   347 IidManager::GetTraceSourceN (uint16_t uid) const
   348 {
   349   struct IidInformation *information = LookupInformation (uid);
   350   return information->traceSources.size ();
   351 }
   352 std::string 
   353 IidManager::GetTraceSourceName (uint16_t uid, uint32_t i) const
   354 {
   355   struct IidInformation *information = LookupInformation (uid);
   356   NS_ASSERT (i < information->traceSources.size ());
   357   return information->traceSources[i].name;
   358 }
   359 std::string 
   360 IidManager::GetTraceSourceHelp (uint16_t uid, uint32_t i) const
   361 {
   362   struct IidInformation *information = LookupInformation (uid);
   363   NS_ASSERT (i < information->traceSources.size ());
   364   return information->traceSources[i].help;
   365 }
   366 ns3::Ptr<const ns3::TraceSourceAccessor> 
   367 IidManager::GetTraceSourceAccessor (uint16_t uid, uint32_t i) const
   368 {
   369   struct IidInformation *information = LookupInformation (uid);
   370   NS_ASSERT (i < information->traceSources.size ());
   371   return information->traceSources[i].accessor;
   372 }
   373 
   374 } // anonymous namespace
   375 
   376 /*********************************************************************
   377  *         The TypeId TraceResolver
   378  *********************************************************************/
   379 
   380 namespace ns3 {
   381 
   382 class TypeIdTraceResolver : public TraceResolver
   383 {
   384 public:
   385   TypeIdTraceResolver (Ptr<const Object> aggregate);
   386   virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
   387   virtual void Disconnect (std::string path, CallbackBase const &cb);
   388   virtual void CollectSources (std::string path, const TraceContext &context, 
   389                                SourceCollection *collection);
   390   virtual void TraceAll (std::ostream &os, const TraceContext &context);
   391 private:
   392   Ptr<const Object> ParseForInterface (std::string path);
   393   Ptr<const Object> m_aggregate;
   394 };
   395 
   396 TypeIdTraceResolver::TypeIdTraceResolver (Ptr<const Object> aggregate)
   397   : m_aggregate (aggregate)
   398 {}
   399 Ptr<const Object>
   400 TypeIdTraceResolver::ParseForInterface (std::string path)
   401 {
   402   std::string element = GetElement (path);
   403   std::string::size_type dollar_pos = element.find ("$");
   404   if (dollar_pos != 0)
   405     {
   406       return 0;
   407     }
   408   std::string interfaceName = element.substr (1, std::string::npos);
   409   TypeId interfaceId = TypeId::LookupByName (interfaceName);
   410   Ptr<Object> interface = m_aggregate->GetObject<Object> (interfaceId);
   411   return interface;
   412 }
   413 void  
   414 TypeIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
   415 {
   416   Ptr<const Object> interface = ParseForInterface (path);
   417   if (interface != 0)
   418     {
   419       interface->GetTraceResolver ()->Connect (GetSubpath (path), cb, context);
   420     }
   421 }
   422 void 
   423 TypeIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
   424 {
   425   Ptr<const Object> interface = ParseForInterface (path);
   426   if (interface != 0)
   427     {
   428       interface->TraceDisconnect (GetSubpath (path), cb);
   429     }
   430 }
   431 void 
   432 TypeIdTraceResolver::CollectSources (std::string path, const TraceContext &context, 
   433                                           SourceCollection *collection)
   434 {
   435   m_aggregate->DoCollectSources (path, context, collection);
   436 }
   437 void 
   438 TypeIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
   439 {
   440   m_aggregate->DoTraceAll (os, context);
   441 }
   442 
   443 /*********************************************************************
   444  *         The TypeId class
   445  *********************************************************************/
   446 
   447 TypeId::TypeId ()
   448   : m_tid (0)
   449 {}
   450 
   451 TypeId::TypeId (const char * name)
   452 {
   453   uint16_t uid = Singleton<IidManager>::Get ()->AllocateUid (name);
   454   NS_ASSERT (uid != 0);
   455   m_tid = uid;
   456 }
   457 
   458 
   459 TypeId::TypeId (uint16_t tid)
   460   : m_tid (tid)
   461 {}
   462 TypeId::~TypeId ()
   463 {}
   464 TypeId 
   465 TypeId::LookupByName (std::string name)
   466 {
   467   uint16_t uid = Singleton<IidManager>::Get ()->GetUid (name);
   468   NS_ASSERT (uid != 0);
   469   return TypeId (uid);
   470 }
   471 bool
   472 TypeId::LookupAttributeByFullName (std::string fullName, struct TypeId::AttributeInfo *info)
   473 {
   474   std::string::size_type pos = fullName.find ("::");
   475   if (pos == std::string::npos)
   476     {
   477       return 0;
   478     }
   479   std::string tidName = fullName.substr (0, pos);
   480   std::string paramName = fullName.substr (pos+2, fullName.size () - (pos+2));
   481   TypeId tid = LookupByName (tidName);
   482   return tid.LookupAttributeByName (paramName, info);
   483 }
   484 uint32_t 
   485 TypeId::GetRegisteredN (void)
   486 {
   487   return Singleton<IidManager>::Get ()->GetRegisteredN ();
   488 }
   489 TypeId 
   490 TypeId::GetRegistered (uint32_t i)
   491 {
   492   return TypeId (Singleton<IidManager>::Get ()->GetRegistered (i));
   493 }
   494 
   495 bool
   496 TypeId::LookupAttributeByName (std::string name, struct TypeId::AttributeInfo *info) const
   497 {
   498   TypeId tid;
   499   TypeId nextTid = *this;
   500   do {
   501     tid = nextTid;
   502     for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
   503       {
   504         std::string paramName = tid.GetAttributeName (i);
   505         if (paramName == name)
   506           {
   507             info->accessor = tid.GetAttributeAccessor (i);
   508             info->flags = tid.GetAttributeFlags (i);
   509             info->initialValue = tid.GetAttributeInitialValue (i);
   510             info->checker = tid.GetAttributeChecker (i);
   511             return true;
   512           }
   513       }
   514     nextTid = tid.GetParent ();
   515   } while (nextTid != tid);
   516   return false;
   517 }
   518 bool
   519 TypeId::LookupAttributeByPosition (uint32_t i, struct TypeId::AttributeInfo *info) const
   520 {
   521   uint32_t cur = 0;
   522   TypeId tid;
   523   TypeId nextTid = *this;
   524   do {
   525     tid = nextTid;
   526     for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
   527       {
   528         if (cur == i)
   529           {
   530             info->accessor = tid.GetAttributeAccessor (j);
   531             info->flags = tid.GetAttributeFlags (j);
   532             info->initialValue = tid.GetAttributeInitialValue (j);
   533             info->checker = tid.GetAttributeChecker (j);
   534             return true;
   535           }
   536         cur++;
   537       }
   538     nextTid = tid.GetParent ();
   539   } while (nextTid != tid);
   540   return false;
   541 }
   542 
   543 
   544 TypeId 
   545 TypeId::SetParent (TypeId tid)
   546 {
   547   Singleton<IidManager>::Get ()->SetParent (m_tid, tid.m_tid);
   548   return *this;
   549 }
   550 TypeId 
   551 TypeId::SetGroupName (std::string groupName)
   552 {
   553   Singleton<IidManager>::Get ()->SetGroupName (m_tid, groupName);
   554   return *this;
   555 }
   556 TypeId 
   557 TypeId::SetTypeName (std::string typeName)
   558 {
   559   Singleton<IidManager>::Get ()->SetTypeName (m_tid, typeName);
   560   return *this;
   561 }
   562 TypeId 
   563 TypeId::GetParent (void) const
   564 {
   565   uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
   566   return TypeId (parent);
   567 }
   568 std::string 
   569 TypeId::GetGroupName (void) const
   570 {
   571   std::string groupName = Singleton<IidManager>::Get ()->GetGroupName (m_tid);
   572   return groupName;
   573 }
   574 std::string 
   575 TypeId::GetTypeName (void) const
   576 {
   577   std::string typeName = Singleton<IidManager>::Get ()->GetTypeName (m_tid);
   578   return typeName;
   579 }
   580 
   581 std::string 
   582 TypeId::GetName (void) const
   583 {
   584   std::string name = Singleton<IidManager>::Get ()->GetName (m_tid);
   585   return name;
   586 }
   587 
   588 bool 
   589 TypeId::HasConstructor (void) const
   590 {
   591   bool hasConstructor = Singleton<IidManager>::Get ()->HasConstructor (m_tid);
   592   return hasConstructor;
   593 }
   594 
   595 void
   596 TypeId::DoAddConstructor (CallbackBase cb, uint32_t nArguments)
   597 {
   598   Singleton<IidManager>::Get ()->AddConstructor (m_tid, cb, nArguments);
   599 }
   600 
   601 TypeId 
   602 TypeId::AddAttribute (std::string name,
   603                       std::string help, 
   604                       Attribute initialValue,
   605                       Ptr<const AttributeAccessor> param,
   606                       Ptr<const AttributeChecker> checker)
   607 {
   608   Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, ATTR_SGC, initialValue, param, checker);
   609   return *this;
   610 }
   611 
   612 TypeId 
   613 TypeId::AddAttribute (std::string name,
   614                       std::string help, 
   615                       uint32_t flags,
   616                       Attribute initialValue,
   617                       Ptr<const AttributeAccessor> param,
   618                       Ptr<const AttributeChecker> checker)
   619 {
   620   Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, flags, initialValue, param, checker);
   621   return *this;
   622 }
   623 
   624 
   625 CallbackBase
   626 TypeId::LookupConstructor (uint32_t nArguments) const
   627 {
   628   CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_tid, nArguments);
   629   return constructor;
   630 }
   631 
   632 Ptr<Object> 
   633 TypeId::CreateObject (void) const
   634 {
   635   return CreateObject (AttributeList ());
   636 }
   637 Ptr<Object> 
   638 TypeId::CreateObject (const AttributeList &attributes) const
   639 {
   640   CallbackBase cb = LookupConstructor (0);
   641   Callback<Ptr<Object>,const AttributeList &> realCb;
   642   realCb.Assign (cb);
   643   Ptr<Object> object = realCb (attributes);
   644   return object;  
   645 }
   646 
   647 uint32_t 
   648 TypeId::GetAttributeListN (void) const
   649 {
   650   uint32_t n = Singleton<IidManager>::Get ()->GetAttributeListN (m_tid);
   651   return n;
   652 }
   653 std::string 
   654 TypeId::GetAttributeName (uint32_t i) const
   655 {
   656   std::string name = Singleton<IidManager>::Get ()->GetAttributeName (m_tid, i);
   657   return name;
   658 }
   659 std::string 
   660 TypeId::GetAttributeFullName (uint32_t i) const
   661 {
   662   return GetName () + "::" + GetAttributeName (i);
   663 }
   664 Attribute 
   665 TypeId::GetAttributeInitialValue (uint32_t i) const
   666 {
   667   Attribute value = Singleton<IidManager>::Get ()->GetAttributeInitialValue (m_tid, i);
   668   return value;
   669 }
   670 Ptr<const AttributeAccessor>
   671 TypeId::GetAttributeAccessor (uint32_t i) const
   672 {
   673   // Used exclusively by the Object class.
   674   Ptr<const AttributeAccessor> param = Singleton<IidManager>::Get ()->GetAttributeAccessor (m_tid, i);
   675   return param;
   676 }
   677 uint32_t 
   678 TypeId::GetAttributeFlags (uint32_t i) const
   679 {
   680   // Used exclusively by the Object class.
   681   uint32_t flags = Singleton<IidManager>::Get ()->GetAttributeFlags (m_tid, i);
   682   return flags;
   683 }
   684 Ptr<const AttributeChecker>
   685 TypeId::GetAttributeChecker (uint32_t i) const
   686 {
   687   // Used exclusively by the Object class.
   688   Ptr<const AttributeChecker> checker = Singleton<IidManager>::Get ()->GetAttributeChecker (m_tid, i);
   689   return checker;
   690 }
   691 
   692 uint32_t 
   693 TypeId::GetTraceSourceN (void) const
   694 {
   695   return Singleton<IidManager>::Get ()->GetTraceSourceN (m_tid);
   696 }
   697 std::string 
   698 TypeId::GetTraceSourceName (uint32_t i) const
   699 {
   700   return Singleton<IidManager>::Get ()->GetTraceSourceName (m_tid, i);
   701 }
   702 std::string 
   703 TypeId::GetTraceSourceHelp (uint32_t i) const
   704 {
   705   return Singleton<IidManager>::Get ()->GetTraceSourceHelp (m_tid, i);
   706 }
   707 Ptr<const TraceSourceAccessor> 
   708 TypeId::GetTraceSourceAccessor (uint32_t i) const
   709 {
   710   return Singleton<IidManager>::Get ()->GetTraceSourceAccessor (m_tid, i);
   711 }
   712 
   713 TypeId 
   714 TypeId::AddTraceSource (std::string name,
   715                         std::string help,
   716                         Ptr<const TraceSourceAccessor> accessor)
   717 {
   718   Singleton<IidManager>::Get ()->AddTraceSource (m_tid, name, help, accessor);
   719   return *this;
   720 }
   721 
   722 
   723 Ptr<const TraceSourceAccessor> 
   724 TypeId::LookupTraceSourceByName (std::string name) const
   725 {
   726   TypeId tid;
   727   TypeId nextTid = *this;
   728   do {
   729     tid = nextTid;
   730     for (uint32_t i = 0; i < tid.GetTraceSourceN (); i++)
   731       {
   732         std::string srcName = tid.GetTraceSourceName (i);
   733         if (srcName == name)
   734           {
   735             return tid.GetTraceSourceAccessor (i);
   736           }
   737       }
   738     nextTid = tid.GetParent ();
   739   } while (nextTid != tid);
   740   return 0;
   741 }
   742 
   743 std::ostream & operator << (std::ostream &os, TypeId tid)
   744 {
   745   os << tid.GetName ();
   746   return os;
   747 }
   748 std::istream & operator >> (std::istream &is, TypeId &tid)
   749 {
   750   std::string tidString;
   751   is >> tidString;
   752   tid = TypeId::LookupByName (tidString);
   753   return is;
   754 }
   755 
   756 
   757 VALUE_HELPER_CPP (TypeId);
   758 
   759 bool operator == (TypeId a, TypeId b)
   760 {
   761   return a.m_tid == b.m_tid;
   762 }
   763 
   764 bool operator != (TypeId a, TypeId b)
   765 {
   766   return a.m_tid != b.m_tid;
   767 }
   768 
   769 /*********************************************************************
   770  *         The AttributeList container implementation
   771  *********************************************************************/
   772 
   773 AttributeList::AttributeList ()
   774 {}
   775 
   776 AttributeList::AttributeList (const AttributeList &o)
   777 {
   778   for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
   779     {
   780       struct Attr attr;
   781       attr.checker = i->checker;
   782       attr.value = i->value.Copy ();
   783       m_attributes.push_back (attr);
   784     }
   785 }
   786 AttributeList &
   787 AttributeList::operator = (const AttributeList &o)
   788 {
   789   Reset ();
   790   for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
   791     {
   792       struct Attr attr;
   793       attr.checker = i->checker;
   794       attr.value = i->value.Copy ();
   795       m_attributes.push_back (attr);
   796     }
   797   return *this;
   798 }
   799 AttributeList::~AttributeList ()
   800 {
   801   Reset ();
   802 }
   803 
   804 bool 
   805 AttributeList::Set (std::string name, Attribute value)
   806 {
   807   struct TypeId::AttributeInfo info;
   808   TypeId::LookupAttributeByFullName (name, &info);
   809   bool ok = DoSet (&info, value);
   810   return ok;
   811 }
   812 bool
   813 AttributeList::SetWithTid (TypeId tid, std::string name, Attribute value)
   814 {
   815   struct TypeId::AttributeInfo info;
   816   tid.LookupAttributeByName (name, &info);
   817   bool ok = DoSet (&info, value);
   818   return ok;
   819 }
   820 bool
   821 AttributeList::SetWithTid (TypeId tid, uint32_t position, Attribute value)
   822 {
   823   struct TypeId::AttributeInfo info;
   824   tid.LookupAttributeByPosition (position, &info);
   825   bool ok = DoSet (&info, value);
   826   return ok;
   827 }
   828 
   829 void
   830 AttributeList::DoSetOne (Ptr<const AttributeChecker> checker, Attribute value)
   831 {
   832   // get rid of any previous value stored in this
   833   // vector of values.
   834   for (Attrs::iterator k = m_attributes.begin (); k != m_attributes.end (); k++)
   835     {
   836       if (k->checker == checker)
   837         {
   838           m_attributes.erase (k);
   839           break;
   840         }
   841     }
   842   // store the new value.
   843   struct Attr attr;
   844   attr.checker = checker;
   845   attr.value = value.Copy ();
   846   m_attributes.push_back (attr);
   847 }
   848 bool
   849 AttributeList::DoSet (struct TypeId::AttributeInfo *info, Attribute value)
   850 {
   851   if (info->checker == 0)
   852     {
   853       return false;
   854     }
   855   bool ok = info->checker->Check (value);
   856   if (!ok)
   857     {
   858       // attempt to convert to string.
   859       const StringValue *str = value.DynCast<const StringValue *> ();
   860       if (str == 0)
   861         {
   862           return false;
   863         }
   864       // attempt to convert back to value.
   865       Attribute v = info->checker->Create ();
   866       ok = v.DeserializeFromString (str->Get ().Get (), info->checker);
   867       if (!ok)
   868         {
   869           return false;
   870         }
   871       ok = info->checker->Check (v);
   872       if (!ok)
   873         {
   874           return false;
   875         }
   876       value = v;
   877     }
   878   DoSetOne (info->checker, value);
   879   return true;
   880 }
   881 void 
   882 AttributeList::Reset (void)
   883 {
   884   m_attributes.clear ();
   885 }
   886 AttributeList *
   887 AttributeList::GetGlobal (void)
   888 {
   889   return Singleton<AttributeList>::Get ();
   890 }
   891 
   892 std::string
   893 AttributeList::LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const
   894 {
   895   for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
   896     {
   897       TypeId tid = TypeId::GetRegistered (i);
   898       for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
   899         {
   900           if (checker == tid.GetAttributeChecker (j))
   901             {
   902               return tid.GetAttributeFullName (j);
   903             }
   904         }
   905     }
   906   NS_FATAL_ERROR ("Could not find requested Accessor.");
   907   // quiet compiler.
   908   return "";
   909 }
   910 
   911 std::string 
   912 AttributeList::SerializeToString (void) const
   913 {
   914   std::ostringstream oss;
   915   for (Attrs::const_iterator i = m_attributes.begin (); i != m_attributes.end (); i++)
   916     {
   917       std::string name = LookupAttributeFullNameByChecker (i->checker);
   918       oss << name << "=" << i->value.SerializeToString (i->checker);
   919       if (i != m_attributes.end ())
   920         {
   921           oss << "|";
   922         }
   923     }  
   924   return oss.str ();
   925 }
   926 bool 
   927 AttributeList::DeserializeFromString (std::string str)
   928 {
   929   Reset ();
   930 
   931   std::string::size_type cur;
   932   cur = 0;
   933   do {
   934     std::string::size_type equal = str.find ("=", cur);
   935     if (equal == std::string::npos)
   936       {
   937         // XXX: invalid attribute.
   938         break;
   939       }
   940     else
   941       {
   942         std::string name = str.substr (cur, equal-cur);
   943         struct TypeId::AttributeInfo info;
   944         if (!TypeId::LookupAttributeByFullName (name, &info))
   945           {
   946             // XXX invalid name.
   947             break;
   948           }
   949         else
   950           {
   951             std::string::size_type next = str.find ("|", cur);
   952             std::string value;
   953             if (next == std::string::npos)
   954               {
   955                 value = str.substr (equal+1, str.size () - (equal+1));
   956                 cur = str.size ();
   957               }
   958             else
   959               {
   960                 value = str.substr (equal+1, next - (equal+1));
   961                 cur++;
   962               }
   963             Attribute val = info.checker->Create ();
   964             bool ok = val.DeserializeFromString (value, info.checker);
   965             if (!ok)
   966               {
   967                 // XXX invalid value
   968                 break;
   969               }
   970             else
   971               {
   972                 DoSetOne (info.checker, val);
   973               }
   974           }
   975       }
   976   } while (cur != str.size ());
   977 
   978   return true;
   979 }
   980 
   981 
   982 /*********************************************************************
   983  *         The Object implementation
   984  *********************************************************************/
   985 
   986 NS_OBJECT_ENSURE_REGISTERED (Object);
   987 
   988 static TypeId
   989 GetObjectIid (void)
   990 {
   991   TypeId tid = TypeId ("Object");
   992   tid.SetParent (tid);
   993   return tid;
   994 }
   995 
   996 TypeId 
   997 Object::GetTypeId (void)
   998 {
   999   static TypeId tid = GetObjectIid ();
  1000   return tid;
  1001 }
  1002 
  1003 
  1004 Object::Object ()
  1005   : m_count (1),
  1006     m_tid (Object::GetTypeId ()),
  1007     m_disposed (false),
  1008     m_collecting (false),
  1009     m_next (this)
  1010 {}
  1011 Object::~Object () 
  1012 {
  1013   m_next = 0;
  1014 }
  1015 void
  1016 Object::Construct (const AttributeList &attributes)
  1017 {
  1018   // loop over the inheritance tree back to the Object base class.
  1019   TypeId tid = m_tid;
  1020   do {
  1021     // loop over all attributes in object type
  1022     NS_LOG_DEBUG ("construct tid="<<tid.GetName ()<<", params="<<tid.GetAttributeListN ());
  1023     for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
  1024       {
  1025         Ptr<const AttributeAccessor> paramSpec = tid.GetAttributeAccessor (i);
  1026         Attribute initial = tid.GetAttributeInitialValue (i);
  1027         Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
  1028         NS_LOG_DEBUG ("try to construct \""<< tid.GetName ()<<"::"<<
  1029                       tid.GetAttributeName (i)<<"\"");
  1030         if (!(tid.GetAttributeFlags (i) & TypeId::ATTR_CONSTRUCT))
  1031           {
  1032             continue;
  1033           }
  1034         bool found = false;
  1035         // is this attribute stored in this AttributeList instance ?
  1036         for (AttributeList::Attrs::const_iterator j = attributes.m_attributes.begin ();
  1037              j != attributes.m_attributes.end (); j++)
  1038           {
  1039             if (j->checker == checker)
  1040               {
  1041                 // We have a matching attribute value.
  1042                 DoSet (paramSpec, initial, checker, j->value);
  1043                 NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
  1044                               tid.GetAttributeName (i)<<"\"");
  1045                 found = true;
  1046                 break;
  1047               }
  1048           }
  1049         if (!found)
  1050           {
  1051             // is this attribute stored in the global instance instance ?
  1052             for (AttributeList::Attrs::const_iterator j = AttributeList::GetGlobal ()->m_attributes.begin ();
  1053                  j != AttributeList::GetGlobal ()->m_attributes.end (); j++)
  1054               {
  1055                 if (j->checker == checker)
  1056                   {
  1057                     // We have a matching attribute value.
  1058                     DoSet (paramSpec, initial, checker, j->value);
  1059                     NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
  1060                                   tid.GetAttributeName (i)<<"\" from global");
  1061                     found = true;
  1062                     break;
  1063                   }
  1064               }
  1065           }
  1066         if (!found)
  1067           {
  1068             // No matching attribute value so we set the default value.
  1069             paramSpec->Set (this, initial);
  1070             NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
  1071                           tid.GetAttributeName (i)<<"\" from initial value.");
  1072           }
  1073       }
  1074     tid = tid.GetParent ();
  1075   } while (tid != Object::GetTypeId ());
  1076   NotifyConstructionCompleted ();
  1077 }
  1078 bool
  1079 Object::DoSet (Ptr<const AttributeAccessor> spec, Attribute initialValue, 
  1080                Ptr<const AttributeChecker> checker, Attribute value)
  1081 {
  1082   bool ok = checker->Check (value);
  1083   if (!ok)
  1084     {
  1085       // attempt to convert to string
  1086       const StringValue *str = value.DynCast<const StringValue *> ();
  1087       if (str == 0)
  1088         {
  1089           return false;
  1090         }
  1091       // attempt to convert back from string.
  1092       Attribute v = checker->Create ();
  1093       ok = v.DeserializeFromString (str->Get ().Get (), checker);
  1094       if (!ok)
  1095         {
  1096           return false;
  1097         }
  1098       ok = checker->Check (v);
  1099       if (!ok)
  1100         {
  1101           return false;
  1102         }
  1103       value = v;
  1104     }
  1105   ok = spec->Set (this, value);
  1106   return ok;
  1107 }
  1108 bool
  1109 Object::SetAttribute (std::string name, Attribute value)
  1110 {
  1111   struct TypeId::AttributeInfo info;
  1112   if (!m_tid.LookupAttributeByName (name, &info))
  1113     {
  1114       return false;
  1115     }
  1116   if (!(info.flags & TypeId::ATTR_SET))
  1117     {
  1118       return false;
  1119     }
  1120   return DoSet (info.accessor, info.initialValue, info.checker, value);
  1121 }
  1122 bool 
  1123 Object::GetAttribute (std::string name, std::string &value) const
  1124 {
  1125   struct TypeId::AttributeInfo info;
  1126   if (!m_tid.LookupAttributeByName (name, &info))
  1127     {
  1128       return false;
  1129     }
  1130   if (!(info.flags & TypeId::ATTR_GET))
  1131     {
  1132       return false;
  1133     }
  1134   Attribute v = info.checker->Create ();
  1135   bool ok = info.accessor->Get (this, v);
  1136   if (ok)
  1137     {
  1138       value = v.SerializeToString (info.checker);
  1139     }
  1140   return ok;
  1141 }
  1142 
  1143 Attribute
  1144 Object::GetAttribute (std::string name) const
  1145 {
  1146   struct TypeId::AttributeInfo info;
  1147   if (!m_tid.LookupAttributeByName (name, &info))
  1148     {
  1149       return Attribute ();
  1150     }
  1151   if (!(info.flags & TypeId::ATTR_GET))
  1152     {
  1153       return Attribute ();
  1154     }
  1155   Attribute value = info.checker->Create ();
  1156   bool ok = info.accessor->Get (this, value);
  1157   if (!ok)
  1158     {
  1159       return Attribute ();
  1160     }
  1161   return value;
  1162 }
  1163 
  1164 bool 
  1165 Object::TraceSourceConnect (std::string name, const CallbackBase &cb)
  1166 {
  1167   Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
  1168   if (accessor == 0)
  1169     {
  1170       return false;
  1171     }
  1172   bool ok = accessor->Connect (this, cb);
  1173   return ok;
  1174 }
  1175 bool 
  1176 Object::TraceSourceConnectWithContext (std::string name, std::string context, const CallbackBase &cb)
  1177 {
  1178   Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
  1179   if (accessor == 0)
  1180     {
  1181       return false;
  1182     }
  1183   bool ok = accessor->ConnectWithContext (this, context, cb);
  1184   return ok;
  1185 }
  1186 bool 
  1187 Object::TraceSourceDisconnect (std::string name, const CallbackBase &cb)
  1188 {
  1189   Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
  1190   if (accessor == 0)
  1191     {
  1192       return false;
  1193     }
  1194   bool ok = accessor->Disconnect (this, cb);
  1195   return ok;
  1196 }
  1197 
  1198 TypeId 
  1199 Object::GetRealTypeId (void) const
  1200 {
  1201   return m_tid;
  1202 }
  1203 
  1204 
  1205 Ptr<Object>
  1206 Object::DoGetObject (TypeId tid) const
  1207 {
  1208   NS_ASSERT (CheckLoose ());
  1209   const Object *currentObject = this;
  1210   do {
  1211     NS_ASSERT (currentObject != 0);
  1212     TypeId cur = currentObject->m_tid;
  1213     while (cur != tid && cur != Object::GetTypeId ())
  1214       {
  1215         cur = cur.GetParent ();
  1216       }
  1217     if (cur == tid)
  1218       {
  1219         return const_cast<Object *> (currentObject);
  1220       }
  1221     currentObject = currentObject->m_next;
  1222   } while (currentObject != this);
  1223   return 0;
  1224 }
  1225 void 
  1226 Object::Dispose (void)
  1227 {
  1228   Object *current = this;
  1229   do {
  1230     NS_ASSERT (current != 0);
  1231     NS_ASSERT (!current->m_disposed);
  1232     current->DoDispose ();
  1233     current->m_disposed = true;
  1234     current = current->m_next;
  1235   } while (current != this);
  1236 }
  1237 void
  1238 Object::NotifyConstructionCompleted (void)
  1239 {}
  1240 void 
  1241 Object::AggregateObject (Ptr<Object> o)
  1242 {
  1243   NS_ASSERT (!m_disposed);
  1244   NS_ASSERT (!o->m_disposed);
  1245   NS_ASSERT (CheckLoose ());
  1246   NS_ASSERT (o->CheckLoose ());
  1247   Object *other = PeekPointer (o);
  1248   Object *next = m_next;
  1249   m_next = other->m_next;
  1250   other->m_next = next;
  1251   NS_ASSERT (CheckLoose ());
  1252   NS_ASSERT (o->CheckLoose ());
  1253 }
  1254 
  1255 void 
  1256 Object::TraceConnect (std::string path, const CallbackBase &cb) const
  1257 {
  1258   NS_ASSERT (CheckLoose ());
  1259   GetTraceResolver ()->Connect (path, cb, TraceContext ());
  1260 }
  1261 void 
  1262 Object::TraceDisconnect (std::string path, const CallbackBase &cb) const
  1263 {
  1264   NS_ASSERT (CheckLoose ());
  1265   GetTraceResolver ()->Disconnect (path, cb);
  1266 }
  1267 
  1268 void 
  1269 Object::SetTypeId (TypeId tid)
  1270 {
  1271   NS_ASSERT (Check ());
  1272   m_tid = tid;
  1273 }
  1274 
  1275 void
  1276 Object::DoDispose (void)
  1277 {
  1278   NS_ASSERT (!m_disposed);
  1279 }
  1280 
  1281 Ptr<TraceResolver>
  1282 Object::GetTraceResolver (void) const
  1283 {
  1284   NS_ASSERT (CheckLoose ());
  1285   Ptr<TypeIdTraceResolver> resolver =
  1286     Create<TypeIdTraceResolver> (this);
  1287   return resolver;
  1288 }
  1289 
  1290 bool 
  1291 Object::Check (void) const
  1292 {
  1293   return (m_count > 0);
  1294 }
  1295 
  1296 /* In some cases, when an event is scheduled against a subclass of
  1297  * Object, and if no one owns a reference directly to this object, the
  1298  * object is alive, has a refcount of zero and the method ran when the
  1299  * event expires runs against the raw pointer which means that we are
  1300  * manipulating an object with a refcount of zero.  So, instead we
  1301  * check the aggregate reference count.
  1302  */
  1303 bool 
  1304 Object::CheckLoose (void) const
  1305 {
  1306   uint32_t refcount = 0;
  1307   const Object *current = this;
  1308   do
  1309     {
  1310       refcount += current->m_count;
  1311       current = current->m_next;
  1312     }
  1313   while (current != this);
  1314 
  1315   return (refcount > 0);
  1316 }
  1317 
  1318 void
  1319 Object::MaybeDelete (void) const
  1320 {
  1321   // First, check if any of the attached
  1322   // Object has a non-zero count.
  1323   const Object *current = this;
  1324   do {
  1325     NS_ASSERT (current != 0);
  1326     if (current->m_count != 0)
  1327       {
  1328         return;
  1329       }
  1330     current = current->m_next;
  1331   } while (current != this);
  1332 
  1333   // Ensure we are disposed.
  1334   Object *tmp = const_cast<Object *> (this);
  1335   const Object *end = this;
  1336   do {
  1337     NS_ASSERT (current != 0);
  1338     Object *next = tmp->m_next;
  1339     if (!tmp->m_disposed)
  1340       {
  1341         tmp->DoDispose ();
  1342       }
  1343     tmp = next;
  1344   } while (tmp != end);
  1345 
  1346   // all attached objects have a zero count so, 
  1347   // we can delete all attached objects.
  1348   current = this;
  1349   do {
  1350     NS_ASSERT (current != 0);
  1351     Object *next = current->m_next;
  1352     delete current;
  1353     current = next;
  1354   } while (current != end);
  1355 }
  1356 
  1357 void 
  1358 Object::DoCollectSources (std::string path, const TraceContext &context, 
  1359                           TraceResolver::SourceCollection *collection) const
  1360 {
  1361   const Object *current;
  1362   current = this;
  1363   do {
  1364     if (current->m_collecting)
  1365       {
  1366         return;
  1367       }
  1368     current = current->m_next;
  1369   } while (current != this);
  1370 
  1371   m_collecting = true;
  1372 
  1373   current = this->m_next;
  1374   while (current != this)
  1375     {
  1376       NS_ASSERT (current != 0);
  1377       NS_LOG_LOGIC ("collect current=" << current);
  1378       TypeId cur = current->m_tid;
  1379       while (cur != Object::GetTypeId ())
  1380         {
  1381           std::string name = cur.GetName ();
  1382           std::string fullpath = path;
  1383           fullpath.append ("/$");
  1384           fullpath.append (name);
  1385           NS_LOG_LOGIC("collect: " << fullpath);
  1386           current->GetTraceResolver ()->CollectSources (fullpath, context, collection);
  1387           cur = cur.GetParent ();
  1388         }
  1389       current = current->m_next;
  1390     }
  1391 
  1392   m_collecting = false;
  1393 }
  1394 void 
  1395 Object::DoTraceAll (std::ostream &os, const TraceContext &context) const
  1396 {
  1397   const Object *current;
  1398   current = this;
  1399   do {
  1400     if (current->m_collecting)
  1401       {
  1402         return;
  1403       }
  1404     current = current->m_next;
  1405   } while (current != this);
  1406 
  1407   m_collecting = true;
  1408 
  1409   current = this->m_next;
  1410   while (current != this)
  1411     {
  1412       NS_ASSERT (current != 0);
  1413       current->GetTraceResolver ()->TraceAll (os, context);
  1414       current = current->m_next;
  1415     }
  1416 
  1417   m_collecting = false;
  1418 }
  1419 
  1420 } // namespace ns3
  1421 
  1422 
  1423 #ifdef RUN_SELF_TESTS
  1424 
  1425 #include "test.h"
  1426 #include "sv-trace-source.h"
  1427 #include "composite-trace-resolver.h"
  1428 
  1429 namespace {
  1430 
  1431 class BaseA : public ns3::Object
  1432 {
  1433 public:
  1434   static ns3::TypeId GetTypeId (void) {
  1435     static ns3::TypeId tid = ns3::TypeId ("BaseA")
  1436       .SetParent (Object::GetTypeId ())
  1437       .AddConstructor<BaseA> ();
  1438     return tid;
  1439   }
  1440   BaseA ()
  1441   {}
  1442   void BaseGenerateTrace (int16_t v)
  1443   { m_source = v; }
  1444   virtual void Dispose (void) {}
  1445   virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
  1446   {
  1447     ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
  1448       ns3::Create<ns3::CompositeTraceResolver> ();
  1449     resolver->AddSource ("basea-x", ns3::TraceDoc ("test source"), m_source);
  1450     resolver->SetParentResolver (Object::GetTraceResolver ());
  1451     return resolver;
  1452   }
  1453   ns3::SVTraceSource<int16_t> m_source;
  1454 };
  1455 
  1456 class DerivedA : public BaseA
  1457 {
  1458 public:
  1459   static ns3::TypeId GetTypeId (void) {
  1460     static ns3::TypeId tid = ns3::TypeId ("DerivedA")
  1461       .SetParent (BaseA::GetTypeId ())
  1462       .AddConstructor<DerivedA> ();
  1463     return tid;
  1464   }
  1465   DerivedA ()
  1466   {}
  1467   void DerivedGenerateTrace (int16_t v)
  1468   { m_sourceDerived = v; }
  1469   virtual void Dispose (void) {
  1470     BaseA::Dispose ();
  1471   }
  1472   virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
  1473   {
  1474     ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
  1475       ns3::Create<ns3::CompositeTraceResolver> ();
  1476     resolver->AddSource ("deriveda-x", ns3::TraceDoc ("test source"), m_sourceDerived);
  1477     resolver->SetParentResolver (BaseA::GetTraceResolver ());
  1478     return resolver;
  1479   }
  1480   ns3::SVTraceSource<int16_t> m_sourceDerived;
  1481 };
  1482 
  1483 class BaseB : public ns3::Object
  1484 {
  1485 public:
  1486   static ns3::TypeId GetTypeId (void) {
  1487     static ns3::TypeId tid = ns3::TypeId ("BaseB")
  1488       .SetParent (Object::GetTypeId ())
  1489       .AddConstructor<BaseB> ();
  1490     return tid;
  1491   }
  1492   BaseB ()
  1493   {}
  1494   void BaseGenerateTrace (int16_t v)
  1495   { m_source = v; }
  1496   virtual void Dispose (void) {}
  1497   virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
  1498   {
  1499     ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
  1500       ns3::Create<ns3::CompositeTraceResolver> ();
  1501     resolver->AddSource ("baseb-x", ns3::TraceDoc ("test source"), m_source);
  1502     resolver->SetParentResolver (Object::GetTraceResolver ());
  1503     return resolver;
  1504   }
  1505   ns3::SVTraceSource<int16_t> m_source;
  1506 };
  1507 
  1508 class DerivedB : public BaseB
  1509 {
  1510 public:
  1511   static ns3::TypeId GetTypeId (void) {
  1512     static ns3::TypeId tid = ns3::TypeId ("DerivedB")
  1513       .SetParent (BaseB::GetTypeId ())
  1514       .AddConstructor<DerivedB> ();
  1515     return tid;
  1516   }
  1517   DerivedB ()
  1518   {}
  1519   void DerivedGenerateTrace (int16_t v)
  1520   { m_sourceDerived = v; }
  1521   virtual void Dispose (void) {
  1522     BaseB::Dispose ();
  1523   }
  1524   virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
  1525   {
  1526     ns3::Ptr<ns3::CompositeTraceResolver> resolver = 
  1527       ns3::Create<ns3::CompositeTraceResolver> ();
  1528     resolver->AddSource ("derivedb-x", ns3::TraceDoc ("test source"), m_sourceDerived);
  1529     resolver->SetParentResolver (BaseB::GetTraceResolver ());
  1530     return resolver;
  1531   }
  1532   ns3::SVTraceSource<int16_t> m_sourceDerived;
  1533 };
  1534 
  1535 NS_OBJECT_ENSURE_REGISTERED (BaseA);
  1536 NS_OBJECT_ENSURE_REGISTERED (DerivedA);
  1537 NS_OBJECT_ENSURE_REGISTERED (BaseB);
  1538 NS_OBJECT_ENSURE_REGISTERED (DerivedB);
  1539 
  1540 } // namespace anonymous
  1541 
  1542 namespace ns3 {
  1543 
  1544 class ObjectTest : public Test
  1545 {
  1546 public:
  1547   ObjectTest ();
  1548   virtual bool RunTests (void);
  1549 private:
  1550   void BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
  1551   void DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
  1552   void BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
  1553   void DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
  1554 
  1555   bool m_baseATrace;
  1556   bool m_derivedATrace;
  1557   bool m_baseBTrace;
  1558   bool m_derivedBTrace;
  1559 };
  1560 
  1561 ObjectTest::ObjectTest ()
  1562   : Test ("Object")
  1563 {}
  1564 void 
  1565 ObjectTest::BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
  1566 {
  1567   m_baseATrace = true;
  1568 }
  1569 void 
  1570 ObjectTest::DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
  1571 {
  1572   m_derivedATrace = true;
  1573 }
  1574 void 
  1575 ObjectTest::BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
  1576 {
  1577   m_baseBTrace = true;
  1578 }
  1579 void 
  1580 ObjectTest::DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
  1581 {
  1582   m_derivedBTrace = true;
  1583 }
  1584 
  1585 bool 
  1586 ObjectTest::RunTests (void)
  1587 {
  1588   bool result = true;
  1589 
  1590   Ptr<BaseA> baseA = CreateObject<BaseA> ();
  1591   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
  1592   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
  1593   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
  1594   baseA = CreateObject<DerivedA> ();
  1595   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
  1596   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA);
  1597   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedA> (), 0);
  1598 
  1599   baseA = CreateObject<BaseA> ();
  1600   Ptr<BaseB> baseB = CreateObject<BaseB> ();
  1601   Ptr<BaseB> baseBCopy = baseB;
  1602   baseA->AggregateObject (baseB);
  1603   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseA> (), 0);
  1604   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
  1605   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
  1606   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedB> (), 0);
  1607   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
  1608   NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedB> (), 0);
  1609   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
  1610   NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedA> (), 0);
  1611   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
  1612 
  1613   baseA = CreateObject<DerivedA> ();
  1614   baseB = CreateObject<DerivedB> ();
  1615   baseBCopy = baseB;
  1616   baseA->AggregateObject (baseB);
  1617   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedB> (), 0);
  1618   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
  1619   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedA> (), 0);
  1620   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
  1621   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<DerivedA> (), 0);
  1622   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
  1623   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedB> (), 0);
  1624   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0)
  1625 
  1626   baseA = CreateObject<BaseA> ();
  1627   baseB = CreateObject<BaseB> ();
  1628   baseA->AggregateObject (baseB);
  1629   baseA = 0;
  1630   baseA = baseB->GetObject<BaseA> ();
  1631 
  1632   baseA = CreateObject<BaseA> ();
  1633   baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1634   m_baseATrace = false;
  1635   baseA->BaseGenerateTrace (1);
  1636   NS_TEST_ASSERT (m_baseATrace);
  1637   baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1638 
  1639   baseB = CreateObject<BaseB> ();
  1640   baseB->TraceConnect ("/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
  1641   m_baseBTrace = false;
  1642   baseB->BaseGenerateTrace (2);
  1643   NS_TEST_ASSERT (m_baseBTrace);
  1644   baseB->TraceDisconnect ("/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
  1645 
  1646   baseA->AggregateObject (baseB);
  1647 
  1648   baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1649   m_baseATrace = false;
  1650   baseA->BaseGenerateTrace (3);
  1651   NS_TEST_ASSERT (m_baseATrace);
  1652   baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1653 
  1654   baseA->TraceConnect ("/$BaseB/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
  1655   m_baseBTrace = false;
  1656   baseB->BaseGenerateTrace (4);
  1657   NS_TEST_ASSERT (m_baseBTrace);
  1658   baseA->TraceDisconnect ("/$BaseB/baseb-x",  MakeCallback (&ObjectTest::BaseBTrace, this));
  1659   m_baseBTrace = false;
  1660   baseB->BaseGenerateTrace (5);
  1661   NS_TEST_ASSERT (!m_baseBTrace);
  1662 
  1663   baseB->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1664   m_baseATrace = false;
  1665   baseA->BaseGenerateTrace (6);
  1666   NS_TEST_ASSERT (m_baseATrace);
  1667   baseB->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1668 
  1669   baseA->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1670   m_baseATrace = false;
  1671   baseA->BaseGenerateTrace (7);
  1672   NS_TEST_ASSERT (m_baseATrace);
  1673   baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1674 
  1675   Ptr<DerivedA> derivedA;
  1676   derivedA = CreateObject<DerivedA> ();
  1677   baseB = CreateObject<BaseB> ();
  1678   derivedA->AggregateObject (baseB);
  1679   baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
  1680   baseB->TraceConnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1681   m_derivedATrace = false;
  1682   m_baseATrace = false;
  1683   derivedA->DerivedGenerateTrace (8);
  1684   derivedA->BaseGenerateTrace (9);
  1685   NS_TEST_ASSERT (m_derivedATrace);
  1686   NS_TEST_ASSERT (m_baseATrace);
  1687   baseB->TraceDisconnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1688   baseB->TraceDisconnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
  1689 
  1690   baseB->TraceConnect ("/$DerivedA/*", MakeCallback (&ObjectTest::DerivedATrace, this));
  1691   m_derivedATrace = false;
  1692   derivedA->DerivedGenerateTrace (10);
  1693   NS_TEST_ASSERT (m_derivedATrace);
  1694   // here, we have connected the derived trace sink to all 
  1695   // trace sources, including the base trace source.
  1696   m_derivedATrace = false;
  1697   derivedA->BaseGenerateTrace (11);
  1698   NS_TEST_ASSERT (m_derivedATrace);
  1699   baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this));
  1700 
  1701   // Test the object creation code of TypeId
  1702   Ptr<Object> a = BaseA::GetTypeId ().CreateObject ();
  1703   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
  1704   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
  1705   NS_TEST_ASSERT_EQUAL (a->GetObject<DerivedA> (), 0);
  1706   a = DerivedA::GetTypeId ().CreateObject ();
  1707   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
  1708   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a);
  1709   NS_TEST_ASSERT_UNEQUAL (a->GetObject<DerivedA> (), 0);
  1710 
  1711 
  1712   return result;
  1713 }
  1714 
  1715 static ObjectTest g_interfaceObjectTests;
  1716 
  1717 
  1718 } // namespace ns3
  1719 
  1720 #endif /* RUN_SELF_TESTS */
  1721 
  1722