001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.client.persistence.javafx;
022
023 import java.io.Externalizable;
024 import java.io.IOException;
025 import java.io.ObjectInput;
026 import java.io.ObjectOutput;
027 import java.util.ArrayList;
028 import java.util.Arrays;
029 import java.util.Collection;
030 import java.util.IdentityHashMap;
031 import java.util.Iterator;
032 import java.util.List;
033 import java.util.ListIterator;
034 import java.util.Map;
035 import java.util.Set;
036
037 import javafx.beans.InvalidationListener;
038 import javafx.collections.FXCollections;
039 import javafx.collections.ListChangeListener;
040 import javafx.collections.ObservableList;
041
042 import org.granite.logging.Logger;
043 import org.granite.messaging.amf.RemoteClass;
044 import org.granite.client.persistence.LazyableCollection;
045
046 /**
047 * @author William DRAI
048 */
049 @RemoteClass("org.granite.messaging.persistence.ExternalizablePersistentSet")
050 public class PersistentSet<T> implements Set<T>, ObservableList<T>, LazyableCollection, Externalizable {
051
052 @SuppressWarnings("unused")
053 private static final Logger log = Logger.getLogger(PersistentSet.class);
054
055 @SuppressWarnings("unused")
056 private boolean initializing = false;
057 private boolean initialized = false;
058 private String metadata = null;
059 private boolean dirty = false;
060
061 private ObservableList<T> oset;
062
063 private ListChangeListener<T> listener = new ListChangeListener<T>() {
064 public void onChanged(ListChangeListener.Change<? extends T> change) {
065 if (!initialized)
066 return;
067 while (change.next()) {
068 if (change.wasAdded() || change.wasRemoved() || change.wasReplaced() || change.wasPermutated()) {
069 dirty = true;
070 break;
071 }
072 }
073 }
074 };
075
076
077 public PersistentSet() {
078 this.oset = FXCollections.observableArrayList();
079 this.initialized = true;
080 this.oset.addListener(listener);
081 }
082
083 public PersistentSet(Set<T> set) {
084 this.oset = FXCollections.observableArrayList(set);
085 this.initialized = true;
086 this.oset.addListener(listener);
087 }
088
089 public PersistentSet(boolean initialized) {
090 this.oset = FXCollections.observableArrayList();
091 this.initialized = initialized;
092 if (initialized)
093 this.oset.addListener(listener);
094 }
095
096
097 public final boolean isInitialized() {
098 return initialized;
099 }
100
101 public void initializing() {
102 clear();
103 initializing = true;
104 dirty = false;
105 oset.removeListener(listener);
106 }
107
108 public void initialize() {
109 initializing = false;
110 initialized = true;
111 dirty = false;
112 oset.addListener(listener);
113 }
114
115 public void uninitialize() {
116 oset.removeListener(listener);
117 initialized = false;
118 clear();
119 dirty = false;
120 }
121
122 public PersistentSet<T> clone(boolean uninitialize) {
123 PersistentSet<T> coll = new PersistentSet<T>(initialized && !uninitialize);
124 coll.metadata = metadata;
125 if (initialized) {
126 for (T obj : this)
127 coll.add(obj);
128 }
129 coll.dirty = dirty;
130 return coll;
131 }
132
133 public void addListener(InvalidationListener listener) {
134 oset.addListener(listener);
135 }
136
137 public void removeListener(InvalidationListener listener) {
138 oset.removeListener(listener);
139 }
140
141 private Map<ListChangeListener<? super T>, ListChangeListener<? super T>> listenerWrappers = new IdentityHashMap<ListChangeListener<? super T>, ListChangeListener<? super T>>();
142
143 @SuppressWarnings({ "unchecked", "rawtypes" })
144 public void addListener(ListChangeListener<? super T> listener) {
145 ListChangeListener<? super T> listenerWrapper = new ListChangeListenerWrapper(this, listener);
146 listenerWrappers.put(listener, listenerWrapper);
147 oset.addListener(listenerWrapper);
148 }
149
150 public void removeListener(ListChangeListener<? super T> listener) {
151 ListChangeListener<? super T> listenerWrapper = listenerWrappers.remove(listener);
152 if (listenerWrapper != null)
153 oset.removeListener(listenerWrapper);
154 }
155
156 public boolean isEmpty() {
157 return oset.isEmpty();
158 }
159
160 public boolean contains(Object o) {
161 return oset.contains(o);
162 }
163
164 public Iterator<T> iterator() {
165 return oset.iterator();
166 }
167
168 public boolean add(T e) {
169 return oset.add(e);
170 }
171
172 public boolean remove(Object o) {
173 return oset.remove(o);
174 }
175
176 public boolean containsAll(Collection<?> c) {
177 return oset.containsAll(c);
178 }
179
180 public boolean addAll(Collection<? extends T> c) {
181 List<T> toAdd = new ArrayList<T>(c);
182 toAdd.removeAll(oset);
183 return oset.addAll(toAdd);
184 }
185
186 public boolean addAll(int index, Collection<? extends T> c) {
187 List<T> toAdd = new ArrayList<T>(c);
188 toAdd.removeAll(oset);
189 return oset.addAll(index, toAdd);
190 }
191
192 public boolean removeAll(Collection<?> c) {
193 return oset.removeAll(c);
194 }
195
196 public boolean equals(Object o) {
197 return oset.equals(o);
198 }
199
200 public int hashCode() {
201 return oset.hashCode();
202 }
203
204 public T get(int index) {
205 return oset.get(index);
206 }
207
208 public void add(int index, T element) {
209 oset.add(index, element);
210 }
211
212 public boolean addAll(T... elements) {
213 List<T> toAdd = Arrays.asList(elements);
214 toAdd.removeAll(oset);
215 return oset.addAll(toAdd);
216 }
217
218 public void clear() {
219 oset.clear();
220 }
221
222 public int indexOf(Object o) {
223 return oset.indexOf(o);
224 }
225
226 public int lastIndexOf(Object o) {
227 return oset.lastIndexOf(o);
228 }
229
230 public ListIterator<T> listIterator() {
231 return oset.listIterator();
232 }
233
234 public ListIterator<T> listIterator(int index) {
235 return oset.listIterator(index);
236 }
237
238 public void remove(int arg0, int arg1) {
239 oset.remove(arg0, arg1);
240 }
241
242 public T remove(int index) {
243 return oset.remove(index);
244 }
245
246 public boolean removeAll(T... elements) {
247 return oset.removeAll(elements);
248 }
249
250 public boolean retainAll(Collection<?> c) {
251 return oset.retainAll(c);
252 }
253
254 public boolean retainAll(T... elements) {
255 return oset.retainAll(elements);
256 }
257
258 public T set(int index, T element) {
259 return oset.set(index, element);
260 }
261
262 public boolean setAll(Collection<? extends T> coll) {
263 return oset.setAll(coll);
264 }
265
266 public boolean setAll(T... arg0) {
267 return oset.setAll(arg0);
268 }
269
270 public int size() {
271 return oset.size();
272 }
273
274 public Object[] toArray() {
275 return oset.toArray();
276 }
277
278 @SuppressWarnings("hiding")
279 public <T> T[] toArray(T[] a) {
280 return oset.toArray(a);
281 }
282
283 public List<T> subList(int fromIndex, int toIndex) {
284 return oset.subList(fromIndex, toIndex);
285 }
286
287 @Override
288 public String toString() {
289 return getClass().getSimpleName() + (initialized ? "" : " (uninitialized)") + (dirty ? " (dirty)" : "") + ":" + oset.toString();
290 }
291
292 @SuppressWarnings("unchecked")
293 public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
294 initialized = ((Boolean)input.readObject()).booleanValue();
295 metadata = (String)input.readObject();
296 if (initialized) {
297 dirty = ((Boolean)input.readObject()).booleanValue();
298 T[] array = (T[])input.readObject();
299 oset = FXCollections.observableArrayList(array);
300 }
301 }
302
303 public void writeExternal(ObjectOutput output) throws IOException {
304 output.writeObject(Boolean.valueOf(initialized));
305 output.writeObject(metadata);
306 if (initialized) {
307 output.writeObject(Boolean.valueOf(dirty));
308 output.writeObject(oset.toArray());
309 }
310 }
311 }