1- # Copyright 2017, Optimizely
1+ # Copyright 2017-2019 , Optimizely
22# Licensed under the Apache License, Version 2.0 (the "License");
33# you may not use this file except in compliance with the License.
44# You may obtain a copy of the License at
1111# See the License for the specific language governing permissions and
1212# limitations under the License.
1313
14- from functools import reduce
15-
1614from .helpers import enums
15+ from . import logger as optimizely_logger
16+
17+
18+ NOTIFICATION_TYPES = tuple (getattr (enums .NotificationTypes , attr )
19+ for attr in dir (enums .NotificationTypes )
20+ if not attr .startswith ('__' ))
1721
1822
1923class NotificationCenter (object ):
20- """ Class encapsulating Broadcast Notifications. The enums.NotifcationTypes includes predefined notifications."""
24+ """ Class encapsulating methods to manage notifications and their listeners.
25+ The enums.NotificationTypes includes predefined notifications."""
2126
22- def __init__ (self , logger ):
23- self .notification_id = 1
24- self .notifications = {}
25- for ( attr , value ) in enums . NotificationTypes . __dict__ . items () :
26- self .notifications [ value ] = []
27- self .logger = logger
27+ def __init__ (self , logger = None ):
28+ self .listener_id = 1
29+ self .notification_listeners = {}
30+ for notification_type in NOTIFICATION_TYPES :
31+ self .notification_listeners [ notification_type ] = []
32+ self .logger = optimizely_logger . adapt_logger ( logger or optimizely_logger . NoOpLogger ())
2833
2934 def add_notification_listener (self , notification_type , notification_callback ):
30- """ Add a notification callback to the notification center.
35+ """ Add a notification callback to the notification center for a given notification type .
3136
3237 Args:
33- notification_type: A string representing the notification type from . helpers.enums.NotificationTypes
34- notification_callback: closure of function to call when event is triggered.
38+ notification_type: A string representing the notification type from helpers.enums.NotificationTypes
39+ notification_callback: Closure of function to call when event is triggered.
3540
3641 Returns:
37- Integer notification id used to remove the notification or -1 if the notification has already been added.
42+ Integer notification ID used to remove the notification or
43+ -1 if the notification listener has already been added or
44+ if the notification type is invalid.
3845 """
3946
40- if notification_type not in self .notifications :
41- self .notifications [notification_type ] = [(self .notification_id , notification_callback )]
42- else :
43- if reduce (lambda a , b : a + 1 ,
44- filter (lambda tup : tup [1 ] == notification_callback , self .notifications [notification_type ]),
45- 0 ) > 0 :
46- return - 1
47- self .notifications [notification_type ].append ((self .notification_id , notification_callback ))
47+ if notification_type not in NOTIFICATION_TYPES :
48+ self .logger .error ('Invalid notification_type: {} provided. Not adding listener.' .format (notification_type ))
49+ return - 1
4850
49- ret_val = self .notification_id
51+ for _ , listener in self .notification_listeners [notification_type ]:
52+ if listener == notification_callback :
53+ self .logger .error ('Listener has already been added. Not adding it again.' )
54+ return - 1
5055
51- self .notification_id += 1
56+ self .notification_listeners [notification_type ].append ((self .listener_id , notification_callback ))
57+ current_listener_id = self .listener_id
58+ self .listener_id += 1
5259
53- return ret_val
60+ return current_listener_id
5461
5562 def remove_notification_listener (self , notification_id ):
5663 """ Remove a previously added notification callback.
@@ -62,40 +69,61 @@ def remove_notification_listener(self, notification_id):
6269 The function returns boolean true if found and removed, false otherwise.
6370 """
6471
65- for v in self .notifications .values ():
66- toRemove = list (filter (lambda tup : tup [0 ] == notification_id , v ))
67- if len (toRemove ) > 0 :
68- v .remove (toRemove [0 ])
72+ for listener in self .notification_listeners .values ():
73+ listener_to_remove = list (filter (lambda tup : tup [0 ] == notification_id , listener ))
74+ if len (listener_to_remove ) > 0 :
75+ listener .remove (listener_to_remove [0 ])
6976 return True
7077
7178 return False
7279
73- def clear_all_notifications (self ):
74- """ Remove all notifications """
75- for key in self .notifications .keys ():
76- self .notifications [key ] = []
80+ def clear_notification_listeners (self , notification_type ):
81+ """ Remove notification listeners for a certain notification type.
82+
83+ Args:
84+ notification_type: String denoting notification type.
85+ """
86+
87+ if notification_type not in NOTIFICATION_TYPES :
88+ self .logger .error ('Invalid notification_type: {} provided. Not removing any listener.' .format (notification_type ))
89+ self .notification_listeners [notification_type ] = []
7790
7891 def clear_notifications (self , notification_type ):
79- """ Remove notifications for a certain notification type
92+ """ (DEPRECATED since 3.2.0, use clear_notification_listeners)
93+ Remove notification listeners for a certain notification type.
8094
8195 Args:
8296 notification_type: key to the list of notifications .helpers.enums.NotificationTypes
8397 """
98+ self .clear_notification_listeners (notification_type )
8499
85- self .notifications [notification_type ] = []
100+ def clear_all_notification_listeners (self ):
101+ """ Remove all notification listeners. """
102+ for notification_type in self .notification_listeners .keys ():
103+ self .clear_notification_listeners (notification_type )
104+
105+ def clear_all_notifications (self ):
106+ """ (DEPRECATED since 3.2.0, use clear_all_notification_listeners)
107+ Remove all notification listeners. """
108+ self .clear_all_notification_listeners ()
86109
87110 def send_notifications (self , notification_type , * args ):
88111 """ Fires off the notification for the specific event. Uses var args to pass in a
89112 arbitrary list of parameter according to which notification type was fired.
90113
91114 Args:
92115 notification_type: Type of notification to fire (String from .helpers.enums.NotificationTypes)
93- args: variable list of arguments to the callback.
116+ args: Variable list of arguments to the callback.
94117 """
95118
96- if notification_type in self .notifications :
97- for notification_id , callback in self .notifications [notification_type ]:
119+ if notification_type not in NOTIFICATION_TYPES :
120+ self .logger .error ('Invalid notification_type: {} provided. '
121+ 'Not triggering any notification.' .format (notification_type ))
122+ return
123+
124+ if notification_type in self .notification_listeners :
125+ for notification_id , callback in self .notification_listeners [notification_type ]:
98126 try :
99127 callback (* args )
100128 except :
101- self .logger .exception ('Problem calling notify callback!' )
129+ self .logger .exception ('Unknown problem when sending "{}" type notification.' . format ( notification_type ) )
0 commit comments