View Javadoc

1   /* This file is part of COPAL (COntext Provisioning for All).
2    *
3    * COPAL is a part of SM4All (Smart hoMes for All) project.
4    *
5    * COPAL is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU Lesser General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * COPAL is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with COPAL. If not, see <http://www.gnu.org/licenses/>.
17   */
18  package at.ac.tuwien.infosys.sm4all.copal.api.event;
19  
20  import java.text.MessageFormat;
21  import org.apache.log4j.Logger;
22  import at.ac.tuwien.infosys.sm4all.copal.api.listener.ContextListener;
23  import at.ac.tuwien.infosys.sm4all.copal.api.publisher.ContextPublisher;
24  import at.ac.tuwien.infosys.sm4all.copal.api.security.Authorization;
25  import at.ac.tuwien.infosys.sm4all.copal.api.security.AuthorizationMethod;
26  import at.ac.tuwien.infosys.sm4all.copal.api.security.Authorizations;
27  import at.ac.tuwien.infosys.sm4all.copal.api.util.Attribute;
28  import at.ac.tuwien.infosys.sm4all.copal.api.util.Attributes;
29  
30  /**
31   * Class which defines type for each {@link ContextEvent}, i.e. each
32   * {@link ContextEvent} must have a corresponding {@link ContextEventType}
33   * associated with it. The name of the {@link ContextEventType} is also the name
34   * of each {@link ContextEvent} associated with this type and is a globally
35   * unique name on which {@link ContextPublisher}s and {@link ContextListener}s
36   * have to agree on and use it to publish and listen on events respectively.
37   * This class is not thread safe.
38   * 
39   * @author sanjin
40   */
41  public class ContextEventType {
42  
43      /**
44       * Default time-to-live of {@link ContextEvent}s.
45       */
46      public static final long TTL_DEFAULT = 60 * 1000; // one minute
47      /**
48       * Minimal priority of {@link ContextEvent}s.
49       */
50      public static final int PRIORITY_MIN = 1;
51      /**
52       * Maximal priority of {@link ContextEvent}s.
53       */
54      public static final int PRIORITY_MAX = 10;
55      /**
56       * Default priority of {@link ContextEvent}s.
57       */
58      public static final int PRIORITY_DEFAULT = 5;
59  
60      private static final Logger LOGGER = Logger.getLogger(ContextEventType.class);
61  
62      private final Actions<DefaultAction> actions = new Actions<DefaultAction>();
63      private final Attributes attributes = new Attributes();
64      private final Authorizations authorizations = new Authorizations();
65      private final String name;
66      private long ttl = TTL_DEFAULT;
67      private int priority = PRIORITY_DEFAULT;
68  
69      /**
70       * Create instance of {@link ContextEventType}. The <code>name</code> must
71       * be globally unique name of the event. TTL and priority are set to
72       * {@link #TTL_DEFAULT} and {@link #PRIORITY_DEFAULT} respectively.
73       * 
74       * @param name the globally unique name of {@link ContextEventType}.
75       * @throws NullPointerException if specified name <code>null</code>.
76       * @throws IllegalArgumentException if specified name is an empty or blank
77       *         string.
78       */
79      public ContextEventType(final String name) {
80          super();
81  
82          if (null == name) {
83              throw new NullPointerException("Name cannot be null.");
84          }
85          if (name.trim().isEmpty()) {
86              throw new IllegalArgumentException(
87                      "Name cannot be an empty or blank string.");
88          }
89  
90          this.name = name;
91  
92          if (LOGGER.isDebugEnabled()) {
93              LOGGER.debug(MessageFormat.format("Created event type ''{0}''.",
94                      this.name));
95          }
96      }
97  
98      /**
99       * Return the globally unique name of this {@link ContextEventType}.
100      * 
101      * @return the globally unique name of this {@link ContextEventType}.
102      */
103     public String getName() {
104         return this.name;
105     }
106 
107     /**
108      * Return the time-to-live in milliseconds of this {@link ContextEventType}.
109      * 
110      * @return the time-to-live in milliseconds of this {@link ContextEventType}
111      *         .
112      */
113     public long getTTL() {
114         return this.ttl;
115     }
116 
117     /**
118      * Set the time-to-live of this {@link ContextEventType}. The specified
119      * value represents time in milliseconds. If specified value is negative
120      * then time-to-live will be set to zero. Value of zero means that
121      * time-to-live is indefinite, i.e. the {@link ContextEvent} never gets old.
122      * 
123      * @param ttl the time-to-live of this {@link ContextEventType}.
124      */
125     public void setTTL(final long ttl) {
126         if (ttl < 0) {
127             this.ttl = 0;
128         } else {
129             this.ttl = ttl;
130         }
131     }
132 
133     /**
134      * Return the priority of this {@link ContextEventType}.
135      * 
136      * @return the priority of this {@link ContextEventType}.
137      */
138     public int getPriority() {
139         return this.priority;
140     }
141 
142     /**
143      * Set the priority of this {@link ContextEventType}. If specified value is
144      * greater than {@link #PRIORITY_MAX} than the priority will be set to
145      * {@link #PRIORITY_MAX}. If specified value is less than
146      * {@link #PRIORITY_MIN} than the priority will be set to
147      * {@link #PRIORITY_MIN}
148      * 
149      * @param priority the priority of this {@link ContextEventType}.
150      */
151     public void setPriority(final int priority) {
152         if (priority >= PRIORITY_MAX) {
153             this.priority = PRIORITY_MAX;
154         } else if (priority <= PRIORITY_MIN) {
155             this.priority = PRIORITY_MIN;
156         } else {
157             this.priority = priority;
158         }
159     }
160 
161     /**
162      * Return the {@link DefaultAction} at specified index.
163      * 
164      * @param index the index of {@link DefaultAction}.
165      * @return the {@link DefaultAction}.
166      */
167     public DefaultAction getAction(final int index) {
168         return this.actions.get(index);
169     }
170 
171     /**
172      * Return all currently added {@link DefaultAction}s.
173      * 
174      * @return all currently added {@link DefaultAction}s.
175      */
176     public DefaultAction[] getActions() {
177         @SuppressWarnings("hiding")
178         final ContextEventAction[] actions = this.actions.getAll();
179         final DefaultAction[] result = new DefaultAction[actions.length];
180 
181         System.arraycopy(actions, 0, result, 0, result.length);
182 
183         return result;
184     }
185 
186     /**
187      * Remove all previously added {@link DefaultAction}s and adds specified
188      * {@link DefaultAction}s.
189      * 
190      * @param actions the {@link DefaultAction}s.
191      */
192     protected void set(final DefaultAction... actions) {
193         this.actions.setAll(actions);
194     }
195 
196     /**
197      * Return if there is at least one {@link DefaultAction} with specified
198      * name.
199      * 
200      * @param name the name of the {@link DefaultAction}.
201      * @return if there is at least one {@link DefaultAction} with specified
202      *         name.
203      */
204     public boolean hasAction(@SuppressWarnings("hiding") final String name) {
205         return this.actions.contains(name);
206     }
207 
208     /**
209      * Return the number of {@link DefaultAction}s.
210      * 
211      * @return the number of {@link DefaultAction}s.
212      */
213     public int getNumberOfActions() {
214         return this.actions.size();
215     }
216 
217     /**
218      * Append specified {@link DefaultAction}s.
219      * 
220      * @param defaultActions the {@link DefaultAction}s.
221      */
222     public void append(final DefaultAction... defaultActions) {
223         this.actions.append(defaultActions);
224     }
225 
226     /**
227      * Insert specified {@link DefaultAction} at specified index.
228      * 
229      * @param index the index at which the {@link DefaultAction} is inserted.
230      * @param action the {@link DefaultAction}.
231      */
232     public void insert(final int index, final DefaultAction action) {
233         this.actions.insert(index, action);
234     }
235 
236     /**
237      * Replace the {@link DefaultAction} at specified index with specified
238      * {@link DefaultAction}.
239      * 
240      * @param index the index at which the {@link DefaultAction} is replaced.
241      * @param action the {@link DefaultAction}.=
242      */
243     public void replace(final int index, final DefaultAction action) {
244         this.actions.set(index, action);
245     }
246 
247     /**
248      * Remove the {@link DefaultAction} at specified index.
249      * 
250      * @param index the index at which the {@link DefaultAction} is removed.
251      */
252     public void removeAction(final int index) {
253         this.actions.remove(index);
254     }
255 
256     /**
257      * Add specified {@link Attribute} into this {@link ContextEventType}. If
258      * there is already an {@link Attribute} with same name as specified
259      * {@link Attribute}, specified {@link Attribute} will overwrite
260      * {@link Attribute} that is already added.
261      * 
262      * @param attribute the {@link Attribute}.
263      */
264     public void add(final Attribute attribute) {
265         this.attributes.register(attribute);
266     }
267 
268     /**
269      * Remove an {@link Attribute} that has specified from this
270      * {@link ContextEventType}.
271      * 
272      * @param name the name of {@link Attribute}.
273      */
274     public void removeAttribute(@SuppressWarnings("hiding") final String name) {
275         this.attributes.unregister(name);
276     }
277 
278     /**
279      * Return the value of {@link ContextEventType} {@link Attribute} that has
280      * specified name. If this {@link ContextEventType} does not have
281      * {@link Attribute} with specified name, <code>null</code> will be
282      * returned.
283      * 
284      * @param name the name of the {@link Attribute}.
285      * @return the value of {@link Attribute} or <code>null</code> if there is
286      *         no such {@link Attribute}.
287      */
288     public String getAttribute(@SuppressWarnings("hiding") final String name) {
289         String result = null;
290 
291         final Attribute attribute = this.attributes.get(name);
292         if (null != attribute) {
293             result = attribute.getValue();
294         }
295 
296         return result;
297     }
298 
299     /**
300      * Return all currently added {@link Attribute}s.
301      * 
302      * @return all currently added {@link Attribute}s.
303      */
304     public Attribute[] getAttributes() {
305         return this.attributes.getAll();
306     }
307 
308     /**
309      * Return if an {@link Attribute} that has specified name is currently
310      * present in this {@link ContextEventType}. If the {@link Attribute} was
311      * never added (or was added and consequently removed by adding it with
312      * <code>null</code> value), <code>false</code> will be returned; otherwise
313      * <code>true</code> will be returned.
314      * 
315      * @param name the name of {@link Attribute}.
316      * @return if an {@link Attribute} that has specified name is currently
317      *         present in this {@link ContextEventType}.
318      */
319     public boolean hasAttribute(@SuppressWarnings("hiding") final String name) {
320         return this.attributes.isRegistered(name);
321     }
322 
323     /**
324      * Add specified {@link Attribute}s and remove all previously registered
325      * {@link Attribute}s.
326      * 
327      * @param attributes {@link Attribute}s.
328      */
329     protected void set(final Attribute... attributes) {
330         this.attributes.setAll(attributes);
331     }
332 
333     /**
334      * Add specified {@link Authorization} into this {@link ContextEventType}.
335      * If there is already an {@link Authorization} with same name of the
336      * {@link AuthorizationMethod} as specified {@link Authorization}, their
337      * attributes will be merged with attributes from specified
338      * {@link Authorization} overwriting ones in already added
339      * {@link Authorization}.
340      * 
341      * @param authorization the {@link Authorization}.
342      */
343     public void add(final Authorization authorization) {
344         this.authorizations.register(authorization);
345     }
346 
347     /**
348      * Remove an {@link Authorization} that has specified name of
349      * {@link AuthorizationMethod} from this {@link ContextEventType}.
350      * 
351      * @param method the name of {@link AuthorizationMethod}.
352      */
353     public void removeAuthorization(final String method) {
354         this.authorizations.unregister(method);
355     }
356 
357     /**
358      * Return the {@link Authorization} that has specified name of
359      * {@link AuthorizationMethod}. If this {@link ContextEventType} does not
360      * have {@link Authorization} with specified name
361      * {@link AuthorizationMethod}, <code>null</code> will be returned.
362      * 
363      * @param method the name of {@link AuthorizationMethod}.
364      * @return the {@link Authorization}; or <code>null</code> if there is no
365      *         such {@link Authorization}.
366      */
367     public Authorization getAuthorization(final String method) {
368         return this.authorizations.get(method);
369     }
370 
371     /**
372      * Return all currently added {@link Authorization}s.
373      * 
374      * @return all currently added {@link Authorization}s.
375      */
376     public Authorization[] getAuthorizations() {
377         return this.authorizations.getAll();
378     }
379 
380     /**
381      * Return if an {@link Authorization} that has specified name of
382      * {@link AuthorizationMethod} is currently present in this
383      * {@link ContextEventType}. If the {@link Authorization} was never added
384      * (or was added and consequently removed), <code>false</code> will be
385      * returned; otherwise <code>true</code> will be returned.
386      * 
387      * @param method the name of {@link AuthorizationMethod}.
388      * @return if an {@link Authorization} that has specified name of
389      *         {@link AuthorizationMethod} is currently present in this
390      *         {@link ContextEventType}.
391      */
392     public boolean hasAuthorization(final String method) {
393         return this.authorizations.isRegistered(method);
394     }
395 
396     /**
397      * Return if there is any added {@link Authorization} in this
398      * {@link ContextEventType}.
399      * 
400      * @return if there is any added {@link Authorization} in this
401      *         {@link ContextEventType}.
402      */
403     public boolean hasAuthorizations() {
404         return this.authorizations.getAll().length > 0;
405     }
406 
407     /**
408      * Add specified {@link Authorization}s and remove all previously registered
409      * {@link Authorization}s.
410      * 
411      * @param authorizations {@link Authorization}s.
412      */
413     protected void set(final Authorization... authorizations) {
414         this.authorizations.setAll(authorizations);
415     }
416 
417     /**
418      * Return hash code for this {@link ContextEventType}. The hash code for a
419      * {@link ContextEventType} object is hash code of its name.
420      * 
421      * @return a hash code value for this {@link ContextEventType}.
422      */
423     @Override
424     public int hashCode() {
425         return this.name.hashCode();
426     }
427 
428     /**
429      * Compare this {@link ContextEventType} to the specified {@link Object}.
430      * The result is <code>true</code> if and only if the argument is not
431      * <code>null</code> and is a {@link ContextEventType} object that has same
432      * name as this {@link ContextEventType}.
433      * 
434      * @param obj the {@link Object} to compare this {@link ContextEventType}
435      *        against.
436      * @return <code>true</code> if {@link ContextEventType}s are equal;
437      *         <code>false</code> otherwise.
438      */
439     @Override
440     public boolean equals(final Object obj) {
441         boolean result = false;
442 
443         if (null != obj) {
444             if (this == obj) {
445                 result = true;
446             } else if (obj instanceof ContextEventType) {
447                 final ContextEventType other = (ContextEventType) obj;
448 
449                 result = this.name.equals(other.name);
450             }
451         }
452 
453         return result;
454     }
455 }