Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/modules/notifications/NotificationManager.cc @ 7319

Last change on this file since 7319 was 7207, checked in by landauf, 14 years ago

moved ScopedSingletonManager to util

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @brief Implementation of the NotificationManager class.
32*/
33
34#include "NotificationManager.h"
35
36#include <set>
37
38#include "util/ScopedSingletonManager.h"
39#include "core/CoreIncludes.h"
40#include "Notification.h"
41#include "interfaces/NotificationListener.h"
42
43namespace orxonox
44{
45
46    const std::string NotificationManager::ALL("all");
47    const std::string NotificationManager::NONE("none");
48
49    ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
50
51    /**
52    @brief
53        Constructor. Registers the Object.
54    */
55    NotificationManager::NotificationManager()
56    {
57        RegisterRootObject(NotificationManager);
58
59        this->highestIndex_ = 0;
60    }
61
62    /**
63    @brief
64        Destructor.
65    */
66    NotificationManager::~NotificationManager()
67    {
68
69    }
70
71    /**
72    @brief
73        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationListeners associated with its sender.
74    @param notification
75        The Notification to be registered.
76    @return
77        Returns true if successful.
78    */
79    bool NotificationManager::registerNotification(Notification* notification)
80    {
81
82        if(notification == NULL) //!< A NULL-Notification cannot be registered.
83            return false;
84
85        std::time_t time = std::time(0); //TODO: Doesn't this expire? //!< Get current time.
86
87        this->allNotificationsList_.insert(std::pair<std::time_t,Notification*>(time,notification));
88
89        if(notification->getSender() == NONE) //!< If the sender has no specific name, then the Notification is only added to the list of all Notifications.
90            return true;
91
92        bool all = false;
93        if(notification->getSender() == ALL) //!< If all are the sender, then the Notifications is added to every NotificationListener.
94            all = true;
95
96        //!< Insert the notification in all listeners that have its sender as target.
97        for(std::map<NotificationListener*,int>::iterator it = this->listenerList_.begin(); it != this->listenerList_.end(); it++) //!< Iterate through all listeners.
98        {
99            std::set<std::string> set = it->first->getTargetsSet();
100            if(all || set.find(notification->getSender()) != set.end() || set.find(ALL) != set.end()) //TODO: Make sure this works.
101            {
102                this->notificationLists_[it->second]->insert(std::pair<std::time_t,Notification*>(time,notification)); //!< Insert the Notification in the Notifications list of the current NotificationListener.
103                it->first->update(notification, time); //!< Update the listener.
104                std::map<Notification*, unsigned int>::iterator counterIt = this->listenerCounter_.find(notification);
105                if(counterIt == this->listenerCounter_.end())
106                    this->listenerCounter_[notification] = 1;
107                else
108                    this->listenerCounter_[notification] = counterIt->second + 1;
109            }
110        }
111
112        COUT(4) << "Notification registered with the NotificationManager." << std::endl;
113
114        return true;
115    }
116
117    /**
118    @brief
119        Unregisters a Notification within the NotificationManager.
120    @param notification
121        A pointer to the Notification to be unregistered.
122    @param listener
123        A pointer to the NotificationListener the Notification is unregistered for.
124    */
125    void NotificationManager::unregisterNotification(Notification* notification, NotificationListener* listener)
126    {
127        assert(notification);
128        assert(listener);
129
130        // If the Notification was removed from the list of Notifications of the input NotificationListener, the counter for the Notification of the number of NotificationListeners it is present in is decremented.
131        if(this->removeNotification(notification, *(this->notificationLists_.find(this->listenerList_.find(listener)->second)->second)))
132            this->listenerCounter_[notification] = this->listenerCounter_[notification] - 1;
133
134        // If the Notification is no longer present in any of the NotificationListeners it can be removed from the map of all Notifications and be destroyed.
135        if(this->listenerCounter_[notification] == (unsigned int) 0)
136        {
137            this->removeNotification(notification, this->allNotificationsList_);
138            this->listenerCounter_.erase(notification);
139            notification->destroy();
140        }
141
142        COUT(4) << "Notification unregistered with the NotificationManager." << std::endl;
143    }
144
145    /**
146    @brief
147        Helper method that removes an input notification form an input map.
148    @param notification
149        A pointer to the notification to be removed.
150    @param map
151        The map the notification should be removed from.
152    @return
153        Returns true if successful.
154    */
155    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
156    {
157        // Iterates through all items in the map until the Notification is found.
158        //TODO: Do more efficiently?
159        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
160        {
161            if(it->second == notification)
162            {
163                map.erase(it);
164                return true;
165            }
166        }
167        return false;
168    }
169
170    /**
171    @brief
172        Registers a NotificationListener within the NotificationManager.
173    @param listener
174        The NotificationListener to be registered.
175    @return
176        Returns true if successful.
177    */
178    bool NotificationManager::registerListener(NotificationListener* listener)
179    {
180        this->highestIndex_ += 1;
181        int index = this->highestIndex_;
182
183        this->listenerList_[listener] = index; //!< Add the NotificationListener to the list of listeners.
184
185        std::set<std::string> set = listener->getTargetsSet(); //TODO: Does this work?
186
187        //! If all senders are the target of the listener, then the list of notification for that specific listener is te same as the list of all Notifications.
188        if(set.find(ALL) != set.end())
189        {
190            this->notificationLists_[index] = &this->allNotificationsList_;
191            COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
192            return true;
193        }
194
195        this->notificationLists_[index] = new std::multimap<std::time_t,Notification*>;
196        std::multimap<std::time_t,Notification*> map = *this->notificationLists_[index];
197
198        //! Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationListener.
199        for(std::multimap<std::time_t,Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
200        {
201            if(set.find(it->second->getSender()) != set.end()) //!< Checks whether the overlay has the sender of the current notification as target.
202            {
203                map.insert(std::pair<std::time_t, Notification*>(it->first, it->second));
204                std::map<Notification*, unsigned int>::iterator counterIt = this->listenerCounter_.find(it->second);
205                if(counterIt == this->listenerCounter_.end())
206                    this->listenerCounter_[it->second] = 1;
207                else
208                    this->listenerCounter_[it->second] = counterIt->second + 1;
209            }
210        }
211
212        listener->update(); //!< Update the listener.
213
214        COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
215
216        return true;
217    }
218
219    /**
220    @brief
221        Unregisters a NotificationListener withing the NotificationManager.
222    */
223    void NotificationManager::unregisterListener(NotificationListener* listener)
224    {
225        assert(listener);
226
227        int identifier = this->listenerList_.find(listener)->second;
228        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(identifier)->second;
229
230        // Make sure all Notifications are removed.
231        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
232        while(it != map->end())
233        {
234            this->unregisterNotification(it->second, listener);
235            it = map->begin();
236        }
237
238        this->listenerList_.erase(listener);
239        this->notificationLists_.erase(identifier);
240
241        // If the map is not the map of all notifications, delete it.
242        if(map != &this->allNotificationsList_)
243            delete map;
244
245        COUT(4) << "NotificationListener unregistered with the NotificationManager." << std::endl;
246    }
247
248    /**
249    @brief
250        Fetches the Notifications for a specific NotificationListener in a specified timeframe.
251    @param listener
252        The NotificationListener the Notifications are fetched for.
253    @param map
254        A multimap, in which the notifications are stored.
255    @param timeFrameStart
256        The start time of the timeframe.
257    @param timeFrameEnd
258        The end time of the timeframe.
259    @return
260        Returns true if successful.
261    */
262    bool NotificationManager::getNotifications(NotificationListener* listener, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
263    {
264        if(listener == NULL || map == NULL)
265            return false;
266
267        std::multimap<std::time_t,Notification*>* notifications = this->notificationLists_[this->listenerList_[listener]]; //!< The Notifications for the input NotificationListener.
268
269        if(notifications == NULL) //!< Returns NULL, if there are no Notifications.
270            return true;
271
272        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
273        itLowest = notifications->lower_bound(timeFrameStart);
274        itHighest = notifications->upper_bound(timeFrameStart);
275
276        for(it = itLowest; it != itHighest; it++) //!< Iterate through the Notifications from the start of the time Frame to the end of it.
277        {
278            map->insert(std::pair<std::time_t,Notification*>(it->first,it->second)); //!< Add the found Notifications to the map.
279        }
280
281        return true;
282    }
283
284}
Note: See TracBrowser for help on using the repository browser.