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