f4c893caf235f918b6331bf88ea0e0c6d32a8a59
[framework/web/wrt-commons.git] / modules / event / include / dpl / event / event_delivery.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        event_delivery.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the header file of event delivery class
21  */
22 #ifndef DPL_EVENT_DELIVERY_H
23 #define DPL_EVENT_DELIVERY_H
24
25 #include <dpl/event/event_delivery_detail.h>
26 #include <dpl/event/event_delivery_messages.h>
27 #include <dpl/event/event_support.h>
28 #include <dpl/noncopyable.h>
29 #include <dpl/shared_ptr.h>
30 #include <dpl/exception.h>
31 #include <dpl/assert.h>
32 #include <dpl/foreach.h>
33 #include <list>
34 #include <map>
35 #include <typeinfo>
36 #include <string>
37
38 /*
39  * Event delivery system
40  *
41  * Sample usages:
42  *
43  * I. Listening for standard predefined notifications
44  *
45  *   class MyClass
46  *       : public EventListener<EventMessages::RoamingChanged>
47  *   {
48  *       void OnEventReceived(const EventMessages::RoamingChanged& event)
49  *       {
50  *           std::cout << "Roaming is now " << event.GetRoamingEnabled() ? "ENABLED" : "DISABLED" << std::endl;
51  *       }
52  *
53  *   public:
54  *       MyClass()
55  *       {
56  *           EventDeliverySystem::AddListener<EventMessages::RoamingChanged>(this);
57  *       }
58  *
59  *       virtual ~MyClass()
60  *       {
61  *           EventDeliverySystem::RemoveListener<EventMessages::RoamingChanged>(this);
62  *       }
63  *
64  *       void SendSampleSignal()
65  *       {
66  *           EventMessages::RoamingChanged roamingMessage(true);
67  *           EventDeliverySystem::Publish(roamingMessage);
68  *       }
69  *   }
70  *
71  *  II. Creation of custom generic events, and listening for them
72  *
73  *   EVENT_DELIVERY_DECLARE_EVENT_MESSAGE_2(MyEvent, int, float);
74  *
75  *   class MyClass
76  *       : public EventListener<MyEvent>
77  *   {
78  *       void OnEventReceived(const MyEvent &event)
79  *       {
80  *           std::cout << "Event contents: " << event.GetArg0() << ", " << event.GetArg1() << std::endl;
81  *       }
82  *
83  *   public:
84  *       MyClass()
85  *       {
86  *           EventDeliverySystem::AddListener<MyEvent>(this);
87  *       }
88  *
89  *       virtual ~MyClass()
90  *       {
91  *           EventDeliverySystem::RemoveListener<MyEvent>(this);
92  *       }
93  *
94  *       void SendSampleSignal()
95  *       {
96  *           MyEvent myEvent(5, 3.14f);
97  *           EventDeliverySystem::Publish(myEvent);
98  *       }
99  *   }
100  *
101  *  In source file, one must add implementation of event delivery message:
102  *
103  *  EVENT_DELIVERY_IMPLEMENT_EVENT_MESSAGE(MyEvent)
104  *
105  */
106 namespace DPL
107 {
108 namespace Event
109 {
110
111 class AbstractEventDeliverySystemPublisher
112 {
113 public:
114     virtual ~AbstractEventDeliverySystemPublisher() = 0;
115 };
116
117 template<typename EventType>
118 class EventDeliverySystemPublisher
119     : private EventSupport<EventType>
120     , public AbstractEventDeliverySystemPublisher
121 {
122 public:
123     typedef typename EventSupport<EventType>::EventListenerType EventListenerType;
124
125 private:
126     friend class EventDeliverySystem;
127
128     EventDeliverySystemPublisher(EventListenerType *eventListener)
129         : m_eventListener(eventListener)
130     {
131         EventSupport<EventType>::AddListener(m_eventListener);
132     }
133
134     EventListenerType *m_eventListener;
135
136 public:
137     ~EventDeliverySystemPublisher()
138     {
139         EventSupport<EventType>::RemoveListener(m_eventListener);
140     }
141
142     void PublishEvent(const EventType &event)
143     {
144         EmitEvent(event, EmitMode::Queued);
145     }
146
147     EventListenerType *GetListener() const
148     {
149         return m_eventListener;
150     }
151 };
152
153 template<typename Type>
154 class EventDeliverySystemTraits
155 {
156 public:
157     typedef Type EventType;
158     typedef EventDeliverySystemPublisher<EventType> PublisherType;
159     typedef typename PublisherType::EventListenerType EventListenerType;
160     typedef SharedPtr<PublisherType> PublisherPtrType;
161     typedef std::list<PublisherPtrType> PublisherPtrContainerType;
162 };
163
164 class EventDeliverySystem
165     : private Noncopyable
166 {
167 private:
168     typedef SharedPtr<AbstractEventDeliverySystemPublisher> AbstractPublisherPtrType;
169     typedef std::list<AbstractPublisherPtrType> AbstractPublisherPtrContainerType;
170     typedef AbstractPublisherPtrContainerType::const_iterator AbstractPublisherPtrContainerTypeConstIterator;
171     typedef AbstractPublisherPtrContainerType::iterator AbstractPublisherPtrContainerTypeIterator;
172     typedef std::map<std::string, AbstractPublisherPtrContainerType> AbstractPublisherPtrContainerMapType;
173
174     template<class EventType>
175     class CrtDeleteCheck
176     {
177     private:
178         const AbstractPublisherPtrContainerType &m_publisherContainer;
179
180     public:
181         CrtDeleteCheck(const AbstractPublisherPtrContainerType &publisherContainer)
182             : m_publisherContainer(publisherContainer)
183         {
184         }
185
186         virtual ~CrtDeleteCheck()
187         {
188             Assert(m_publisherContainer.empty() && "All event delivery listeners must be removed before exit!");
189         }
190     };
191
192     // Map containing publishers for all registered events
193     static AbstractPublisherPtrContainerMapType m_publishers;
194
195     // Detail implementation: lazy initialized
196     static EventDeliverySystemDetail m_detailSystem;
197
198     EventDeliverySystem()
199     {
200     }
201
202     template<typename EventType>
203     static AbstractPublisherPtrContainerType &GetPublisherContainerRef()
204     {
205         std::string typeId = typeid(EventType).name();
206
207         //FIXME: problem with linking per compilation unit won't hurt this check?
208         static CrtDeleteCheck<EventType> crtDeleteCheck(m_publishers[typeId]);
209         (void)crtDeleteCheck;
210
211         return m_publishers[typeId];
212     }
213
214     template<typename EventType>
215     static typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType GetPublisherContainer()
216     {
217         std::string typeId = typeid(EventType).name();
218         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherContainerType;
219         typedef typename EventDeliverySystemTraits<EventType>::PublisherType PublisherType;
220         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
221
222         AbstractPublisherPtrContainerType eventPublishers = m_publishers[typeId];
223         PublisherContainerType publisherContainer;
224
225         FOREACH(iterator, eventPublishers)
226         {
227             PublisherPtrType publisher =
228                     StaticPointerCast<PublisherType>(*iterator);
229             publisherContainer.push_back(publisher);
230         }
231
232         return publisherContainer;
233     }
234
235     // Detail access
236     template<typename EventType>
237     static void Inject(const EventType &event)
238     {
239         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherContainerType;
240         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
241
242         PublisherContainerType publisherContainer = GetPublisherContainer<EventType>();
243         typename PublisherContainerType::iterator iterator;
244
245         for (iterator = publisherContainer.begin(); iterator != publisherContainer.end(); ++iterator)
246         {
247             PublisherPtrType &publisher = *iterator;
248             publisher->PublishEvent(event);
249         }
250     }
251
252     template<typename EventType>
253     class PublisherPtrContainerListenerPredicate
254     {
255     public:
256         typedef EventListener<EventType> EventListenerType;
257
258     private:
259         EventListenerType *m_listener;
260
261     public:
262         PublisherPtrContainerListenerPredicate(EventListenerType *listener)
263             : m_listener(listener)
264         {
265         }
266
267         bool operator()(const AbstractPublisherPtrType &publisher) const
268         {
269             return StaticPointerCast<typename EventDeliverySystemTraits<EventType>::PublisherType>(publisher)->GetListener() == m_listener;
270         }
271     };
272
273     friend class EventDeliverySystemInjector;
274
275 public:
276     virtual ~EventDeliverySystem()
277     {
278     }
279
280     template<typename EventType>
281     static void AddListener(EventListener<EventType> *listener)
282     {
283         typedef typename EventDeliverySystemTraits<EventType>::PublisherType PublisherType;
284         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
285         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherPtrContainerType;
286
287         typedef PublisherPtrContainerListenerPredicate<EventType> PublisherPtrContainerListenerPredicateType;
288
289         AbstractPublisherPtrContainerType &publisherContainer = GetPublisherContainerRef<EventType>();
290         AbstractPublisherPtrContainerTypeConstIterator iterator =
291                 std::find_if(publisherContainer.begin(), publisherContainer.end(), PublisherPtrContainerListenerPredicateType(listener));
292
293         Assert(iterator == publisherContainer.end() && "Listener already exists");
294
295         // Add new publisher
296         publisherContainer.push_back(AbstractPublisherPtrType(new PublisherType(listener)));
297
298         // When first listener is inserted, start to listen for events
299         if (publisherContainer.size() == 1) {
300             m_detailSystem.Listen(EventType());
301         }
302     }
303
304     template<typename EventType>
305     static void RemoveListener(EventListener<EventType> *listener)
306     {
307         typedef typename EventDeliverySystemTraits<EventType>::PublisherType PublisherType;
308         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrType PublisherPtrType;
309         typedef typename EventDeliverySystemTraits<EventType>::PublisherPtrContainerType PublisherPtrContainerType;
310
311         typedef PublisherPtrContainerListenerPredicate<EventType> PublisherPtrContainerListenerPredicateType;
312
313         AbstractPublisherPtrContainerType &publisherContainer = GetPublisherContainerRef<EventType>();
314
315         AbstractPublisherPtrContainerTypeIterator iterator =
316                 std::find_if(publisherContainer.begin(), publisherContainer.end(), PublisherPtrContainerListenerPredicateType(listener));
317
318         Assert(iterator != publisherContainer.end() && "Listener does not exist");
319
320         // Remove publisher
321         publisherContainer.erase(iterator);
322
323         // When last listener was removed, stop to listen for events
324         if (publisherContainer.empty())
325             m_detailSystem.Unlisten(EventType());
326     }
327
328     template<typename EventType>
329     static void Publish(const EventType &event)
330     {
331         m_detailSystem.Publish(event);
332     }
333 };
334
335 }
336 } // namespace DPL
337
338 #endif // DPL_EVENT_DELIVERY_H