src/core/model/names.h
author Tom Henderson <tomh@tomh.org>
Mon, 04 Jan 2016 14:11:51 -0800
changeset 11800 bd9c9abd5d6e
parent 11538 397bd6465dd9
permissions -rw-r--r--
merge to ns-3-dev@11799:f410a3b3825b

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2009 University of Washington
 *
 * 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
 */

#ifndef OBJECT_NAMES_H
#define OBJECT_NAMES_H

#include "ptr.h"
#include "object.h"

/**
 * \file
 * \ingroup config
 * Declaration of class ns3::Names.
 */

namespace ns3 {

/**
 * \ingroup config
 * \brief A directory of name and Ptr<Object> associations that allows
 * us to give any ns3 Object a name.
 */
class Names
{
public:

  /**
   * \brief Add the association between the string "name" and the
   * Ptr<Object> obj.
   *
   * The name may begin either with "/Names" to explicitly call out
   * the fact that the name provided is installed under the root of
   * the name space, or it may begin with the name of the first object
   * in the path.  For example, Names::Add ("/Names/client", obj) and
   * Names::Add ("client", obj) accomplish exactly the same thing.  A
   * name at a given level in the name space path must be unique.  In
   * the case of the example above, it would be illegal to try and
   * associate a different object with the same name: "client" at the
   * same level ("/Names") in the path.
   *
   * As well as specifying a name at the root of the "/Names"
   * namespace, the name parameter can contain a path that fully
   * qualifies the name to be added.  For example, if you previously
   * have named an object "client" in the root namespace as above, you
   * could name an object "under" that name by making a call like
   * Names::Add ("/Names/client/eth0", obj).  This will define the
   * name "eth0" and make it reachable using the path specified.  Note
   * that Names::Add ("client/eth0", obj) would accomplish exactly the
   * same thing.
   *
   * Duplicate names are not allowed at the same level in a path,
   * however you may associate similar names with different paths.
   * For example, if you define "/Names/Client", you may not define
   * another "/Names/Client" just as you may not have two files with
   * the same name in a classical filesystem.  However, you may have
   * "/Names/Client/eth0" and "/Names/Server/eth0" defined at the same
   * time just as you might have different files of the same name
   * under different directories.
   *
   * \param [in] name The name of the object you want to associate; which may be 
   *             prepended with a path to that object.
   * \param [in] object A smart pointer to the object itself.
   */
  static void Add (std::string name, Ptr<Object> object);

  /**
   * \brief An intermediate form of Names::Add allowing you to provide
   * a path to the parent object (under which you want this name to be
   * defined) in the form of a name path string.
   *
   * In some cases, it is desirable to break up the path used to
   * describe an item in the names namespace into a path and a name.
   * This is analogous to a file system operation in which you provide
   * a directory name and a file name.
   *
   * For example, consider a situation where you have previously named
   * an object "/Names/server".  If you further want to create an
   * association for between a Ptr<Object> object that you want to
   * live "under" the server in the name space -- perhaps "eth0" --
   * you could do this in two ways, depending on which was more
   * convenient: Names::Add ("/Names/server/eth0", object) or, using
   * the split path and name approach, Names::Add ("/Names/server",
   * "eth0", object).
   *
   * Duplicate names are not allowed at the same level in a path,
   * however you may associate similar names with different paths.
   * For example, if you define "/Names/Client", you may not define
   * another "/Names/Client" just as you may not have two files with
   * the same name in a classical filesystem.  However, you may have
   * "/Names/Client/eth0" and "/Names/Server/eth0" defined at the same
   * time just as you might have different files of the same name
   * under different directories.
   *
   * \param [in] path A path name describing a previously named object
   *             under which you want this new name to be defined.
   * \param [in] name The name of the object you want to associate.
   * \param [in] object A smart pointer to the object itself.
   *
   * \see Names::Add (Ptr<Object>,std::string,Ptr<Object>);
   */
  static void Add (std::string path, std::string name, Ptr<Object> object);

  /**
   * \brief A low-level form of Names::Add allowing you to specify the
   * path to the parent object (under which you want this name to be
   * defined) in the form of a previously named object.
   *
   * In some use cases, it is desirable to break up the path in the
   * names name space into a path and a name.  This is analogous to a
   * file system operation in which you provide a directory name and a
   * file name.  Recall that the path string actually refers to a
   * previously named object, "under" which you want to accomplish
   * some naming action.
   * 
   * However, the path is sometimes not available, and you only have
   * the object that is represented by the path in the names name
   * space.  To support this use-case in a reasonably high-performance
   * way, the path string is can be replaced by the object pointer to
   * which that path would refer.  In the spirit of the Config code
   * where this use-case is most prominent, we refer to this object as
   * the "context" for the names operation.
   *
   * You can think of the context roughly as the inode number of a
   * directory file in Unix.  The inode number can be used to look up
   * the directory file which contains the list of file names defined
   * at that directory level.  Similarly the context is used to look
   * up an internal name service entry which contains the names
   * defined for that context.
   *
   * For example, consider a situation where you have previously named
   * an object "/Names/server".  If you further want to create an
   * association for between a Ptr<Object> object that you want to
   * live "under" the server in the name space -- perhaps "eth0" --
   * you could do this by providing a complete path to the new name:
   * Names::Add ("/Names/server/eth0", object).  If, however,
   * somewhere in your code you only had a pointer to the server, say
   * Ptr<Node> node, and not a handy path string, you could also
   * accomplish this by Names::Add (node, "eth0", object).
   *
   * Duplicate names are not allowed at the same level in a path.  In
   * the case of this method, the context object gives the same
   * information as a path string.  You may associate similar names
   * with different paths.  For example, if you define"/Names/Client",
   * you may not define another "/Names/Client" just as you may not
   * have two files with the same name in a classical filesystem.
   * However, you may have "/Names/Client/eth0" and
   * "/Names/Server/eth0" defined at the same time just as you might
   * have different files of the same name under different
   * directories.
   *
   * \param [in] context A smart pointer to an object that is used
   *             in place of the path under which you want this new
   *             name to be defined.
   * \param [in] name The name of the object you want to associate.
   * \param [in] object A smart pointer to the object itself.
   */
  static void Add (Ptr<Object> context, std::string name, Ptr<Object> object);

  /**
   * \brief Rename a previously associated name.
   *
   * The name may begin either with "/Names" to explicitly call out
   * the fact that the name provided is installed under the root of
   * the name space, or it may begin with the name of the first object
   * in the path.  For example, Names::Rename ("/Names/client",
   * "server") and Names::Rename ("client", "server") accomplish
   * exactly the same thing.  Names at a given level in the name space
   * path must be unique. In the case of the example above, it would
   * be illegal to try and rename a different object to the same name:
   * "server" at the same level ("/Names") in the path.
   *
   * As well as specifying a name at the root of the "/Names"
   * namespace, the name parameter can contain a path that fully
   * qualifies the name to be changed.  For example, if you previously
   * have (re)named an object "server" in the root namespace as above,
   * you could then rename an object "under" that name by making a
   * call like Names::Rename ("/Names/server/csma", "eth0").  This
   * will rename the object previously associated with
   * "/Names/server/csma" to "eth0" and make leave it reachable using
   * the path "/Names/server/eth0".  Note that Names::Rename
   * ("server/csma", "eth0") would accomplish exactly the same thing.
   *
   * \param [in] oldpath The current path name to the object you want
   *             to change.
   * \param [in] newname The new name of the object you want to change.
   *
   * \see Names::Add (std::string name, Ptr<Object> obj)
   */
  static void Rename (std::string oldpath, std::string newname);

  /**
   * \brief An intermediate form of Names::Rename allowing you to
   * provide a path to the parent object (under which you want this
   * name to be changed) in the form of a name path string.
   *
   * In some cases, it is desirable to break up the path used to
   * describe an item in the names namespace into a path and a name.
   * This is analogous to a file system operation in which you provide
   * a directory name and a file name.
   *
   * For example, consider a situation where you have previously named
   * an object "/Names/server/csma".  If you want to change the name
   * "csma" to "eth0", you could do this in two ways, depending on
   * which was more convenient: Names::Rename ("/Names/server/csma",
   * "eth0") or, using the split path and name approach, Names::Rename
   * ("/Names/server", "csma", "eth0").
   *
   * \param [in] path A path name describing a previously named object
   *             under which you want this name change to occur
   *             (cf. directory).
   * \param [in] oldname The currently defined name of the object.
   * \param [in] newname The new name you want the object to have.
   */
  static void Rename (std::string path, std::string oldname, std::string newname);

  /**
   * \brief A low-level form of Names::Rename allowing you to specify
   * the path to the parent object (under which you want this name to
   * be changed) in the form of a previously named object.
   *
   * In some use cases, it is desirable to break up the path in the
   * names name space into a path and a name.  This is analogous to a
   * file system operation in which you provide a directory name and a
   * file name.  Recall that the path string actually refers to a
   * previously named object, "under" which you want to accomplish
   * some naming action.
   * 
   * However, the path is sometimes not available, and you only have
   * the object that is represented by the path in the names name
   * space.  To support this use-case in a reasonably high-performance
   * way, the path string is can be replaced by the object pointer to
   * which that path would refer.  In the spirit of the Config code
   * where this use-case is most prominent, we refer to this object as
   * the "context" for the names operation.
   *
   * You can think of the context roughly as the inode number of a
   * directory file in Unix.  The inode number can be used to look up
   * the directory file which contains the list of file names defined
   * at that directory level.  Similarly the context is used to look
   * up an internal name service entry which contains the names
   * defined for that context.
   *
   * For example, consider a situation where you have previously named
   * an object "/Names/server/csma".  If you later decide to rename
   * the csma object to say "eth0" -- you could do this by providing a
   * complete path as in Names::Rename ("/Names/server/csma", "eth0").
   * If, however, somewhere in your code you only had a pointer to the
   * server, and not a handy path string, say Ptr<Node> node, you
   * could also accomplish this by Names::Rename (node, "csma",
   * "eth0").
   *
   * \param [in] context A smart pointer to an object that is used
   *             in place of the path under which you want this
   *             new name to be defined.
   * \param [in] oldname The current shortname of the object you want
   *             to change.
   * \param [in] newname The new shortname of the object you want
   *             to change.
   */
  static void Rename (Ptr<Object> context, std::string oldname, std::string newname);

  /**
   * \brief Given a pointer to an object, look to see if that object
   * has a name associated with it and, if so, return the name of the
   * object otherwise return an empty string.
   *
   * An object can be referred to in two ways.  Either you can talk
   * about it using its fully qualified path name, for example,
   * "/Names/client/eth0" or you can refer to it by its name, in this
   * case "eth0".
   *
   * This method returns the name of the object, e.g., "eth0".
   *
   * \param [in] object A smart pointer to an object for which you want
   *             to find its name.
   *
   * \returns A string containing the name of the object if found,
   *          otherwise the empty string.
   */
  static std::string FindName (Ptr<Object> object);

  /**
   * \brief Given a pointer to an object, look to see if that object
   * has a name associated with it and return the fully qualified name
   * path of the object otherwise return an empty string.
   *
   * An object can be referred to in two ways.  Either you can talk
   * about it using its fully qualified path name, for example,
   * "/Names/client/eth0" or you can refer to it by its name, in this
   * case "eth0".
   *
   * This method returns the name path of the object, e.g.,
   * "Names/client/eth0".
   *
   * \param [in] object A smart pointer to an object for which you
   *             want to find its fullname.
   *
   * \returns A string containing the name path of the object,
   *          otherwise the empty string.
   */
  static std::string FindPath (Ptr<Object> object);

  /**
   * \brief Clear the list of objects associated with names.
   */

  static void Clear (void);

  /**
   * \brief Given a name path string, look to see if there's an object
   * in the system with that associated to it.  If there is, do a
   * GetObject on the resulting object to convert it to the requested
   * typename and return it.
   * 
   * An object can be referred to in two ways.  Either you can talk
   * about it using its fully qualified path name, for example,
   * "/Names/client/eth0" or you can refer to it by its name, in this
   * case "eth0".
   *
   * This method requires that the name path of the object be
   * provided, e.g., "Names/client/eth0".
   *
   * \param [in] path A string containing a name space path used
   *             to locate the object.
   *
   * \returns A smart pointer to the named object converted to
   *          the requested type.
   */
  template <typename T>
  static Ptr<T> Find (std::string path);

  /**
   * \brief Given a path to an object and an object name, look through
   * the names defined under the path to see if there's an object
   * there with the given name.
   *
   * In some cases, it is desirable to break up the path used to
   * describe an item in the names namespace into a path and a name.
   * This is analogous to a file system operation in which you provide
   * a directory name and a file name.
   *
   * For example, consider a situation where you have previously named
   * an object "/Names/server/eth0".  If you want to discover the
   * object which you associated with this path, you could do this in
   * two ways, depending on which was more convenient: Names::Find
   * ("/Names/server/eth0") or, using the split path and name
   * approach, Names::Find ("/Names/server", "eth0").
   *
   * \param [in] path A path name describing a previously named object
   *             under which you want to look for the specified name.
   * \param [in] name A string containing a name to search for.
   *
   * \returns A smart pointer to the named object converted to
   *          the requested type.
   */
  template <typename T>
  static Ptr<T> Find (std::string path, std::string name);

  /**
   * \brief Given a path to an object and an object name, look through
   * the names defined under the path to see if there's an object
   * there with the given name.
   *
   * In some cases, it is desirable to break up the path used to
   * describe an item in the names namespace into a path and a name.
   * This is analogous to a file system operation in which you provide
   * a directory name and a file name.
   *
   * For example, consider a situation where you have previously named
   * an object "/Names/server/eth0".  If you want to discover the
   * object which you associated with this path, you could do this in
   * two ways, depending on which was more convenient: Names::Find
   * ("/Names/server/eth0") or, using the split path and name
   * approach, Names::Find ("/Names/server", "eth0").
   *
   * However, the path is sometimes not available, and you only have
   * the object that is represented by the path in the names name
   * space.  To support this use-case in a reasonably high-performance
   * way, the path string is can be replaced by the object pointer to
   * which that path would refer.  In the spirit of the Config code
   * where this use-case is most prominent, we refer to this object as
   * the "context" for the names operation.
   *
   * You can think of the context roughly as the inode number of a
   * directory file in Unix.  The inode number can be used to look up
   * the directory file which contains the list of file names defined
   * at that directory level.  Similarly the context is used to look
   * up an internal name service entry which contains the names
   * defined for that context.
   *
   * \param [in] context A smart pointer to an object that is used
   *             in place of the path under which you want this
   *             new name to be defined.
   * \param [in] name A string containing a name to search for.
   *
   * \returns A smart pointer to the named object converted to
   *          the requested type.
   */
  template <typename T>
  static Ptr<T> Find (Ptr<Object> context, std::string name);

private:
  /**
   * \brief Non-templated internal version of Names::Find
   *
   * \param [in] path A string containing the path of the object
   *             to look for.
   *
   * \returns A smart pointer to the named object.
   */
  static Ptr<Object> FindInternal (std::string path);

  /**
   * \brief Non-templated internal version of Names::Find
   *
   * \param [in] path A string containing the path to search
   *             for the object in.
   * \param [in] name A string containing the name of the object
   *             to look for.
   *
   * \returns A smart pointer to the named object.
   */
  static Ptr<Object> FindInternal (std::string path, std::string name);

  /**
   * \brief Non-templated internal version of Names::Find
   *
   * \param [in] context A smart pointer to an object under which
   *             you want to look for the provided name.
   * \param [in] name A string containing the name to look for.
   *
   * \returns A smart pointer to the named object.
   */
  static Ptr<Object> FindInternal (Ptr<Object> context, std::string name);
};

  
template <typename T>
/* static */
Ptr<T> 
Names::Find (std::string path)
{
  Ptr<Object> obj = FindInternal (path);
  if (obj)
    {
      return obj->GetObject<T> ();
    }
  else
    {
      return 0;
    }
}

template <typename T>
/* static */
Ptr<T> 
Names::Find (std::string path, std::string name)
{
  Ptr<Object> obj = FindInternal (path, name);
  if (obj)
    {
      return obj->GetObject<T> ();
    }
  else
    {
      return 0;
    }
}

template <typename T>
/* static */
Ptr<T> 
Names::Find (Ptr<Object> context, std::string name)
{
  Ptr<Object> obj = FindInternal (context, name);
  if (obj)
    {
      return obj->GetObject<T> ();
    }
  else
    {
      return 0;
    }
}

} // namespace ns3

#endif /* OBJECT_NAMES_H */