2  * lemon/notifier.h - Part of LEMON, a generic C++ optimization library
 
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 
     7  * Permission to use, modify and distribute this software is granted
 
     8  * provided that this copyright notice appears in all copies. For
 
     9  * precise terms see the accompanying LICENSE file.
 
    11  * This software is provided "AS IS" with no warranty of any kind,
 
    12  * express or implied, and with no claim as to its suitability for any
 
    17 #ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H
 
    18 #define LEMON_ALTERATION_OBSERVER_REGISTRY_H
 
    23 ///\ingroup graphmapfactory
 
    25 ///\brief Observer registry for graph alteration observers.
 
    29   /// \addtogroup graphmapfactory
 
    32   /// \brief Registry class to register objects observes alterations in 
 
    35   /// This class is a registry for the objects which observe the
 
    36   /// alterations in a container. The alteration observers can be attached
 
    37   /// to and detached from the registry. The observers have to inherit
 
    38   /// from the \ref AlterationNotifier::ObserverBase and override
 
    39   /// the virtual functions in that.
 
    41   /// The most important application of the alteration observing is the
 
    42   /// dynamic map implementation.
 
    44   /// \param _Item The item type what the observers are observing, usually
 
    47   /// \author Balazs Dezso
 
    49   template <typename _Item>
 
    50   class AlterationNotifier {
 
    54     /// ObserverBase is the base class for the observers.
 
    56     /// ObserverBase is the abstract base class for the observers.
 
    57     /// It will be notified about an item was inserted into or
 
    58     /// erased from the graph.
 
    60     /// The observer interface contains some pure virtual functions
 
    61     /// to override. The add() and erase() functions are
 
    62     /// to notify the oberver when one item is added or
 
    65     /// The build() and clear() members are to notify the observer
 
    66     /// about the container is built from an empty container or
 
    67     /// is cleared to an empty container. 
 
    69     /// \author Balazs Dezso
 
    73       typedef AlterationNotifier Registry;
 
    75       friend class AlterationNotifier;
 
    77       /// \brief Default constructor.
 
    79       /// Default constructor for ObserverBase.
 
    81       ObserverBase() : registry(0) {}
 
    83       virtual ~ObserverBase() {}
 
    85       /// \brief Attaches the observer into an AlterationNotifier.
 
    87       /// This member attaches the observer into an AlterationNotifier.
 
    89       void attach(AlterationNotifier& r) {
 
    91 	registry->attach(*this);
 
    94       /// \brief Detaches the observer into an AlterationNotifier.
 
    96       /// This member detaches the observer from an AlterationNotifier.
 
   100 	  registry->detach(*this);
 
   105       /// Gives back a pointer to the registry what the map attached into.
 
   107       /// This function gives back a pointer to the registry what the map
 
   110       Registry* getRegistry() const { return const_cast<Registry*>(registry); }
 
   112       /// Gives back true when the observer is attached into a registry.
 
   113       bool attached() const { return registry != 0; }
 
   117       ObserverBase(const ObserverBase& copy);
 
   118       ObserverBase& operator=(const ObserverBase& copy);
 
   127       /// \brief The member function to notificate the observer about an
 
   128       /// item is added to the container.
 
   130       /// The add() member function notificates the observer about an item
 
   131       /// is added to the container. It have to be overrided in the
 
   134       virtual void add(const Item&) = 0;
 
   136       /// \brief The member function to notificate the observer about 
 
   137       /// simulitem is added to the container.
 
   139       /// The add() member function notificates the observer about an item
 
   140       /// is added to the container. It have to be overrided in the
 
   143       virtual void add(const std::vector<Item>& items) {
 
   144 	for (int i = 0; i < (int)items.size(); ++i) {
 
   149       /// \brief The member function to notificate the observer about an
 
   150       /// item is erased from the container.
 
   152       /// The erase() member function notificates the observer about an
 
   153       /// item is erased from the container. It have to be overrided in
 
   156       virtual void erase(const Item&) = 0;
 
   158       virtual void erase(const std::vector<Item>& items) {
 
   159 	for (int i = 0; i < (int)items.size(); ++i) {
 
   164       /// \brief The member function to notificate the observer about the
 
   165       /// container is built.
 
   167       /// The build() member function notificates the observer about the
 
   168       /// container is built from an empty container. It have to be
 
   169       /// overrided in the subclasses.
 
   171       virtual void build() = 0;
 
   173       /// \brief The member function to notificate the observer about all
 
   174       /// items are erased from the container.
 
   176       /// The clear() member function notificates the observer about all
 
   177       /// items are erased from the container. It have to be overrided in
 
   180       virtual void clear() = 0;
 
   187     typedef std::vector<ObserverBase*> Container; 
 
   194     /// Default constructor.
 
   197     /// The default constructor of the AlterationNotifier. 
 
   198     /// It creates an empty registry.
 
   199     AlterationNotifier() {}
 
   201     /// Copy Constructor of the AlterationNotifier. 
 
   203     /// Copy constructor of the AlterationNotifier. 
 
   204     /// It creates only an empty registry because the copiable
 
   205     /// registry's observers have to be registered still into that registry.
 
   206     AlterationNotifier(const AlterationNotifier&) {}
 
   210     /// Assign operator for the AlterationNotifier. 
 
   211     /// It makes the notifier only empty because the copiable
 
   212     /// notifier's observers have to be registered still into that registry.
 
   213     AlterationNotifier& operator=(const AlterationNotifier&) {
 
   214       typename Container::iterator it;
 
   215       for (it = container.begin(); it != container.end(); ++it) {
 
   222     /// Destructor of the AlterationNotifier.
 
   224     ~AlterationNotifier() {
 
   225       typename Container::iterator it;
 
   226       for (it = container.begin(); it != container.end(); ++it) {
 
   234     void attach(ObserverBase& observer) {
 
   235       container.push_back(&observer);
 
   236       observer.registry = this;
 
   237       observer.registry_index = container.size()-1;
 
   240     void detach(ObserverBase& base) {
 
   241       container.back()->registry_index = base.registry_index; 
 
   242       container[base.registry_index] = container.back();
 
   243       container.pop_back();
 
   249     /// \brief Notifies all the registered observers about an Item added to 
 
   252     /// It notifies all the registered observers about an Item added to 
 
   255     void add(const Item& item) {
 
   256       typename Container::iterator it;
 
   257       for (it = container.begin(); it != container.end(); ++it) {
 
   262     /// \brief Notifies all the registered observers about more Item added to 
 
   265     /// It notifies all the registered observers about more Item added to 
 
   268     void add(const std::vector<Item>& items) {
 
   269       typename Container::iterator it;
 
   270       for (it = container.begin(); it != container.end(); ++it) {
 
   275     /// \brief Notifies all the registered observers about an Item erased from 
 
   278     /// It notifies all the registered observers about an Item erased from 
 
   281     void erase(const Item& key) {
 
   282       typename Container::iterator it;
 
   283       for (it = container.begin(); it != container.end(); ++it) {
 
   288     /// \brief Notifies all the registered observers about more Item erased  
 
   289     /// from the container.
 
   291     /// It notifies all the registered observers about more Item erased from 
 
   294     void erase(const std::vector<Item>& items) {
 
   295       typename Container::iterator it;
 
   296       for (it = container.begin(); it != container.end(); ++it) {
 
   302     /// \brief Notifies all the registered observers about the container is 
 
   305     /// Notifies all the registered observers about the container is built
 
   306     /// from an empty container.
 
   308       typename Container::iterator it;
 
   309       for (it = container.begin(); it != container.end(); ++it) {
 
   315     /// \brief Notifies all the registered observers about all Items are 
 
   318     /// Notifies all the registered observers about all Items are erased
 
   319     /// from the container.
 
   321       typename Container::iterator it;
 
   322       for (it = container.begin(); it != container.end(); ++it) {
 
   329   /// \brief Class to extend a graph with the functionality of alteration
 
   332   /// AlterableGraphExtender extends the _Base graphs functionality with
 
   333   /// the possibility of alteration observing. It defines two observer
 
   334   /// registrys for the nodes and mapes.
 
   336   /// \todo Document what "alteration observing" is. And probably find a
 
   337   /// better (shorter) name.
 
   339   /// \param _Base is the base class to extend.
 
   341   /// \pre _Base is conform to the BaseGraphComponent concept.
 
   343   /// \post AlterableGraphExtender<_Base> is conform to the
 
   344   /// AlterableGraphComponent concept.
 
   346   /// \author Balazs Dezso
 
   348   template <typename _Base> 
 
   349   class AlterableGraphExtender : public _Base {
 
   352     typedef AlterableGraphExtender Graph;
 
   353     typedef _Base Parent;
 
   355     typedef typename Parent::Node Node;
 
   356     typedef typename Parent::Edge Edge;
 
   358     /// The edge observer registry.
 
   359     typedef AlterationNotifier<Edge> EdgeNotifier;
 
   360     /// The node observer registry.
 
   361     typedef AlterationNotifier<Node> NodeNotifier;
 
   366     mutable EdgeNotifier edge_notifier;
 
   368     mutable NodeNotifier node_notifier;
 
   372     /// \brief Gives back the edge alteration notifier.
 
   374     /// Gives back the edge alteration notifier.
 
   375     EdgeNotifier& getNotifier(Edge) const {
 
   376       return edge_notifier;
 
   379     /// \brief Gives back the node alteration notifier.
 
   381     /// Gives back the node alteration notifier.
 
   382     NodeNotifier& getNotifier(Node) const {
 
   383       return node_notifier;
 
   386     ~AlterableGraphExtender() {
 
   387       node_notifier.clear();
 
   388       edge_notifier.clear();
 
   393   /// \brief Class to extend an undirected graph with the functionality of
 
   394   /// alteration observing.
 
   398   /// \sa AlterableGraphExtender
 
   400   /// \bug This should be done some other way. Possibilities: template
 
   401   /// specialization (not very easy, if at all possible); some kind of
 
   402   /// enable_if boost technique?
 
   404   template <typename _Base> 
 
   405   class AlterableUndirGraphExtender
 
   406     : public AlterableGraphExtender<_Base> {
 
   409     typedef AlterableUndirGraphExtender Graph;
 
   410     typedef AlterableGraphExtender<_Base> Parent;
 
   412     typedef typename Parent::UndirEdge UndirEdge;
 
   414     /// The edge observer registry.
 
   415     typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
 
   419     mutable UndirEdgeNotifier undir_edge_notifier;
 
   423     using Parent::getNotifier;
 
   424     UndirEdgeNotifier& getNotifier(UndirEdge) const {
 
   425       return undir_edge_notifier;
 
   428     ~AlterableUndirGraphExtender() {
 
   429       undir_edge_notifier.clear();