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