object.h

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #ifndef __OBJECT_H__
00020 #define __OBJECT_H__
00021 
00022 /**
00023  * \page dsh Data Structures Hierarchy
00024  *
00025  * \section Overview
00026  *
00027  * This is, basically, the center of Module/GUI Communication, however is also
00028  * used by the Core itself. An object is a container which can contain other
00029  * objects, as well as arbitary data. An object knows about its parent and
00030  * shall notify the parent upon events happening within itself. An object shall
00031  * also relay messages coming from deeper within the object hierarchy upwards.
00032  * Upon events, either internal or coming from lower levels, an object notifies
00033  * all of its watchers before passing the event up the hierarchy.
00034  *
00035  * \section Rationale
00036  *
00037  * The basic problem regarding HydraNode Core/GUI Communication is that we need
00038  * to relay arbitary data up to the user interface which we do not know the
00039  * specifics about. The data is defined and implemented within loaded modules
00040  * to which the Core Framework has no access. The intent is also to keep the
00041  * user interface oblivious about the modules data structures specifications,
00042  * while allowing the structures to be displayed, modified and interacted with.
00043  *
00044  * \section Implementation
00045  *
00046  * In order to achieve the afore-mentioned requirements, an Object class
00047  * implements the following characteristics:
00048  *
00049  * - It keeps a pointer to its parent object. The pointer may be null in case
00050  *   of top-level parent node.
00051  * - It keeps a unique identifier which refers to this concrete object. The
00052  *   identifier is assigned to the object by its parent when the object is
00053  *   added to the hierarchy.
00054  * - It keeps a string member which may be displayed to the user to allow the
00055  *   user identify the object.
00056  * - It keeps a list of callback functions which are to be called whenever there
00057  *   are events within this object, or below it in the hierarchy. This allows
00058  *   user interfaces to perform real-time updates of the data structure changes.
00059  *
00060  * The default constructor of the Object is not allowed. An Object is required
00061  * to have a parent, thus placing it immediately within the data structures
00062  * hierarchy upon construction.
00063  *
00064  * The only allowed constructor, as well as the destructor of Object are
00065  * protected, only accessible from derived classes. This enforces the
00066  * implementation to use only objects derived from Object in the hierarchy,
00067  * effectivly forbidding base class construction. It also disallows deleting
00068  * the Object pointers returned by traversing the hierarchy, since that would
00069  * give control of the data structures to outside world, which is a threat
00070  * to the original implementer of the data structure (e.g. the module).
00071  *
00072  * \section Requirements
00073  *
00074  * If an object contains other objects which in turn contain data members,
00075  * the Core/GUI Communication Protocol requires that the data fields names
00076  * for all of the contained objects are same. This means an object is required
00077  * to contain only objects of same type, thus with same data members. This
00078  * requirement is not enforced by the implementation of the base class due to
00079  * impelemtation complications, however is required to be enforced by derived
00080  * classes. Objects containing mixed set of objects of different types is not
00081  * allowed.
00082  *
00083  * \section Usage
00084  *
00085  * The module wishing to make its data structures available to the user
00086  * interface must first derive the container class from Object, and also
00087  * the actual data structure to be exported from Object. Modules are required
00088  * to place their data structures below their entry class. In order to make
00089  * the implemented structures available to the interface, the implementor
00090  * should override the virtual functions defined in the base class. A sample
00091  * implementation can be found in the Core Framework test-suite, at
00092  * tests/test-object/test-object.cpp.
00093  *
00094  * If the implemented data structure changes, the implementor is recommended
00095  * to notify the user interface through the notify() member function. This
00096  * allows the user interface to react to changes in the structure, allowing
00097  * real-time updates.
00098  *
00099  * \section Remarks
00100  *
00101  * The parent/child relationship is strong, e.g. the parent owns the child.
00102  * Additionally, the child always notifies its parent about its destruction,
00103  * thus deletion of a child is a safe operation - the child is guaranteed to
00104  * be removed from its parent. The result of this is that the implementors
00105  * of specific data structures in modules are no longer required to keep any
00106  * pointers or manage the lifetime of the contained objects (unless explicitly
00107  * needed).
00108  */
00109 
00110 #include <hn/osdep.h>
00111 #include <hn/event.h>
00112 #include <map>
00113 #include <string>
00114 #include <vector>
00115 #include <stdexcept>
00116 #include <boost/noncopyable.hpp>
00117 
00118 #ifdef _MSC_VER
00119         // 'this' used in base member initializer list
00120         #pragma warning(disable:4355)
00121 #endif
00122 
00123 //! Object identifiers are 32-bit unsigned integers
00124 typedef uint32_t ObjectId;
00125 
00126 //! Object events, propangated up the object hierarchy, and passed to event
00127 //! handler
00128 enum ObjectEvent {
00129         OBJ_MODIFIED = 0x01, //!< This object's data has been modified
00130         OBJ_ADDED,           //!< An object has been added to this container
00131         OBJ_REMOVED,         //!< An object has been removed from thsi container
00132         OBJ_DESTROY          //!< This object has been destroyed
00133 };
00134 
00135 /**
00136  * Data type description
00137  */
00138 enum DataType {
00139         ODT_UNKNOWN   = 0x00,             //!< 00000000  unknown
00140         ODT_INT       = 0x01,             //!< 00000001  integer
00141         ODT_STRING    = 0x02,             //!< 00000010  string
00142         ODT_BOOL      = 0x04,             //!< 00000100  boolean
00143         ODT_CHOICE    = 0x08,             //!< 00001000  choice
00144         ODT_RESERVED1 = 0x10,             //!< 00010000  <reserved for future>
00145         ODT_REQUIRED  = 0x20,             //!< 00100000  required/always present
00146         ODT_READONLY  = 0x40,             //!< 01000000  read-only
00147         ODT_UNSIGNED  = 0x80              //!< 10000000  unsigned
00148 };
00149 
00150 //! Base object class
00151 class DLLEXPORT Object : public boost::noncopyable {
00152 public:
00153         DECLARE_EVENT_TABLE(Object*, ObjectEvent);
00154         class Operation;
00155 
00156         //! @name Accessors for internal data members.
00157         //@{
00158         //! Retrieve the name of this object
00159         std::string getName() const;
00160         //! Retrieve the unique identifier for this object
00161         ObjectId getId() const { return m_id; }
00162         //! Rename this object
00163         void setName(const std::string &name);
00164         //! Retrieve the parent of this object
00165         Object* getParent() const;
00166         //! Change the parent of this object
00167         void setParent(Object *newParent);
00168         //! Retrieve the number of children this object has
00169         uint32_t getChildCount() const;
00170         //! Retrieve a specific child
00171         Object* getChild(uint32_t id) const;
00172         //! Check if this object has children
00173         bool hasChildren() const;
00174         //@}
00175 
00176         //! @name Customization
00177         //! Modules deriving their objects from this class in order to make
00178         //! them available to user interface can override any of these virtual
00179         //! functions to describe themselves to the user interface, allow access
00180         //! to internal data structures and perform operations with themselves.
00181         //@{
00182         //! Retrieve the number of data fields within this object
00183         virtual uint8_t getDataCount() const;
00184         //! Retrieve the data at specific field
00185         virtual std::string getData(uint8_t num) const;
00186         //! Retrieve the data field name
00187         virtual std::string getFieldName(uint8_t num) const;
00188         //! Retrieve the data type of the field
00189         virtual DataType getFieldType(uint8_t num) const;
00190         //! Fill the passed vector with possible values for this field.
00191         //! Generally used in conjuction with FieldType OFT_CHOICE
00192         virtual void getValueChoices(std::vector<std::string> *cont) const;
00193         //! Retrieve the number of operations for this object
00194         virtual uint8_t getOperCount() const;
00195         //! Retrieve a specific operation description
00196         virtual Operation getOper(uint8_t n) const;
00197         //! Perform an operation with this object
00198         virtual void doOper(const Operation &oper);
00199         //! Modify the data at specific field
00200         virtual void setData(uint8_t num, const std::string &data);
00201         //@}
00202 
00203         //! Internal map constant iterator
00204         typedef std::map<ObjectId, Object*>::const_iterator CIter;
00205 
00206         //! @name Iterators and accessors for our internal data tree for easier
00207         //! navigation. The iterators are const to avoid outside world modifying
00208         //! our internal structures.
00209         //@{
00210         //! Iterator to the beginning of our internal map
00211         CIter begin() const;
00212         //! Iterator to the one-past-end of our internal map
00213         CIter end() const;
00214         //@}
00215 
00216         //! Static accessors for locating an object with a specific identifier
00217         //! from the entire hierarchy. May return null if the object could not
00218         //! be found.
00219         static Object* findObject(ObjectId id);
00220 
00221         /**
00222          * Operation is a "command" one can perform with an object. An operation
00223          * has a name and optional list of arguments the command supports.
00224          */
00225         class DLLEXPORT Operation {
00226         public:
00227                 class Argument;
00228 
00229                 /**
00230                  * This constructor should be used by modules to describe an
00231                  * operation to an user interface. It may optionally be follwed
00232                  * by argument additions through addArgument() method.
00233                  *
00234                  * @param name                         Name of the command
00235                  * @param requiresArgs                 If arguments are required
00236                  */
00237                 Operation(const std::string &name, bool requiresArgs)
00238                 : m_name(name), m_requiresArgs(requiresArgs) {}
00239 
00240                 /**
00241                  * This constructor should be used by UI parser to construct
00242                  * a command to be sent to an object.
00243                  *
00244                  * @param name                         Name of the command
00245                  * @param args                         Optional argument list
00246                  */
00247                 Operation(const std::string &name, std::vector<Argument> args)
00248                 : m_name(name), m_argList(args) {}
00249 
00250                 //! Destructor
00251                 ~Operation() {}
00252 
00253                 /**
00254                  * Add an argument to this operation.
00255                  *
00256                  * @param arg                          Argument to be added
00257                  */
00258                 void addArg(const Argument &arg) {
00259                         m_argList.push_back(arg);
00260                 }
00261 
00262                 //! @name Accessors
00263                 //@{
00264                 uint32_t    getArgCount()  const { return m_argList.size(); }
00265                 std::string getName()      const { return m_name;           }
00266                 bool        requiresArgs() const { return m_requiresArgs;   }
00267                 Argument getArg(uint32_t num) const { return m_argList.at(num);}
00268                 //@}
00269 
00270                 /**
00271                  * Get argument by name
00272                  *
00273                  * @param name                         Argument to retrieve
00274                  * @return                             The argument, if found
00275                  *
00276                  * \throws std::runtime_error if argument is not found
00277                  */
00278                 Argument getArg(const std::string &name) const {
00279                         std::vector<Argument>::const_iterator i;
00280                         i = m_argList.begin();
00281                         while (i != m_argList.end()) {
00282                                 if ((*i).getName() == name) {
00283                                         return *i;
00284                                 }
00285                                 ++i;
00286                         }
00287                         throw std::runtime_error("Argument not found.");
00288                 }
00289 
00290                 /**
00291                  * Argument class represents one argument that can be passed
00292                  * to an operation. An argument has a name, type, and boolean
00293                  * indicating whether this argument is always required to be
00294                  * present in an operation.
00295                  */
00296                 class DLLEXPORT Argument {
00297                 public:
00298                         /**
00299                          * This constructor should be used by modules to add
00300                          * an argument to an operation being described.
00301                          *
00302                          * @param name                 Name of the argument
00303                          * @param required             If argument is required
00304                          * @param type                 Type of argument's data
00305                          */
00306                         Argument(
00307                                 const std::string &name, bool required,
00308                                 DataType type
00309                         ) : m_name(name), m_required(required), m_type(type) {}
00310 
00311                         /**
00312                          * This constructor should be used by UI parser to
00313                          * construct an argument to be added to an operation
00314                          * which is then passed to an object.
00315                          *
00316                          * @param name                 Name of the argument
00317                          * @param value                Value of the argument
00318                          *
00319                          * \note The type of argument is intentionally left
00320                          *       undefined here, since it would add nothing
00321                          *       for the creator, and the object receiving the
00322                          *       argument checks the type internally anyway.
00323                          */
00324                         Argument(
00325                                 const std::string &name,
00326                                 const std::string &value
00327                         ) : m_name(name), m_value(value) {}
00328 
00329                         //! Dummy destructor
00330                         ~Argument() {}
00331 
00332                         //! @name Accessors
00333                         //@{
00334                         std::string getValue()   const { return m_value;    }
00335                         std::string getName()    const { return m_name;     }
00336                         DataType    getType()    const { return m_type;     }
00337                         bool        isRequired() const { return m_required; }
00338                         //@}
00339                 private:
00340                         std::string m_name;      //!< Name of the argument
00341                         bool m_required;         //!< If this is required
00342                         DataType m_type;         //!< Argument value type
00343                         std::string m_value;     //!< Argument value
00344                 };
00345         private:
00346                 friend class Object;
00347                 //!< Default constructor for internal usage only
00348                 Operation() {}
00349                 std::string m_name;              //!< Name of the operation
00350                 bool m_requiresArgs;             //!< If arguments are required
00351                 std::vector<Argument> m_argList; //!< Argument list
00352         };
00353 
00354 protected:
00355         /**
00356          * Only allowed constructor.
00357          *
00358          * @param parent       Pointer to the parent object
00359          * @param name         Optional name for this object
00360          */
00361         Object(Object *parent, const std::string &name = "");
00362 
00363         /**
00364          * Protected destructor.
00365          */
00366         virtual ~Object();
00367 
00368         /**
00369          * Notify about an event. The event is propagated up the objects
00370          * hierarchy, and passed to all watchers of this object and all its
00371          * parent objects.
00372          *
00373          * @param source        Event source object identifier
00374          * @param event         Event type
00375          */
00376         void notify(ObjectId source, ObjectEvent event);
00377 
00378         /**
00379          * More convenient function for derived classes - no need to pass
00380          * source id, and event type has convenient default value.
00381          */
00382         void notify(ObjectEvent event = OBJ_MODIFIED);
00383 
00384         /**
00385          * @name Convenience methods for derived classes.
00386          * Override these functions to receive notifications about
00387          * the object's contents changes.
00388          */
00389         //@{
00390         //! A child has been added.
00391         virtual void onChildAdded(ObjectId id);
00392         //! A child has been removed (either deleted or reparented)
00393         virtual void onChildRemoved(ObjectId id);
00394         //@}
00395 private:
00396         //! Private iterator for the internal data container
00397         typedef std::map<ObjectId, Object*>::iterator Iter;
00398 
00399         //! Default constructor is private - Object needs parent for
00400         //! construction to avoid having Object's around w/o parents.
00401         Object();
00402 
00403         //! @name Copying is not allowed
00404         //@{
00405         Object(const Object&);
00406         Object& operator=(Object&);
00407         //@}
00408 
00409         //! Pointer to the parent of this object
00410         Object *m_parent;
00411 
00412         //! Optional name of this object
00413         std::string m_name;
00414 
00415         //! Unique identifier, assigned by parent upon addition
00416         ObjectId m_id;
00417 
00418         //! Map of all child objects
00419         std::map<ObjectId, Object*> *m_children;
00420 
00421         //! @name Internal usage functions. These are private on purpose.
00422         //@{
00423         //! Add a new child.
00424         void addChild(Object *child);
00425         //! Remove a child
00426         void delChild(Object *child);
00427         //@}
00428 
00429         //! Contains all identifiers currently in use and the object they
00430         //! refer to.
00431         static std::map<ObjectId, Object*> s_usedIds;
00432 };
00433 
00434 /**
00435  * Bottom line -> This is what the final data structures hierarchy might look
00436  * like:
00437         HydraNode
00438            +-- MetaDb
00439            |      +-- MetaData
00440            |      |      +-- File Size
00441            |      |      +-- Modification date
00442            |      |      +-- File Names
00443            |      |      |       |-- FileName[0]
00444            |      |      |       |-- FileName[1]
00445            |      |      |       |-- FileName[2]
00446            |      |      +-- HashSets
00447            |      |      |       +-- ED2K
00448            |      |      |       |    + PartSize (9728000)
00449            |      |      |       |    + FileHash
00450            |      |      |       |    + PartHashes
00451            |      |      |       |          + PartHash[0]
00452            |      |      |       |          + PartHash[1]
00453            |      |      |       |          + PartHash[2]
00454            |      |      |       +-- SHA1
00455            |      |      |            + PartSize (0)
00456            |      |      |            + FileHash
00457            |      |      +-- AudioMetaData
00458            |      |               + Title
00459            |      |               + Album
00460            |      |               + Performer
00461            |      +-- MetaData
00462            |             + File Size
00463            |             ...
00464            |      ...
00465            +-- SharedFilesList
00466            |       +-- SharedFile
00467            |       |       +-- FileSize
00468            |       |       +-- PartData
00469            |       |              +-- PartData
00470            |       |                     +-- Completed
00471            |       |                     +-- Verified
00472            |       +-- SharedFile
00473            |           ...
00474            +-- Modules
00475                  +-- ED2K
00476                  |     +-- ServerList
00477                  |     |        +-- Server
00478                  |     |        |     +-- IP
00479                  |     |        |     +-- Port
00480                  |     |        +-- Server
00481                  |     +-- CreditsDb
00482                  |              +-- ClientCredits
00483                  |              |        +-- Uploaded
00484                  |              |        +-- Downloaded
00485                  |              |        +-- Hash
00486                  |              |        +-- PubKey
00487                  |              +-- ClientCredits
00488                  |                       ...
00489                  +-- BitTorrent
00490                  |      +-- ...
00491                  +-- gnutella
00492                  |      +-- ...
00493                  +-- ...
00494 
00495 
00496 */
00497 
00498 #endif // !__OBJECT_H__