src/work/deba/map_registry.h
author alpar
Tue, 06 Jul 2004 11:28:20 +0000
changeset 696 48aa9ace1d7d
parent 627 6cc21a9c9fda
child 701 c03e073b8394
permissions -rw-r--r--
Example in the doc is corrected.
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@676
     8
namespace hugo {
alpar@676
     9
deba@627
    10
/** 
deba@627
    11
    Registry class to register edge or node maps in the graph. The
deba@627
    12
    registry helps you to implement an observer pattern. If you add
deba@627
    13
    or erase an edge or node you must notify all the maps about the
deba@627
    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
alpar@676
    25
    ///. 
alpar@676
    26
alpar@676
    27
    ///. 
alpar@676
    28
    /// 
deba@627
    29
    class MapBase {
deba@627
    30
    public:
deba@627
    31
      typedef G Graph;
deba@627
    32
      typedef MapRegistry<G, K, KIt> Registry;
deba@627
    33
      typedef K Key;
deba@627
    34
      typedef KIt KeyIt;
deba@378
    35
	
deba@627
    36
      friend class Registry;
deba@627
    37
		
deba@627
    38
      /** 
deba@627
    39
	  Default constructor.
deba@627
    40
      */	
deba@627
    41
		
deba@627
    42
      MapBase() : graph(0), registry(0) {}
deba@627
    43
deba@627
    44
      /** 
deba@627
    45
	  Simple constructor to register into a graph registry.
deba@627
    46
      */
deba@378
    47
	
deba@627
    48
      MapBase(Graph& g, Registry& r) : graph(&g), registry(0) {
deba@627
    49
	r.attach(*this);
deba@627
    50
      }
deba@627
    51
deba@627
    52
      /** 
deba@627
    53
	  Copy constructor with registering into the map.
deba@627
    54
      */	
deba@627
    55
	
deba@627
    56
      MapBase(const MapBase& copy) : registry(0), graph(copy.graph) {
deba@627
    57
	if (copy.registry) {
deba@627
    58
	  copy.registry->attach(*this);
deba@627
    59
	}
deba@627
    60
      } 
deba@627
    61
	
deba@627
    62
      /** 
deba@627
    63
	  Assign operator.
deba@627
    64
      */	
deba@627
    65
deba@627
    66
      const MapBase& operator=(const MapBase& copy) {
deba@627
    67
	if (registry) {
deba@627
    68
	  registry->detach(*this);
deba@627
    69
	}
deba@627
    70
	graph = copy.graph;
deba@627
    71
	if (copy.registry) {
deba@627
    72
	  copy.registry->attach(*this);
deba@627
    73
	}
deba@627
    74
      }
deba@627
    75
	
deba@627
    76
deba@627
    77
      /** 
deba@627
    78
	  Destructor.
deba@627
    79
      */		
deba@627
    80
deba@627
    81
      virtual ~MapBase() {
deba@627
    82
	if (registry) {
deba@627
    83
	  registry->detach(*this);
deba@627
    84
	}
deba@627
    85
      }
deba@627
    86
	
deba@627
    87
    protected:
deba@627
    88
		
deba@627
    89
      Graph* graph;
deba@627
    90
      Registry* registry;
deba@627
    91
deba@627
    92
      int registry_index;
deba@627
    93
	
deba@627
    94
      /**
deba@627
    95
	 Helper function to implement constructors in the subclasses.
deba@627
    96
      */
deba@627
    97
	
deba@627
    98
      virtual void init() {
deba@627
    99
	for (KeyIt it(*graph); graph->valid(it); graph->next(it)) {
deba@627
   100
	  add(it);
deba@627
   101
	}
deba@627
   102
      }
deba@627
   103
	
deba@627
   104
      /**
deba@627
   105
	 Helper function to implement the destructor in the subclasses.
deba@627
   106
      */
deba@627
   107
	
deba@627
   108
      virtual void destroy() {
deba@627
   109
	for (KeyIt it(*graph); graph->valid(it); graph->next(it)) {
deba@627
   110
	  erase(it);
deba@627
   111
	}
deba@627
   112
      }
deba@627
   113
	
deba@627
   114
      /** 
deba@627
   115
	  The add member function should be overloaded in the subclasses.
deba@627
   116
	  \e Add extends the map with the new node.
deba@627
   117
      */
deba@627
   118
	
deba@627
   119
      virtual void add(const Key&) = 0;	
deba@627
   120
      /** 
deba@627
   121
	  The erase member function should be overloaded in the subclasses.
deba@627
   122
	  \e Erase removes the node from the map.
deba@627
   123
      */
deba@627
   124
	
deba@627
   125
      virtual void erase(const Key&) = 0;
deba@627
   126
	
deba@627
   127
      /**
deba@627
   128
	 Exception class to throw at unsupported operation.
deba@627
   129
      */
deba@627
   130
	
deba@627
   131
      class NotSupportedOperationException {};
deba@627
   132
deba@627
   133
    };
deba@627
   134
	
deba@627
   135
  protected:
deba@627
   136
	
deba@627
   137
    typedef std::vector<MapBase*> Container; 
deba@627
   138
    Container container;
deba@378
   139
deba@378
   140
		
deba@627
   141
    public:
deba@378
   142
	
alpar@676
   143
    ///. 
deba@627
   144
    MapRegistry() {}
deba@571
   145
	
alpar@676
   146
    ///.
deba@627
   147
    MapRegistry(const MapRegistry&) {}
deba@571
   148
		
alpar@676
   149
    ///.
deba@627
   150
    MapRegistry& operator=(const MapRegistry&) {
deba@627
   151
      for (it = container.begin(); it != container.end(); ++it) {
deba@627
   152
	(*it)->destroy();
deba@627
   153
	(*it)->graph = 0;
deba@627
   154
	(*it)->registry = 0;
deba@627
   155
      }
deba@627
   156
    }
deba@378
   157
				
alpar@676
   158
    ///.
deba@627
   159
    ~MapRegistry() {
deba@627
   160
      typename Container::iterator it;
deba@627
   161
      for (it = container.begin(); it != container.end(); ++it) {
deba@627
   162
	(*it)->destroy();
deba@627
   163
	(*it)->registry = 0;
deba@627
   164
	(*it)->graph = 0;
deba@627
   165
      }
deba@627
   166
    }
deba@378
   167
	
deba@378
   168
	
deba@627
   169
    public:
deba@378
   170
	
alpar@676
   171
    ///.
deba@627
   172
    void attach(MapBase& map) {
deba@627
   173
      if (map.registry) {
deba@627
   174
	map.registry->detach(map);
deba@627
   175
      }
deba@627
   176
      container.push_back(&map);
deba@627
   177
      map.registry = this;
deba@627
   178
      map.registry_index = container.size()-1;
deba@627
   179
    } 
deba@378
   180
	
alpar@676
   181
    ///.
deba@627
   182
    void detach(MapBase& map) {
deba@627
   183
      container.back()->registry_index = map.registry_index; 
deba@627
   184
      container[map.registry_index] = container.back();
deba@627
   185
      container.pop_back();
deba@627
   186
      map.registry = 0;
deba@627
   187
      map.graph = 0;
deba@627
   188
    }
deba@378
   189
	
deba@378
   190
		
alpar@676
   191
    ///. 
deba@627
   192
    virtual void add(Key& key) {
deba@627
   193
      typename Container::iterator it;
deba@627
   194
      for (it = container.begin(); it != container.end(); ++it) {
deba@627
   195
	(*it)->add(key);
deba@627
   196
      }
deba@627
   197
    }	
deba@378
   198
		
alpar@676
   199
    ///.
deba@627
   200
    virtual void erase(Key& key) {
deba@627
   201
      typename Container::iterator it;
deba@627
   202
      for (it = container.begin(); it != container.end(); ++it) {
deba@627
   203
	(*it)->erase(key);
deba@627
   204
      }
deba@627
   205
    }
deba@378
   206
deba@627
   207
  };
deba@378
   208
deba@378
   209
}
deba@378
   210
deba@378
   211
#endif