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 ObserverBase(const ObserverBase& copy) {
84 if (copy.attached()) {
85 copy.getRegistry()->attach(*this);
89 virtual ~ObserverBase() {}
91 /// \brief Attaches the observer into an AlterationNotifier.
93 /// This member attaches the observer into an AlterationNotifier.
95 void attach(AlterationNotifier& r) {
97 registry->attach(*this);
100 /// \brief Detaches the observer into an AlterationNotifier.
102 /// This member detaches the observer from an AlterationNotifier.
106 registry->detach(*this);
111 /// Gives back a pointer to the registry what the map attached into.
113 /// This function gives back a pointer to the registry what the map
116 Registry* getRegistry() const { return const_cast<Registry*>(registry); }
118 /// Gives back true when the observer is attached into a registry.
119 bool attached() const { return registry != 0; }
123 ObserverBase& operator=(const ObserverBase& copy);
132 /// \brief The member function to notificate the observer about an
133 /// item is added to the container.
135 /// The add() member function notificates the observer about an item
136 /// is added to the container. It have to be overrided in the
139 virtual void add(const Item&) = 0;
141 /// \brief The member function to notificate the observer about
142 /// more item is added to the container.
144 /// The add() member function notificates the observer about more item
145 /// is added to the container. It have to be overrided in the
148 virtual void add(const std::vector<Item>& items) {
149 for (int i = 0; i < (int)items.size(); ++i) {
154 /// \brief The member function to notificate the observer about an
155 /// item is erased from the container.
157 /// The erase() member function notificates the observer about an
158 /// item is erased from the container. It have to be overrided in
161 virtual void erase(const Item&) = 0;
163 /// \brief The member function to notificate the observer about
164 /// more item is erased from the container.
166 /// The erase() member function notificates the observer about more item
167 /// is erased from the container. It have to be overrided in the
169 virtual void erase(const std::vector<Item>& items) {
170 for (int i = 0; i < (int)items.size(); ++i) {
175 /// \brief Signal a property change on the given item.
177 /// Signal a property change on the given item. It should
178 /// be used always with the commitChange() function.
179 /// This function is called always the property change.
180 /// The commitChange() is called always after the change.
181 virtual void signalChange(const Item&) {}
183 /// \brief Commit the property change on the given item.
185 /// Commit the property change on the given item. It should
186 /// be used always with the signalChange() function.
187 /// This function is called always the property change.
188 /// The commitChange() is called always after the change.
189 virtual void commitChange(const Item&) {}
191 /// \brief The member function to notificate the observer about the
192 /// container is built.
194 /// The build() member function notificates the observer about the
195 /// container is built from an empty container. It have to be
196 /// overrided in the subclasses.
198 virtual void build() = 0;
200 /// \brief The member function to notificate the observer about all
201 /// items are erased from the container.
203 /// The clear() member function notificates the observer about all
204 /// items are erased from the container. It have to be overrided in
207 virtual void clear() = 0;
214 typedef std::vector<ObserverBase*> Container;
221 /// Default constructor.
224 /// The default constructor of the AlterationNotifier.
225 /// It creates an empty registry.
226 AlterationNotifier() {}
228 /// Copy Constructor of the AlterationNotifier.
230 /// Copy constructor of the AlterationNotifier.
231 /// It creates only an empty registry because the copiable
232 /// registry's observers have to be registered still into that registry.
233 AlterationNotifier(const AlterationNotifier&) {}
237 /// Assign operator for the AlterationNotifier.
238 /// It makes the notifier only empty because the copiable
239 /// notifier's observers have to be registered still into that registry.
240 AlterationNotifier& operator=(const AlterationNotifier&) {
241 typename Container::iterator it;
242 for (it = container.begin(); it != container.end(); ++it) {
249 /// Destructor of the AlterationNotifier.
251 ~AlterationNotifier() {
252 typename Container::iterator it;
253 for (it = container.begin(); it != container.end(); ++it) {
261 void attach(ObserverBase& observer) {
262 container.push_back(&observer);
263 observer.registry = this;
264 observer.registry_index = container.size()-1;
267 void detach(ObserverBase& base) {
268 container.back()->registry_index = base.registry_index;
269 container[base.registry_index] = container.back();
270 container.pop_back();
276 /// \brief Notifies all the registered observers about an Item added to
279 /// It notifies all the registered observers about an Item added to
282 void add(const Item& item) {
283 typename Container::iterator it;
284 for (it = container.begin(); it != container.end(); ++it) {
289 /// \brief Notifies all the registered observers about more Item added to
292 /// It notifies all the registered observers about more Item added to
295 void add(const std::vector<Item>& items) {
296 typename Container::iterator it;
297 for (it = container.begin(); it != container.end(); ++it) {
302 /// \brief Notifies all the registered observers about an Item erased from
305 /// It notifies all the registered observers about an Item erased from
308 void erase(const Item& key) {
309 typename Container::iterator it;
310 for (it = container.begin(); it != container.end(); ++it) {
315 /// \brief Notifies all the registered observers about more Item erased
316 /// from the container.
318 /// It notifies all the registered observers about more Item erased from
321 void erase(const std::vector<Item>& items) {
322 typename Container::iterator it;
323 for (it = container.begin(); it != container.end(); ++it) {
328 /// \brief Signal a property change on the given item.
330 /// Signal a property change on the given item. It should
331 /// be used always with the commitChange() function.
332 /// This function is called always the property change.
333 /// The commitChange() is called always after the change.
334 void signalChange(const Item& item) {
335 typename Container::iterator it;
336 for (it = container.begin(); it != container.end(); ++it) {
337 (*it)->signalChange(item);
341 /// \brief Commit the property change on the given item.
343 /// Commit the property change on the given item. It should
344 /// be used always with the signalChange() function.
345 /// This function is called always the property change.
346 /// The commitChange() is called always after the change.
347 void commitChange(const Item& item) {
348 typename Container::iterator it;
349 for (it = container.begin(); it != container.end(); ++it) {
350 (*it)->commitChange(item);
354 /// \brief Notifies all the registered observers about the container is
357 /// Notifies all the registered observers about the container is built
358 /// from an empty container.
360 typename Container::iterator it;
361 for (it = container.begin(); it != container.end(); ++it) {
367 /// \brief Notifies all the registered observers about all Items are
370 /// Notifies all the registered observers about all Items are erased
371 /// from the container.
373 typename Container::iterator it;
374 for (it = container.begin(); it != container.end(); ++it) {
381 /// \brief Class to extend a graph with the functionality of alteration
384 /// AlterableGraphExtender extends the _Base graphs functionality with
385 /// the possibility of alteration observing. It defines two observer
386 /// registrys for the nodes and mapes.
388 /// \todo Document what "alteration observing" is. And probably find a
389 /// better (shorter) name.
391 /// \param _Base is the base class to extend.
393 /// \pre _Base is conform to the BaseGraphComponent concept.
395 /// \post AlterableGraphExtender<_Base> is conform to the
396 /// AlterableGraphComponent concept.
398 /// \author Balazs Dezso
400 template <typename _Base>
401 class AlterableGraphExtender : public _Base {
404 typedef AlterableGraphExtender Graph;
405 typedef _Base Parent;
407 typedef typename Parent::Node Node;
408 typedef typename Parent::Edge Edge;
410 /// The edge observer registry.
411 typedef AlterationNotifier<Edge> EdgeNotifier;
412 /// The node observer registry.
413 typedef AlterationNotifier<Node> NodeNotifier;
418 mutable EdgeNotifier edge_notifier;
420 mutable NodeNotifier node_notifier;
424 /// \brief Gives back the edge alteration notifier.
426 /// Gives back the edge alteration notifier.
427 EdgeNotifier& getNotifier(Edge) const {
428 return edge_notifier;
431 /// \brief Gives back the node alteration notifier.
433 /// Gives back the node alteration notifier.
434 NodeNotifier& getNotifier(Node) const {
435 return node_notifier;
438 ~AlterableGraphExtender() {
439 node_notifier.clear();
440 edge_notifier.clear();
445 /// \brief Class to extend an undirected graph with the functionality of
446 /// alteration observing.
450 /// \sa AlterableGraphExtender
452 /// \bug This should be done some other way. Possibilities: template
453 /// specialization (not very easy, if at all possible); some kind of
454 /// enable_if boost technique?
456 template <typename _Base>
457 class AlterableUndirGraphExtender
458 : public AlterableGraphExtender<_Base> {
461 typedef AlterableUndirGraphExtender Graph;
462 typedef AlterableGraphExtender<_Base> Parent;
464 typedef typename Parent::UndirEdge UndirEdge;
466 /// The edge observer registry.
467 typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
471 mutable UndirEdgeNotifier undir_edge_notifier;
475 using Parent::getNotifier;
476 UndirEdgeNotifier& getNotifier(UndirEdge) const {
477 return undir_edge_notifier;
480 ~AlterableUndirGraphExtender() {
481 undir_edge_notifier.clear();