1 package cz.cuni.amis.utils.collections;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.Iterator;
7 import java.util.LinkedList;
8
9 import cz.cuni.amis.utils.listener.Listeners;
10
11
12
13
14
15
16
17 public class ObservableCollection<E> implements Collection<E> {
18
19 protected Collection<E> col = null;
20 protected Listeners<CollectionEventListener> eventListeners = new Listeners<CollectionEventListener>();
21
22 private abstract class ListenerNotifier implements Listeners.ListenerNotifier<CollectionEventListener> {
23
24 public Collection what;
25 public Collection where;
26
27 public ListenerNotifier() {
28 }
29
30 @Override
31 public Object getEvent() {
32 return what;
33 }
34
35 @Override
36 public abstract void notify(CollectionEventListener listener);
37
38 }
39
40 private ListenerNotifier preAddNotifier = new ListenerNotifier() {
41
42 @Override
43 public void notify(CollectionEventListener listener) {
44 listener.preAddEvent(what, where);
45 }
46
47 };
48
49 private ListenerNotifier postAddNotifier = new ListenerNotifier() {
50
51 @Override
52 public void notify(CollectionEventListener listener) {
53 listener.postAddEvent(what, where);
54 }
55
56 };
57
58 private ListenerNotifier preRemoveNotifier = new ListenerNotifier() {
59
60 @Override
61 public void notify(CollectionEventListener listener) {
62 listener.preRemoveEvent(what, where);
63 }
64
65 };
66
67 private ListenerNotifier postRemoveNotifier = new ListenerNotifier() {
68
69 @Override
70 public void notify(CollectionEventListener listener) {
71 listener.postRemoveEvent(what, where);
72 }
73
74 };
75
76 public void addCollectionListener(CollectionEventListener listener) {
77 eventListeners.addStrongListener(listener);
78 }
79
80 public boolean removeCollectionListener(CollectionEventListener listener) {
81 return eventListeners.removeListener(listener) > 0;
82 }
83
84 public ObservableCollection(Collection c) {
85 col = c;
86 }
87
88 @Override
89 public int size() {
90 return col.size();
91 }
92
93 @Override
94 public boolean isEmpty() {
95 return col.isEmpty();
96 }
97
98 @Override
99 public boolean contains(Object o) {
100 return col.contains(o);
101 }
102
103 @Override
104 public Iterator<E> iterator() {
105 return col.iterator();
106 }
107
108 @Override
109 public Object[] toArray() {
110 return col.toArray();
111 }
112
113 @Override
114 public <T> T[] toArray(T[] a) {
115 return col.toArray(a);
116 }
117
118 @Override
119 public boolean add(E e) {
120 Collection add = Collections.singletonList(e);
121 notifyPreAdd(add);
122 boolean ret = col.add(e);
123 notifyPostAdd(add);
124 return ret;
125 }
126
127 @Override
128 public boolean remove(Object o) {
129 Collection rem = Collections.singletonList(o);
130 notifyPreRemove(rem);
131 boolean ret = col.remove(o);
132 notifyPostRemove(rem);
133 return ret;
134 }
135
136 @Override
137 public boolean containsAll(Collection<?> c) {
138 return col.containsAll(c);
139 }
140
141 @Override
142 public boolean addAll(Collection<? extends E> c) {
143 notifyPreAdd(c);
144 boolean ret = col.addAll(c);
145 notifyPostAdd(c);
146 return ret;
147
148 }
149
150 @Override
151 public boolean removeAll(Collection<?> c) {
152 notifyPreRemove(c);
153 boolean ret = col.removeAll(c);
154 notifyPostRemove(c);
155 return ret;
156 }
157
158 @Override
159 public boolean retainAll(Collection<?> c) {
160
161 Collection<Object> toRemove = new LinkedList<Object>();
162 for (Object o : col) {
163 if (!c.contains(o)) {
164 toRemove.add(o);
165 }
166 }
167 notifyPreRemove(toRemove);
168 boolean ret = col.retainAll(c);
169 notifyPostRemove(toRemove);
170
171 return ret;
172 }
173
174 @Override
175 public void clear() {
176 Collection<Object> copy = new ArrayList<Object>(col);
177 notifyPreRemove(copy);
178 col.clear();
179 notifyPostRemove(copy);
180 }
181
182 protected synchronized void notifyPreAdd(Collection<? extends E> add) {
183 preAddNotifier.what = add;
184 preAddNotifier.where = this;
185 eventListeners.notify(preAddNotifier);
186 }
187
188 protected synchronized void notifyPostAdd(Collection<? extends E> add) {
189 postAddNotifier.what = add;
190 postAddNotifier.where = this;
191 eventListeners.notify(postAddNotifier);
192 }
193
194 protected synchronized void notifyPreRemove(Collection<?> remove) {
195 preRemoveNotifier.what = remove;
196 preRemoveNotifier.where = this;
197 eventListeners.notify(preRemoveNotifier);
198 }
199
200 protected synchronized void notifyPostRemove(Collection<?> remove) {
201 postRemoveNotifier.what = remove;
202 postRemoveNotifier.where = this;
203 eventListeners.notify(postRemoveNotifier);
204 }
205 }