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