ObjectDispatcher.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2006-2007 by Peter Dimov.
00004 
00005 This file is part of Calitko (http://www.calitko.org).
00006 
00007 Calitko is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 Calitko is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Calitko; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 */
00022 
00023 #ifndef UTILS__OBJECT_DISPATCHER_H
00024 #define UTILS__OBJECT_DISPATCHER_H
00025 
00026 #include "Imports.h"
00027 #include "Callable.h"
00028 
00029 namespace Utils {
00030 
00032 
00076 template <typename DispatchBase, typename Sender = void>
00077 class ObjectDispatcher
00078 {
00079 public:
00080     typedef Callable <void (const DispatchBase &)>  DispatchBaseHandler;
00081     typedef Callable <void (const DispatchBase &, Sender *)>
00082                                                     DispatchBaseSenderHandler;
00083 
00085     ObjectDispatcher()
00086      :  catchAllHandlers(), handlers(), notHandledHandlers()
00087     {
00088     }
00089 
00091     ~ObjectDispatcher()
00092     {
00093         foreach (Handler *handler, catchAllHandlers + handlers.values()
00094                                     + notHandledHandlers)
00095             delete handler;
00096 
00097         catchAllHandlers.clear();
00098         handlers.clear();
00099         notHandledHandlers.clear();
00100     }
00101 
00103     void registerCatchAllHandler (const DispatchBaseHandler &handler)
00104     {
00105         doRegisterCatchAllHandler (
00106                             new TypeHandler <DispatchBaseHandler> (handler));
00107     }
00108 
00110     void registerCatchAllHandler (const DispatchBaseSenderHandler &handler)
00111     {
00112         doRegisterCatchAllHandler (
00113             new TypeHandlerWithSender <DispatchBaseSenderHandler> (handler));
00114     }
00115 
00117     template <typename T>
00118     void registerTypeHandler (const Callable <void (const T &)> &handler)
00119     {
00120         doRegisterHandler <T> (
00121                     new TypeHandler <Callable <void (const T &)> > (handler));
00122     }
00123 
00125     template <typename T>
00126     void registerTypeHandler (const Callable <void (const T &, Sender *)> &handler)
00127     {
00128         doRegisterHandler <T> (new TypeHandlerWithSender
00129                         <Callable <void (const T &, Sender *)> > (handler));
00130     }
00131 
00133     template <typename T>
00134     void unregisterTypeHandler (const Callable <void (const T &)> &handler)
00135     {
00136         doUnregisterHandler <T> (
00137                     new TypeHandler <Callable <void (const T &)> > (handler));
00138     }
00139 
00141     template <typename T>
00142     void unregisterTypeHandler (const Callable <void (const T &, Sender *)> &handler)
00143     {
00144         doUnregisterHandler <T> (new TypeHandlerWithSender
00145                         <Callable <void (const T &, Sender *)> > (handler));
00146     }
00147 
00149     void registerNotHandledHandler (const DispatchBaseHandler &handler)
00150     {
00151         doRegisterNotHandledHandler (
00152                         new TypeHandler <DispatchBaseHandler> (handler));
00153     }
00154 
00156     void registerNotHandledHandler (const DispatchBaseSenderHandler &handler)
00157     {
00158         doRegisterNotHandledHandler (
00159             new TypeHandlerWithSender <DispatchBaseSenderHandler> (handler));
00160     }
00161 
00163 
00177     bool dispatch (const DispatchBase &object, Sender *sender = 0)
00178     {
00179         dispatchToCatchAllHandlers (object, sender);
00180         if (dispatchToTypeHandlers (object, sender))
00181             return true;
00182         dispatchToNotHandledHandlers (object, sender);
00183         return false;
00184     }
00185 
00186 private:
00187     struct Handler; // Declared below.
00188 
00190     void doRegisterCatchAllHandler (Handler *handler)
00191     {
00192         catchAllHandlers.append (handler);
00193     }
00194 
00196     template <typename T>
00197     void doRegisterHandler (Handler *handler)
00198     {
00199         const std::type_info *type = &typeid (T);
00200         handlers.insert (type, handler);
00201     }
00202 
00204     template <typename T>
00205     void doUnregisterHandler (Handler *handler)
00206     {
00207         const std::type_info *type = &typeid (T);
00208         QMultiMap <const std::type_info *, Handler *> newHandlers;
00209         typename QMultiMap <const std::type_info *, Handler *>::iterator it, end;
00210         for (it = handlers.begin(), end = handlers.end(); it != end; ++it)
00211             if (it.key() == type && handler->operator== (*it.value()))
00212                 delete it.value();
00213             else
00214                 newHandlers.insert (it.key(), it.value());
00215         delete handler;
00216         handlers = newHandlers;
00217     }
00218 
00220     void doRegisterNotHandledHandler (Handler *handler)
00221     {
00222         notHandledHandlers.append (handler);
00223     }
00224 
00226     void dispatchToCatchAllHandlers (const DispatchBase &object, Sender *sender)
00227     {
00228         foreach (Handler *handler, catchAllHandlers)
00229             handler->handle (object, sender);
00230     }
00231 
00233 
00240     bool dispatchToTypeHandlers (const DispatchBase &object, Sender *sender)
00241     {
00242         const std::type_info *type = &typeid (object);
00243         QListIterator <Handler *> list (handlers.values (type));
00244         if (!list.hasNext())
00245             return false; // List was empty, we have not dispatched.
00246         list.toBack();
00247         while (list.hasPrevious())
00248             list.previous()->handle (object, sender);
00249         return true; // List was not empty, we dispatched.
00250     }
00251 
00253     void dispatchToNotHandledHandlers (const DispatchBase &object,
00254                                        Sender *sender)
00255     {
00256         foreach (Handler *handler, notHandledHandlers)
00257             handler->handle (object, sender);
00258     }
00259 
00261     struct Handler
00262     {
00263         bool operator == (const Handler &other) const
00264         { return typeid (*this) == typeid (other) && isEqual (other); }
00265 
00266         virtual ~Handler() {}
00267         virtual void handle (const DispatchBase &, Sender *) = 0;
00268         virtual bool isEqual (const Handler &) const = 0;
00269     };
00270 
00271     template <typename Callable>
00272     class TypeHandler : public Handler
00273     {
00274     public:
00275         TypeHandler (const Callable &c)
00276         : callable (c) {}
00277 
00278         void handle (const DispatchBase &packet, Sender *)
00279         { callable (dynamic_cast <typename Callable::ParameterType1>
00280                                                             (packet)); }
00281 
00282         bool isEqual (const Handler &other) const
00283         { return dynamic_cast <const TypeHandler &> (other).callable
00284                     == callable; }
00285 
00286     private:
00287         Callable callable;
00288     };
00289 
00290     template <typename Callable>
00291     class TypeHandlerWithSender : public Handler
00292     {
00293     public:
00294         TypeHandlerWithSender (const Callable &c)
00295         : callable (c) {}
00296 
00297         void handle (const DispatchBase &packet, Sender *sender)
00298         { callable (dynamic_cast <typename Callable::ParameterType1>
00299                                                         (packet), sender); }
00300 
00301         bool isEqual (const Handler &other) const
00302         { return dynamic_cast <const TypeHandlerWithSender &> (other)
00303                     .callable == callable; }
00304 
00305     private:
00306         Callable callable;
00307     };
00308 
00309     QList <Handler *>                               catchAllHandlers;
00310     QMultiMap <const std::type_info *, Handler *>   handlers;
00311     QList <Handler *>                               notHandledHandlers;
00312 };
00313 
00314 } // namespace Utils
00315 
00316 #endif // UTILS__OBJECT_DISPATCHER_H