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.ArrayList;
21  import java.util.List;
22  import java.util.concurrent.locks.ReadWriteLock;
23  import java.util.concurrent.locks.ReentrantReadWriteLock;
24  
25  /**
26   * Class which defines a list of {@link ContextEventAction}s and makes possible
27   * to manipulate and retrieve {@link ContextEventAction}.
28   * 
29   * @param <T> the subclass of {@link ContextEventAction} that is used for
30   *        storage and retrieval.
31   * @author sanjin
32   */
33  public class Actions<T extends ContextEventAction> {
34  
35      private static final ContextEventAction[] EMPTY_ACTIONS = new ContextEventAction[0];
36  
37      private final List<T> actions = new ArrayList<T>();
38      private final ReadWriteLock lock = new ReentrantReadWriteLock();
39  
40      /**
41       * Return {@link ContextEventAction} at specified index.
42       * 
43       * @param index the index of the {@link ContextEventAction} to return.
44       * @return the {@link ContextEventAction}.
45       * @throws IllegalArgumentException if specified index has negative value or
46       *         is greater or equal than {@link #size()}.
47       */
48      public T get(final int index) {
49          if (index < 0) {
50              throw new IllegalArgumentException("Index cannot be negative.");
51          }
52  
53          final T result;
54  
55          this.lock.readLock().lock();
56          try {
57              if (index >= this.actions.size()) {
58                  throw new IllegalArgumentException(
59                          "Index cannot be greater than or equal to number of actions.");
60              }
61  
62              result = this.actions.get(index);
63          } finally {
64              this.lock.readLock().unlock();
65          }
66  
67          return result;
68      }
69  
70      /**
71       * Set specified {@link ContextEventAction} at specified index.
72       * 
73       * @param index the index at which to set the {@link ContextEventAction}.
74       * @param action the {@link ContextEventAction}.
75       * @throws NullPointerException if specified {@link ContextEventAction} is
76       *         <code>null</code>.
77       * @throws IllegalArgumentException if specified index has negative value or
78       *         is greater or equal than {@link #size()}.
79       */
80      public void set(final int index, final T action) {
81          if (null == action) {
82              throw new NullPointerException("Action cannot be null.");
83          }
84          if (index < 0) {
85              throw new IllegalArgumentException("Index cannot be negative.");
86          }
87  
88          this.lock.writeLock().lock();
89          try {
90              if (index >= this.actions.size()) {
91                  throw new IllegalArgumentException(
92                          "Index cannot be greater than or equal to number of actions.");
93              }
94  
95              this.actions.remove(index);
96              this.actions.add(index, action);
97          } finally {
98              this.lock.writeLock().unlock();
99          }
100     }
101 
102     /**
103      * Return all currently added {@link ContextEventAction}s.
104      * 
105      * @return all currently added {@link ContextEventAction}s.
106      */
107     public ContextEventAction[] getAll() {
108         final ContextEventAction[] result;
109 
110         this.lock.readLock().lock();
111         try {
112             if (this.actions.isEmpty()) {
113                 result = EMPTY_ACTIONS;
114             } else {
115                 result = this.actions.toArray(new ContextEventAction[this.actions.size()]);
116             }
117         } finally {
118             this.lock.readLock().unlock();
119         }
120 
121         return result;
122     }
123 
124     /**
125      * Add specified {@link ContextEventAction}s and remove all previous
126      * {@link ContextEventAction}s.
127      * 
128      * @param actions the {@link ContextEventAction}s.
129      * @throws NullPointerException if specified array
130      *         {@link ContextEventAction}s or any {@link ContextEventAction} in
131      *         the array is <code>null</code>.
132      */
133     public void setAll(final T... actions) {
134         if (null == actions) {
135             throw new NullPointerException("Actions cannot be null.");
136         }
137         for (final T action : actions) {
138             if (null == action) {
139                 throw new NullPointerException("Action cannot be null.");
140             }
141         }
142 
143         this.lock.writeLock().lock();
144         try {
145             this.actions.clear();
146             for (final T action : actions) {
147                 this.actions.add(action);
148             }
149         } finally {
150             this.lock.writeLock().unlock();
151         }
152     }
153 
154     /**
155      * Return if there is at least one {@link ContextEventAction} with specified
156      * name.
157      * 
158      * @param name the name of the {@link ContextEventAction}.
159      * @return if there is at least one {@link ContextEventAction} with
160      *         specified name.
161      */
162     public boolean contains(final String name) {
163         boolean result = false;
164 
165         this.lock.readLock().lock();
166         try {
167             for (final T action : this.actions) {
168                 if (name.equals(action.getName())) {
169                     result = true;
170                     break;
171                 }
172             }
173         } finally {
174             this.lock.readLock().unlock();
175         }
176 
177         return result;
178     }
179 
180     /**
181      * Return the number of {@link ContextEventAction}.
182      * 
183      * @return the number of {@link ContextEventAction}.
184      */
185     public int size() {
186         final int result;
187 
188         this.lock.readLock().lock();
189         try {
190             result = this.actions.size();
191         } finally {
192             this.lock.readLock().unlock();
193         }
194 
195         return result;
196     }
197 
198     /**
199      * Append specified {@link ContextEventAction}s.
200      * 
201      * @param actions the {@link ContextEventAction}s.
202      * @param <S> the type of appended {@link ContextEventAction}s.
203      * @throws NullPointerException if specified array of
204      *         {@link ContextEventAction}s or any {@link ContextEventAction} in
205      *         the array is <code>null</code>.
206      */
207     public <S extends T> void append(
208             @SuppressWarnings("hiding") final S... actions) {
209         if (null == actions) {
210             throw new NullPointerException("Actions cannot be null.");
211         }
212         for (final S action : actions) {
213             if (null == action) {
214                 throw new NullPointerException("Action cannot be null.");
215             }
216         }
217 
218         this.lock.writeLock().lock();
219         try {
220             for (final S action : actions) {
221                 this.actions.add(action);
222             }
223         } finally {
224             this.lock.writeLock().unlock();
225         }
226     }
227 
228     /**
229      * Insert specified {@link ContextEventAction} at specified index.
230      * 
231      * @param index the index at which the {@link ContextEventAction} is
232      *        inserted.
233      * @param action the {@link ContextEventAction}.
234      * @throws NullPointerException if specified {@link ContextEventAction} is
235      *         <code>null</code>.
236      * @throws IllegalArgumentException if specified index has negative value or
237      *         is greater or equal than {@link #size()}.
238      */
239     public void insert(final int index, final T action) {
240         if (null == action) {
241             throw new NullPointerException("Action cannot be null.");
242         }
243         if (index < 0) {
244             throw new IllegalArgumentException("Index cannot be negative.");
245         }
246 
247         this.lock.writeLock().lock();
248         try {
249             if (index >= this.actions.size()) {
250                 throw new IllegalArgumentException(
251                         "Index cannot be greater than or equal to number of actions.");
252             }
253 
254             this.actions.add(index, action);
255         } finally {
256             this.lock.writeLock().unlock();
257         }
258     }
259 
260     /**
261      * Remove the {@link ContextEventAction} at specified position.
262      * 
263      * @param index the position of the {@link ContextEventAction} to remove.
264      * @throws IllegalArgumentException if specified index has negative value or
265      *         is greater or equal than {@link #size()}.
266      */
267     public void remove(final int index) {
268         if (index < 0) {
269             throw new IllegalArgumentException("Index cannot be negative.");
270         }
271 
272         this.lock.writeLock().lock();
273         try {
274             if (index >= this.actions.size()) {
275                 throw new IllegalArgumentException(
276                         "Index cannot be greater than or equal to number of actions.");
277             }
278 
279             this.actions.remove(index);
280         } finally {
281             this.lock.writeLock().unlock();
282         }
283     }
284 
285     /**
286      * Remove all {@link ContextEventAction}s.
287      */
288     public void clear() {
289         this.lock.writeLock().lock();
290         try {
291             this.actions.clear();
292         } finally {
293             this.lock.writeLock().unlock();
294         }
295     }
296 }