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