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.util.Date;
21  import java.util.LinkedList;
22  import java.util.List;
23  import at.ac.tuwien.infosys.sm4all.copal.api.security.Authorization;
24  import at.ac.tuwien.infosys.sm4all.copal.api.security.AuthorizationMethod;
25  import at.ac.tuwien.infosys.sm4all.copal.api.security.Authorizations;
26  import at.ac.tuwien.infosys.sm4all.copal.api.util.Attribute;
27  import at.ac.tuwien.infosys.sm4all.copal.api.util.Attributes;
28  
29  /**
30   * Class which contains meta-data for all context events. This class is not
31   * thread safe.
32   * 
33   * @author fei
34   * @author sanjin
35   */
36  public class ContextEvent extends BaseEvent {
37  
38      private final Attributes attributes;
39      private final Authorizations authorizations;
40      private final ContextEventType type;
41      private long ttl;
42      private int priority;
43  
44      /**
45       * Create instance of {@link ContextEvent} with specified
46       * {@link ContextEventType}, source ID, and time stamp. TTL and priority are
47       * set to specified {@link ContextEventType} time-to-live and priority
48       * respectively.
49       * 
50       * @param type the {@link ContextEventType}.
51       * @param sourceID the source ID of the {@link ContextEvent}.
52       * @param timeStamp the time stamp for the {@link ContextEvent}.
53       * @throws NullPointerException if specified type, source ID or time stamp
54       *         is <code>null</code>.
55       * @throws IllegalArgumentException if specified source ID is an empty or
56       *         blank string.
57       */
58      protected ContextEvent(final ContextEventType type, final String sourceID,
59              final Date timeStamp) {
60          super(sourceID, timeStamp);
61  
62          if (null == type) {
63              throw new NullPointerException("Type cannot be null.");
64          }
65  
66          this.type = type;
67          this.ttl = type.getTTL();
68          this.priority = type.getPriority();
69          this.attributes = new Attributes(type.getAttributes());
70          this.authorizations = new Authorizations(type.getAuthorizations());
71          final List<UnprocessedAction> actions = new LinkedList<UnprocessedAction>();
72          for (final DefaultAction action : type.getActions()) {
73              actions.add(new UnprocessedAction(action));
74          }
75          append(actions.toArray(new UnprocessedAction[actions.size()]));
76      }
77  
78      /**
79       * Returns the {@link ContextEventType} associated with this
80       * {@link ContextEvent}.
81       * 
82       * @return the {@link ContextEventType} associated with this
83       *         {@link ContextEvent}.
84       */
85      public ContextEventType getType() {
86          return this.type;
87      }
88  
89      /**
90       * Returns the time-to-live in milliseconds of this {@link ContextEventType}
91       * .
92       * 
93       * @return the time-to-live in milliseconds of this {@link ContextEventType}
94       *         .
95       */
96      public long getTTL() {
97          return this.ttl;
98      }
99  
100     /**
101      * Sets the time-to-live of this {@link ContextEventType}. The specified
102      * value represents time in milliseconds. If specified value is negative
103      * then time-to-live will be set to zero. Value of zero means that
104      * time-to-live is indefinite, i.e. the {@link ContextEvent} never gets old.
105      * 
106      * @param ttl the time-to-live of this {@link ContextEventType}.
107      */
108     public void setTTL(final long ttl) {
109         if (ttl < 0) {
110             this.ttl = 0;
111         } else {
112             this.ttl = ttl;
113         }
114     }
115 
116     /**
117      * Returns if this {@link ContextEvent} is stale (i.e. time-stamp +
118      * time-to-live < current time).
119      * 
120      * @return if this {@link ContextEvent} is stale.
121      */
122     public boolean isStale() {
123         final Date maxCreationTime = new Date(System.currentTimeMillis()
124                 - this.ttl);
125         return maxCreationTime.after(getTimeStamp());
126 
127     }
128 
129     /**
130      * Returns the priority of this {@link ContextEventType}.
131      * 
132      * @return the priority of this {@link ContextEventType}.
133      */
134     public int getPriority() {
135         return this.priority;
136     }
137 
138     /**
139      * Sets the priority of this {@link ContextEventType}. If specified value is
140      * greater than {@link ContextEventType#PRIORITY_MAX} than the priority will
141      * be set to {@link ContextEventType#PRIORITY_MAX}. If specified value is
142      * less than {@link ContextEventType#PRIORITY_MIN} than the priority will be
143      * set to {@link ContextEventType#PRIORITY_MIN}
144      * 
145      * @param priority the priority of this {@link ContextEventType}.
146      */
147     public void setPriority(final int priority) {
148         if (priority >= ContextEventType.PRIORITY_MAX) {
149             this.priority = ContextEventType.PRIORITY_MAX;
150         } else if (priority <= ContextEventType.PRIORITY_MIN) {
151             this.priority = ContextEventType.PRIORITY_MIN;
152         } else {
153             this.priority = priority;
154         }
155     }
156 
157     /**
158      * Add specified {@link Attribute} into this {@link ContextEvent}. If there
159      * is already an {@link Attribute} with same name as specified
160      * {@link Attribute}, specified {@link Attribute} will overwrite
161      * {@link Attribute} that is already added.
162      * 
163      * @param attribute the {@link Attribute}.
164      */
165     public void add(final Attribute attribute) {
166         this.attributes.register(attribute);
167     }
168 
169     /**
170      * Remove an {@link Attribute} that has specified from this
171      * {@link ContextEvent}.
172      * 
173      * @param name the name of {@link Attribute}.
174      */
175     public void removeAttribute(final String name) {
176         this.attributes.unregister(name);
177     }
178 
179     /**
180      * Returns the value of {@link ContextEvent} {@link Attribute} that has
181      * specified name. If this {@link ContextEventType} does not have
182      * {@link Attribute} with specified name, <code>null</code> will be
183      * returned.
184      * 
185      * @param name the name of the {@link Attribute}.
186      * @return the value of {@link Attribute} or <code>null</code> if there is
187      *         no such {@link Attribute}.
188      */
189     public String getAttribute(final String name) {
190         String result = null;
191 
192         final Attribute attribute = this.attributes.get(name);
193         if (null != attribute) {
194             result = attribute.getValue();
195         }
196 
197         return result;
198     }
199 
200     /**
201      * Returns all currently added {@link Attribute}s.
202      * 
203      * @return all currently added {@link Attribute}s.
204      */
205     public Attribute[] getAttributes() {
206         return this.attributes.getAll();
207     }
208 
209     /**
210      * Returns if an {@link Attribute} that has specified name is currently
211      * present in this {@link ContextEvent}. If the {@link Attribute} was never
212      * added (or was added and consequently removed by adding it with
213      * <code>null</code> value), <code>false</code> will be returned; otherwise
214      * <code>true</code> will be returned.
215      * 
216      * @param name the name of {@link Attribute}.
217      * @return if an {@link Attribute} that has specified name is currently
218      *         present in this {@link ContextEvent}.
219      */
220     public boolean hasAttribute(final String name) {
221         return this.attributes.isRegistered(name);
222     }
223 
224     /**
225      * Add specified {@link Attribute}s and remove all previously registered
226      * {@link Attribute}s.
227      * 
228      * @param attributes {@link Attribute}s.
229      */
230     protected void set(final Attribute... attributes) {
231         this.attributes.setAll(attributes);
232     }
233 
234     /**
235      * Adds specified {@link Authorization} into this {@link ContextEvent}. If
236      * there is already an {@link Authorization} with same name of the
237      * {@link AuthorizationMethod} as specified {@link Authorization}, their
238      * attributes will be merged with attributes from specified
239      * {@link Authorization} overwriting ones in already added
240      * {@link Authorization}.
241      * 
242      * @param authorization the {@link Authorization}.
243      */
244     public void add(final Authorization authorization) {
245         this.authorizations.register(authorization);
246     }
247 
248     /**
249      * Removes an {@link Authorization} that has specified name of
250      * {@link AuthorizationMethod} from this {@link ContextEvent}.
251      * 
252      * @param method the name of {@link AuthorizationMethod}.
253      */
254     public void removeAuthorization(final String method) {
255         this.authorizations.unregister(method);
256     }
257 
258     /**
259      * Returns the {@link Authorization} that has specified name of
260      * {@link AuthorizationMethod}. If this {@link ContextEventType} does not
261      * have {@link Authorization} with specified name
262      * {@link AuthorizationMethod}, <code>null</code> will be returned.
263      * 
264      * @param method the name of {@link AuthorizationMethod}.
265      * @return the {@link Authorization}; or <code>null</code> if there is no
266      *         such {@link Authorization}.
267      */
268     public Authorization getAuthorization(final String method) {
269         return this.authorizations.get(method);
270     }
271 
272     /**
273      * Returns all currently added {@link Authorization}s.
274      * 
275      * @return all currently added {@link Authorization}s.
276      */
277     public Authorization[] getAuthorizations() {
278         return this.authorizations.getAll();
279     }
280 
281     /**
282      * Returns if an {@link Authorization} that has specified name of
283      * {@link AuthorizationMethod} is currently present in this
284      * {@link ContextEvent}. If the {@link Authorization} was never added (or
285      * was added and consequently removed), <code>false</code> will be returned;
286      * otherwise <code>true</code> will be returned.
287      * 
288      * @param method the name of {@link AuthorizationMethod}.
289      * @return if an {@link Authorization} that has specified name of
290      *         {@link AuthorizationMethod} is currently present in this
291      *         {@link ContextEvent}.
292      */
293     public boolean hasAuthorization(final String method) {
294         return this.authorizations.isRegistered(method);
295     }
296 
297     /**
298      * Returns if there is any added {@link Authorization} in this
299      * {@link ContextEvent}.
300      * 
301      * @return if there is any added {@link Authorization} in this
302      *         {@link ContextEvent}.
303      */
304     public boolean hasAuthorizations() {
305         return this.authorizations.getAll().length > 0;
306     }
307 
308     /**
309      * Add specified {@link Authorization}s and remove all previously registered
310      * {@link Authorization}s.
311      * 
312      * @param authorizations {@link Authorization}s.
313      */
314     protected void set(final Authorization... authorizations) {
315         this.authorizations.setAll(authorizations);
316     }
317 
318     /**
319      * Returns hash code for this {@link ContextEvent}. The hash code for a
320      * {@link ContextEvent} object is computed as:
321      * 
322      * <pre>
323      * type * 31 + super
324      * </pre>
325      * 
326      * using integer arithmetic.
327      * 
328      * @return a hash code value for this {@link ContextEvent}.
329      */
330     @Override
331     public int hashCode() {
332         final int prime = 31;
333         return (this.type.hashCode() * prime) + super.hashCode();
334     }
335 
336     /**
337      * Compares this {@link ContextEvent} to the specified {@link Object}. The
338      * result is <code>true</code> if and only if the argument is not
339      * <code>null</code> and is a {@link ContextEvent} object that has same
340      * type, source ID, and time stamp as this {@link ContextEvent}.
341      * 
342      * @param obj the {@link Object} to compare this {@link ContextEvent}
343      *        against.
344      * @return <code>true</code> if this {@link ContextEvent}s are equal;
345      *         <code>false</code> otherwise.
346      */
347     @Override
348     public boolean equals(final Object obj) {
349         boolean result = super.equals(obj) && (obj instanceof ContextEvent);
350 
351         if (result) {
352             final ContextEvent other = (ContextEvent) obj;
353             result = this.type.equals(other.type);
354         }
355 
356         return result;
357     }
358 }