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