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