View Javadoc

1   package eu.scape_project.watch.notification;
2   
3   import java.util.HashMap;
4   import java.util.HashSet;
5   import java.util.Map;
6   import java.util.Set;
7   
8   import eu.scape_project.watch.domain.DataType;
9   import eu.scape_project.watch.domain.Notification;
10  import eu.scape_project.watch.interfaces.NotificationAdaptorInterface;
11  
12  import org.slf4j.Logger;
13  import org.slf4j.LoggerFactory;
14  
15  /**
16   * 
17   * Singleton that allows sending of notifications.
18   * 
19   * @author Luis Faria <lfaria@keep.pt>
20   * 
21   */
22  public final class NotificationService {
23  
24    /**
25     * The singleton instance.
26     */
27    private static NotificationService instance = null;
28  
29    /**
30     * Get the singleton instance.
31     * 
32     * @return The existing instance if exists or a creates a new one.
33     */
34    public static synchronized NotificationService getInstance() {
35      if (instance == null) {
36        instance = new NotificationService();
37      }
38      return instance;
39    }
40  
41    /**
42     * Logger.
43     */
44    private static final Logger LOG = LoggerFactory.getLogger(NotificationService.class);
45  
46    /**
47     * Registered adaptors.
48     */
49    private final Set<NotificationAdaptorInterface> adaptors;
50  
51    /**
52     * Index of adaptors by type.
53     */
54    private final Map<String, Set<NotificationAdaptorInterface>> adaptorsIndex;
55  
56    /**
57     * Private constructor for the singleton.
58     */
59    private NotificationService() {
60      this.adaptors = new HashSet<NotificationAdaptorInterface>();
61      this.adaptorsIndex = new HashMap<String, Set<NotificationAdaptorInterface>>();
62  
63      // TODO load only notification via plugins
64      addAdaptor(new LogNotificationAdaptor());
65    }
66  
67    /**
68     * Add a new notification adaptor and update index.
69     * 
70     * @param adaptor
71     *          The notification adaptor to add.
72     * @return <code>true</code> if did not already contain the specified adaptor
73     */
74    public boolean addAdaptor(final NotificationAdaptorInterface adaptor) {
75      final boolean ret = this.adaptors.add(adaptor);
76  
77      // update index
78      for (final String type : adaptor.getSupportedTypes()) {
79        Set<NotificationAdaptorInterface> typeAdaptors = this.adaptorsIndex.get(type);
80  
81        // add type if this is the first adaptor to support it
82        if (typeAdaptors == null) {
83          typeAdaptors = new HashSet<NotificationAdaptorInterface>();
84          this.adaptorsIndex.put(type, typeAdaptors);
85        }
86  
87        typeAdaptors.add(adaptor);
88      }
89  
90      LOG.debug("Registered " + adaptor);
91  
92      return ret;
93    }
94  
95    /**
96     * Remove an existing adaptor, updating index.
97     * 
98     * @param adaptor
99     *          The adaptor to remove
100    * @return <code>true</code> if contained the specified adaptor
101    */
102   public boolean removeAdaptor(final NotificationAdaptorInterface adaptor) {
103     boolean ret;
104     if (adaptor != null) {
105       ret = this.adaptors.remove(adaptor);
106 
107       // update index
108       for (final String type : adaptor.getSupportedTypes()) {
109         final Set<NotificationAdaptorInterface> typeAdaptors = this.adaptorsIndex.get(type);
110 
111         if (typeAdaptors != null) {
112           typeAdaptors.remove(adaptor);
113 
114           // Remove type if no adaptor supports it
115           if (typeAdaptors.isEmpty()) {
116             this.adaptorsIndex.remove(type);
117           }
118         }
119       }
120 
121       LOG.debug("Unregistered " + adaptor);
122     } else {
123       ret = false;
124     }
125 
126     return ret;
127   }
128 
129   public Set<NotificationAdaptorInterface> getAdaptors() {
130     return this.adaptors;
131   }
132 
133   public Set<String> getTypes() {
134     return this.adaptorsIndex.keySet();
135   }
136 
137   /**
138    * Get all possible parameters for a notification type.
139    * 
140    * @param type
141    *          The notification type.
142    * @return A map will all the parameters.
143    */
144   public Map<String, DataType> getTypeParameters(final String type) {
145     final Map<String, DataType> ret = new HashMap<String, DataType>();
146 
147     final Set<NotificationAdaptorInterface> typeAdaptors = this.adaptorsIndex.get(type);
148     for (final NotificationAdaptorInterface adaptor : typeAdaptors) {
149       final Map<String, DataType> adaptorParam = adaptor.getParametersInfo();
150       ret.putAll(adaptorParam);
151     }
152 
153     return ret;
154   }
155 
156   /**
157    * Send a notification by all adaptors that support the notification type.
158    * 
159    * @param notification
160    *          The notification to send
161    * @return <code>true</code> if notification sent by one or more adaptors
162    */
163   public boolean send(final Notification notification) {
164     boolean ret;
165     final String type = notification.getType();
166 
167     final Set<NotificationAdaptorInterface> typeAdaptors = this.adaptorsIndex.get(type);
168     ret = !typeAdaptors.isEmpty();
169 
170     for (NotificationAdaptorInterface adaptor : typeAdaptors) {
171       final boolean consume = adaptor.send(notification);
172 
173       if (consume) {
174         break;
175       }
176     }
177 
178     return ret;
179   }
180 
181 }