View Javadoc

1   /*
2    * $Id: ObservableList.java 20320 2010-11-24 15:03:31Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.launcher.util;
12  
13  import java.beans.PropertyChangeListener;
14  import java.beans.PropertyChangeSupport;
15  import java.util.ArrayList;
16  import java.util.Collection;
17  import java.util.Iterator;
18  import java.util.List;
19  import java.util.ListIterator;
20  
21  /**
22   * Adapted version of a groovy.util.ObservableList.
23   * List decorator that will trigger PropertyChangeEvents when a value changes.<br>
24   * <p/>
25   * The current implementation will trigger specialized events in the following scenarios, you need
26   * not register a different listener as those events extend from PropertyChangeEvent
27   * <ul>
28   * <li>ObservableList.ElementAddedEvent - a new element is added to the list</li>
29   * <li>ObservableList.ElementRemovedEvent - a element is removed from the list</li>
30   * <li>ObservableList.ElementUpdatedEvent - a element changes value (same as regular
31   * PropertyChangeEvent)</li>
32   * <li>ObservableList.ElementClearedEvent - all elements have been removed from the list</li>
33   * <li>ObservableList.MultiElementAddedEvent - triggered by calling list.addAll()</li>
34   * <li>ObservableList.MultiElementRemovedEvent - triggered by calling
35   * list.removeAll()/list.retainAll()</li>
36   * </ul>
37   * </p>
38   */
39  public class ObservableList<E> implements List<E> {
40  
41      private List<E> delegate;
42      private PropertyChangeSupport pcs;
43  
44      public ObservableList() {
45          this(new ArrayList<E>());
46      }
47  
48      public ObservableList(List<E> delegate) {
49          this.delegate = delegate;
50          pcs = new PropertyChangeSupport(this);
51      }
52  
53      public void add(int index, E element) {
54          delegate.add(index, element);
55          pcs.firePropertyChange(new ElementAddedEvent(this, element, index));
56      }
57  
58  
59      public boolean addAll(Collection<? extends E> c) {
60          int index = size() - 1;
61          index = index < 0 ? 0 : index;
62  
63          boolean success = delegate.addAll(c);
64          if (success && c != null) {
65              List<E> values = new ArrayList<E>();
66              for (E element : values) {
67                  values.add(element);
68              }
69  
70              if (values.size() > 0) {
71                  pcs.firePropertyChange(new MultiElementAddedEvent(this, index, values));
72              }
73          }
74  
75          return success;
76      }
77  
78      public boolean addAll(int index, Collection<? extends E> c) {
79          boolean success = delegate.addAll(index, c);
80  
81          if (success && c != null) {
82              List<E> values = new ArrayList<E>();
83              for (E element : c) {
84                  values.add(element);
85              }
86              if (values.size() > 0) {
87                  pcs.firePropertyChange(new MultiElementAddedEvent(this, index, values));
88              }
89          }
90  
91          return success;
92      }
93  
94      public void clear() {
95          List values = new ArrayList();
96          values.addAll(delegate);
97          delegate.clear();
98          if (!values.isEmpty()) {
99              pcs.firePropertyChange(new ElementsClearedEvent(this, values));
100         }
101     }
102 
103     public boolean contains(Object o) {
104         return delegate.contains(o);
105     }
106 
107     public boolean containsAll(Collection<?> c) {
108         return delegate.containsAll(c);
109     }
110 
111     public boolean equals(Object o) {
112         return delegate.equals(o);
113     }
114 
115     public E get(int index) {
116         return delegate.get(index);
117     }
118 
119     public int hashCode() {
120         return delegate.hashCode();
121     }
122 
123     public int indexOf(Object o) {
124         return delegate.indexOf(o);
125     }
126 
127     public boolean isEmpty() {
128         return delegate.isEmpty();
129     }
130 
131     public Iterator<E> iterator() {
132         return new ObservableIterator(delegate.iterator());
133     }
134 
135     public int lastIndexOf(Object o) {
136         return delegate.lastIndexOf(o);
137     }
138 
139     public ListIterator<E> listIterator() {
140         return new ObservableListIterator(delegate.listIterator(), 0);
141     }
142 
143     public ListIterator<E> listIterator(int index) {
144         return new ObservableListIterator(delegate.listIterator(index), index);
145     }
146 
147     public E remove(int index) {
148         E element = delegate.remove(index);
149         pcs.firePropertyChange(new ElementRemovedEvent(this, element, index));
150         return element;
151     }
152 
153     public boolean remove(Object o) {
154         int index = delegate.indexOf(o);
155         boolean success = delegate.remove(o);
156         if (success) {
157             pcs.firePropertyChange(new ElementRemovedEvent(this, o, index));
158         }
159         return success;
160     }
161 
162     public boolean removeAll(Collection<?> c) {
163         if (c == null) {
164             return false;
165         }
166 
167         List<Object> values = new ArrayList();
168         for (Object element : c) {
169             if (delegate.contains(element)) {
170                 values.add(element);
171             }
172         }
173 
174         boolean success = delegate.removeAll(c);
175         if (success && !values.isEmpty()) {
176             pcs.firePropertyChange(new MultiElementRemovedEvent(this, values));
177         }
178 
179         return success;
180     }
181 
182     public boolean retainAll(Collection<?> c) {
183         if (c == null) {
184             return false;
185         }
186 
187         List<E> values = new ArrayList<E>();
188         if (c != null) {
189             for (E element : delegate) {
190                 if (!c.contains(element)) {
191                     values.add(element);
192                 }
193             }
194         }
195 
196         boolean success = delegate.retainAll(c);
197         if (success && !values.isEmpty()) {
198             pcs.firePropertyChange(new MultiElementRemovedEvent(this, values));
199         }
200 
201         return success;
202     }
203 
204     public E set(int index, E element) {
205         E oldValue = delegate.set(index, element);
206         pcs.firePropertyChange(new ElementUpdatedEvent(this, oldValue, element, index));
207         return oldValue;
208     }
209 
210     public int size() {
211         return delegate.size();
212     }
213 
214     public List subList(int fromIndex, int toIndex) {
215         return delegate.subList(fromIndex, toIndex);
216     }
217 
218     public Object[] toArray() {
219         return delegate.toArray();
220     }
221 
222     public boolean add(E o) {
223         boolean success = delegate.add(o);
224         if (success) {
225             pcs.firePropertyChange(new ElementAddedEvent(this, o, size() - 1));
226         }
227         return success;
228     }
229 
230 
231     public Object[] toArray(Object[] a) {
232         return delegate.toArray(a);
233     }
234 
235     private class ObservableIterator implements Iterator<E> {
236 
237         private Iterator<E> iterDelegate;
238         protected int cursor = 0;
239 
240         public ObservableIterator(Iterator<E> iterDelegate) {
241             this.iterDelegate = iterDelegate;
242         }
243 
244         public Iterator<E> getDelegate() {
245             return iterDelegate;
246         }
247 
248         public boolean hasNext() {
249             return iterDelegate.hasNext();
250         }
251 
252         public E next() {
253             cursor++;
254             return iterDelegate.next();
255         }
256 
257         public void remove() {
258             ObservableList.this.remove(cursor--);
259         }
260     }
261 
262     protected class ObservableListIterator extends ObservableIterator implements ListIterator<E> {
263 
264         public ObservableListIterator(ListIterator<E> iterDelegate, int index) {
265             super(iterDelegate);
266             cursor = index;
267         }
268 
269         public ListIterator<E> getListIterator() {
270             return (ListIterator<E>) getDelegate();
271         }
272 
273         public void add(E o) {
274             ObservableList.this.add(o);
275             cursor++;
276         }
277 
278         public boolean hasPrevious() {
279             return getListIterator().hasPrevious();
280         }
281 
282         public int nextIndex() {
283             return getListIterator().nextIndex();
284         }
285 
286         public E previous() {
287             return getListIterator().previous();
288         }
289 
290         public int previousIndex() {
291             return getListIterator().previousIndex();
292         }
293 
294         public void set(E e) {
295             ObservableList.this.set(cursor, e);
296         }
297 
298     }
299 
300     // observable interface
301 
302     public void addPropertyChangeListener(PropertyChangeListener listener) {
303         pcs.addPropertyChangeListener(listener);
304     }
305 
306     public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
307         pcs.addPropertyChangeListener(propertyName, listener);
308     }
309 
310     public PropertyChangeListener[] getPropertyChangeListeners() {
311         return pcs.getPropertyChangeListeners();
312     }
313 
314     public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
315         return pcs.getPropertyChangeListeners(propertyName);
316     }
317 
318     public void removePropertyChangeListener(PropertyChangeListener listener) {
319         pcs.removePropertyChangeListener(listener);
320     }
321 
322     public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
323         pcs.removePropertyChangeListener(propertyName, listener);
324     }
325 
326     public boolean hasListeners(String propertyName) {
327         return pcs.hasListeners(propertyName);
328     }
329 
330 }