src/hugo/map_registry.h
author marci
Thu, 02 Sep 2004 17:56:40 +0000
changeset 792 147eb3a58706
parent 785 a9b0863c2265
child 822 88226d9fe821
permissions -rw-r--r--
Nicer and more documented graph_wrapper.h file.
These are only the first steps for making this file more beautiful.
deba@782
     1
// -*- c++ -*-
deba@782
     2
#ifndef MAP_REGISTRY_H
deba@782
     3
#define MAP_REGISTRY_H
deba@782
     4
deba@782
     5
#include <vector>
deba@782
     6
alpar@785
     7
///\ingroup graphmapfactory
alpar@785
     8
///\file
alpar@785
     9
///\brief Map registry for graph maps.
alpar@785
    10
deba@782
    11
using namespace std;
deba@782
    12
deba@782
    13
namespace hugo {
deba@782
    14
alpar@785
    15
/// \addtogroup graphmapfactory
alpar@785
    16
/// @{
alpar@785
    17
deba@782
    18
/** 
deba@782
    19
 * Registry class to register edge or node maps into the graph. The
deba@782
    20
 * registry helps you to implement an observer pattern. If you add
deba@782
    21
 * or erase an edge or node you must notify all the maps about the
deba@782
    22
 * event.
deba@782
    23
*/
deba@782
    24
  template <typename G, typename K, typename KIt>
deba@782
    25
  class MapRegistry {
deba@782
    26
  public:
deba@782
    27
    typedef G Graph;
alpar@786
    28
    typedef K KeyType;
deba@782
    29
    typedef KIt KeyIt;
deba@782
    30
	
deba@782
    31
deba@782
    32
deba@782
    33
    /**
deba@782
    34
     * MapBase is the base class of the registered maps.
deba@782
    35
     * It defines the core modification operations on the maps and
deba@782
    36
     * implements some helper functions. 
deba@782
    37
     */
deba@782
    38
    class MapBase {
deba@782
    39
    public:
deba@782
    40
      typedef G Graph;
alpar@786
    41
      typedef K KeyType;
deba@782
    42
      typedef KIt KeyIt;
deba@782
    43
deba@782
    44
      typedef MapRegistry<G, K, KIt> Registry;
deba@782
    45
	
deba@782
    46
      friend class MapRegistry<G, K, KIt>;
deba@782
    47
deba@782
    48
      /**
deba@782
    49
       * Default constructor for MapBase.
deba@782
    50
       */
deba@782
    51
deba@782
    52
      MapBase() : graph(0), registry(0) {}
deba@782
    53
		
deba@782
    54
      /** 
deba@782
    55
       * Simple constructor to register into a graph registry.
deba@782
    56
      */
deba@782
    57
	
deba@782
    58
      MapBase(const Graph& g, Registry& r) : graph(&g), registry(0) {
deba@782
    59
	r.attach(*this);
deba@782
    60
      }
deba@782
    61
deba@782
    62
      /** 
deba@782
    63
       * Copy constructor to register into the registry.
deba@782
    64
      */	
deba@782
    65
	
deba@783
    66
      MapBase(const MapBase& copy) : graph(copy.graph), registry(0) {
deba@782
    67
	if (copy.registry) {
deba@782
    68
	  copy.registry->attach(*this);
deba@782
    69
	}
deba@782
    70
      } 
deba@782
    71
	
deba@782
    72
      /** 
deba@782
    73
       * Assign operator.
deba@782
    74
      */	
deba@782
    75
deba@782
    76
      const MapBase& operator=(const MapBase& copy) {
deba@782
    77
	if (registry) {
deba@782
    78
	  registry->detach(*this);
deba@782
    79
	}
deba@782
    80
	graph = copy.graph;
deba@782
    81
	if (copy.registry) {
deba@782
    82
	  copy.registry->attach(*this);
deba@782
    83
	}
deba@783
    84
	return *this;
deba@782
    85
      }
deba@782
    86
	
deba@782
    87
deba@782
    88
      /** 
deba@782
    89
       * Destructor. 
deba@782
    90
      */		
deba@782
    91
deba@782
    92
      virtual ~MapBase() {
deba@782
    93
	if (registry) {
deba@782
    94
	  registry->detach(*this);
deba@782
    95
	}
deba@782
    96
      }
deba@782
    97
deba@782
    98
      /*
deba@782
    99
       * Returns the graph that the map belongs to.
deba@782
   100
      */
deba@782
   101
deba@782
   102
      const Graph* getGraph() const { return graph; }
deba@782
   103
	
deba@782
   104
    protected:
deba@782
   105
		
deba@782
   106
      const Graph* graph;     
deba@782
   107
      Registry* registry;
deba@782
   108
deba@782
   109
      int registry_index;
deba@782
   110
deba@782
   111
    protected:
deba@782
   112
	
deba@782
   113
      /**
deba@782
   114
	 Helper function to implement constructors in the subclasses.
deba@782
   115
      */
deba@782
   116
	
deba@782
   117
      virtual void init() {
deba@782
   118
	for (KeyIt it(*graph); it != INVALID; ++it) {
deba@782
   119
	  add(it);
deba@782
   120
	}
deba@782
   121
      }
deba@782
   122
	
deba@782
   123
      /**
deba@782
   124
	 Helper function to implement the destructor in the subclasses.
deba@782
   125
      */
deba@782
   126
	
deba@782
   127
      virtual void destroy() {
deba@782
   128
	for (KeyIt it(*getGraph()); it != INVALID; ++it) {
deba@782
   129
	  erase(it);
deba@782
   130
	}
deba@782
   131
      }
deba@782
   132
	
deba@782
   133
      /** 
deba@782
   134
	  The add member function should be overloaded in the subclasses.
deba@782
   135
	  \e Add extends the map with the new node.
deba@782
   136
      */
deba@782
   137
	
alpar@786
   138
      virtual void add(const KeyType&) = 0;	
deba@782
   139
      /** 
deba@782
   140
	  The erase member function should be overloaded in the subclasses.
deba@782
   141
	  \e Erase removes the node from the map.
deba@782
   142
      */
deba@782
   143
	
alpar@786
   144
      virtual void erase(const KeyType&) = 0;
deba@782
   145
deba@782
   146
      /**
deba@782
   147
       *  The clear member function should be overloaded in the subclasses.
deba@782
   148
       *  \e Clear makes empty the data structure.
deba@782
   149
       */
deba@782
   150
deba@782
   151
      virtual void clear() = 0;
deba@782
   152
	
deba@782
   153
      /**
deba@782
   154
	 Exception class to throw at unsupported operation.
deba@782
   155
      */
deba@782
   156
	
deba@782
   157
      class NotSupportedOperationException {};
deba@782
   158
deba@782
   159
    };
deba@782
   160
	
deba@782
   161
  protected:
deba@782
   162
	
deba@782
   163
    /** 
deba@782
   164
     * The container type of the maps.
deba@782
   165
     */
deba@782
   166
    typedef std::vector<MapBase*> Container; 
deba@782
   167
deba@782
   168
    /**
deba@782
   169
     * The container of the registered maps.
deba@782
   170
     */
deba@782
   171
    Container container;
deba@782
   172
deba@782
   173
		
deba@782
   174
  public:
deba@782
   175
	
deba@782
   176
    /**
deba@782
   177
     * Default Constructor of the MapRegistry. It creates an empty registry.
deba@782
   178
     */
deba@782
   179
    MapRegistry() {}
deba@782
   180
	
deba@782
   181
    /**
deba@782
   182
     * Copy Constructor of the MapRegistry. The new registry does not steal
deba@782
   183
     * the maps from the right value. The new registry will be an empty.
deba@782
   184
     */
deba@782
   185
    MapRegistry(const MapRegistry&) {}
deba@782
   186
		
deba@782
   187
    /**
deba@782
   188
     * Assign operator. The left value does not steal the maps 
deba@782
   189
     * from the right value. The left value will be an empty registry.
deba@782
   190
     */
deba@782
   191
    MapRegistry& operator=(const MapRegistry&) {
deba@782
   192
      typename Container::iterator it;
deba@782
   193
      for (it = container.begin(); it != container.end(); ++it) {
deba@782
   194
	(*it)->destroy();
deba@782
   195
	(*it)->graph = 0;
deba@782
   196
	(*it)->registry = 0;
deba@782
   197
      }
deba@782
   198
    }
deba@782
   199
				
deba@782
   200
    /**
deba@782
   201
     * Destructor of the MapRegistry.
deba@782
   202
     */
deba@782
   203
    ~MapRegistry() {
deba@782
   204
      typename Container::iterator it;
deba@782
   205
      for (it = container.begin(); it != container.end(); ++it) {
deba@782
   206
	(*it)->destroy();
deba@782
   207
	(*it)->registry = 0;
deba@782
   208
	(*it)->graph = 0;
deba@782
   209
      }
deba@782
   210
    }
deba@782
   211
	
deba@782
   212
	
deba@782
   213
    public:
deba@782
   214
	
deba@782
   215
    /**
deba@782
   216
     * Attach a map into thr registry. If the map has been attached
deba@782
   217
     * into an other registry it is detached from that automaticly.
deba@782
   218
     */
deba@782
   219
    void attach(MapBase& map) {
deba@782
   220
      if (map.registry) {
deba@782
   221
	map.registry->detach(map);
deba@782
   222
      }
deba@782
   223
      container.push_back(&map);
deba@782
   224
      map.registry = this;
deba@782
   225
      map.registry_index = container.size()-1;
deba@782
   226
    } 
deba@782
   227
	
deba@782
   228
    /**
deba@782
   229
     * Detach the map from the registry.
deba@782
   230
     */
deba@782
   231
    void detach(MapBase& map) {
deba@782
   232
      container.back()->registry_index = map.registry_index; 
deba@782
   233
      container[map.registry_index] = container.back();
deba@782
   234
      container.pop_back();
deba@782
   235
      map.registry = 0;
deba@782
   236
      map.graph = 0;
deba@782
   237
    }
deba@782
   238
	
deba@782
   239
		
deba@782
   240
    /**
deba@782
   241
     * Notify all the registered maps about a Key added.
deba@782
   242
     */
alpar@786
   243
    void add(KeyType& key) {
deba@782
   244
      typename Container::iterator it;
deba@782
   245
      for (it = container.begin(); it != container.end(); ++it) {
deba@782
   246
	(*it)->add(key);
deba@782
   247
      }
deba@782
   248
    }	
deba@782
   249
		
deba@782
   250
    /**
deba@782
   251
     * Notify all the registered maps about a Key erased.
deba@782
   252
     */ 
alpar@786
   253
    void erase(KeyType& key) {
deba@782
   254
      typename Container::iterator it;
deba@782
   255
      for (it = container.begin(); it != container.end(); ++it) {
deba@782
   256
	(*it)->erase(key);
deba@782
   257
      }
deba@782
   258
    }
deba@782
   259
deba@782
   260
    /**
deba@782
   261
     * Notify all the registered maps about the map should be cleared.
deba@782
   262
     */ 
deba@783
   263
    void clear() {
deba@782
   264
      typename Container::iterator it;
deba@782
   265
      for (it = container.begin(); it != container.end(); ++it) {
deba@782
   266
	(*it)->clear();
deba@782
   267
      }
deba@782
   268
    }
deba@782
   269
  };
deba@782
   270
alpar@785
   271
  
alpar@785
   272
/// @}
alpar@785
   273
  
alpar@785
   274
deba@782
   275
}
deba@782
   276
deba@782
   277
#endif