ObjectDispatcher.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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;
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;
00246 list.toBack();
00247 while (list.hasPrevious())
00248 list.previous()->handle (object, sender);
00249 return true;
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 }
00315
00316 #endif // UTILS__OBJECT_DISPATCHER_H