001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2013 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.messaging.amf.persistence;
022
023 import java.io.IOException;
024 import java.io.ObjectInput;
025 import java.io.ObjectOutput;
026 import java.util.Arrays;
027 import java.util.Collection;
028 import java.util.Comparator;
029 import java.util.Iterator;
030 import java.util.Map;
031 import java.util.Map.Entry;
032 import java.util.NoSuchElementException;
033 import java.util.Set;
034
035 import org.granite.messaging.persistence.PersistentCollectionSnapshot;
036
037 /**
038 * @author Franck WOLFF
039 */
040 public class AMFPersistentCollectionSnapshot implements PersistentCollectionSnapshot {
041
042 protected boolean initialized = false;
043 protected String detachedState = null;
044 protected boolean dirty = false;
045 protected Object[] elements = null;
046
047 public AMFPersistentCollectionSnapshot(String detachedState) {
048 this.detachedState = detachedState;
049 }
050
051 public AMFPersistentCollectionSnapshot(boolean sorted, String detachedState) {
052 this.detachedState = detachedState;
053 }
054
055 public AMFPersistentCollectionSnapshot(boolean initialized, String detachedState, boolean dirty, Collection<?> collection) {
056 this.initialized = initialized;
057 this.detachedState = detachedState;
058 if (initialized) {
059 this.dirty = dirty;
060 this.elements = collection.toArray();
061 }
062 }
063
064 public AMFPersistentCollectionSnapshot(boolean initialized, String detachedState, boolean dirty, Map<?, ?> collection) {
065 this.initialized = initialized;
066 this.detachedState = detachedState;
067 if (initialized) {
068 this.dirty = dirty;
069
070 Object[] entries = collection.entrySet().toArray();
071 this.elements = new Object[entries.length];
072
073 int elementIndex = 0;
074 for (int entryIndex = 0; entryIndex < entries.length; entryIndex++) {
075 Map.Entry<?, ?> entry = (Map.Entry<?, ?>)entries[entryIndex];
076 this.elements[elementIndex++] = new Object[] { entry.getKey(), entry.getValue() };
077 }
078 }
079 }
080
081 public boolean isInitialized() {
082 return initialized;
083 }
084
085 public String getDetachedState() {
086 return detachedState;
087 }
088
089 public boolean isDirty() {
090 return dirty;
091 }
092
093 public boolean isSorted() {
094 return false;
095 }
096
097 public <T> Comparator<T> newComparator(ObjectInput in) {
098 return null;
099 }
100
101 @SuppressWarnings("unchecked")
102 public <T> Collection<T> getElementsAsCollection() {
103 return (Collection<T>)Arrays.asList(elements);
104 }
105
106 public <K, V> Map<K, V> getElementsAsMap() {
107 return new SnapshotMap<K, V>(elements);
108 }
109
110 public void writeExternal(ObjectOutput out) throws IOException {
111 out.writeObject(initialized);
112 out.writeObject(detachedState);
113 if (initialized) {
114 out.writeObject(dirty);
115 out.writeObject(elements);
116 }
117 }
118
119 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
120 readInitializationData(in);
121 if (initialized)
122 readCoreData(in);
123 }
124
125 public void readInitializationData(ObjectInput in) throws IOException, ClassNotFoundException {
126 initialized = ((Boolean)in.readObject()).booleanValue();
127 detachedState = (String)in.readObject();
128 }
129
130 public void readCoreData(ObjectInput in) throws IOException, ClassNotFoundException {
131 this.dirty = ((Boolean)in.readObject()).booleanValue();
132 this.elements = (Object[])in.readObject();
133 }
134
135 static class SnapshotMap<K, V> implements Map<K, V> {
136
137 private final Object[] elements;
138
139 public SnapshotMap(Object[] elements) {
140 this.elements = elements;
141 }
142
143 public int size() {
144 return elements.length;
145 }
146
147 public boolean isEmpty() {
148 return elements.length == 0;
149 }
150
151 public Set<Entry<K, V>> entrySet() {
152 return new Set<Entry<K, V>>() {
153
154 public int size() {
155 return elements.length;
156 }
157
158 public boolean isEmpty() {
159 return elements.length == 0;
160 }
161
162 public Iterator<Entry<K, V>> iterator() {
163
164 return new Iterator<Entry<K, V>>() {
165
166 private int cursor = 0;
167
168 public boolean hasNext() {
169 return cursor < elements.length;
170 }
171
172 @SuppressWarnings("unchecked")
173 public Entry<K, V> next() {
174 if (cursor >= elements.length)
175 throw new NoSuchElementException();
176
177 Object[] element = (Object[])elements[cursor++];
178 K key = (K)element[0];
179 V value = (V)element[1];
180 return new SnapshotMapEntry<K, V>(key, value);
181 }
182
183 public void remove() {
184 throw new UnsupportedOperationException();
185 }
186 };
187 }
188
189 public boolean contains(Object o) {
190 throw new UnsupportedOperationException();
191 }
192
193 public Object[] toArray() {
194 throw new UnsupportedOperationException();
195 }
196
197 public <T> T[] toArray(T[] a) {
198 throw new UnsupportedOperationException();
199 }
200
201 public boolean add(Entry<K, V> e) {
202 throw new UnsupportedOperationException();
203 }
204
205 public boolean remove(Object o) {
206 throw new UnsupportedOperationException();
207 }
208
209 public boolean containsAll(Collection<?> c) {
210 throw new UnsupportedOperationException();
211 }
212
213 public boolean addAll(Collection<? extends Entry<K, V>> c) {
214 throw new UnsupportedOperationException();
215 }
216
217 public boolean retainAll(Collection<?> c) {
218 throw new UnsupportedOperationException();
219 }
220
221 public boolean removeAll(Collection<?> c) {
222 throw new UnsupportedOperationException();
223 }
224
225 public void clear() {
226 throw new UnsupportedOperationException();
227 }
228
229 @Override
230 public int hashCode() {
231 throw new UnsupportedOperationException();
232 }
233
234 @Override
235 public boolean equals(Object obj) {
236 throw new UnsupportedOperationException();
237 }
238 };
239 }
240
241 public boolean containsKey(Object key) {
242 throw new UnsupportedOperationException();
243 }
244
245 public boolean containsValue(Object value) {
246 throw new UnsupportedOperationException();
247 }
248
249 public V get(Object key) {
250 throw new UnsupportedOperationException();
251 }
252
253 public V put(K key, V value) {
254 throw new UnsupportedOperationException();
255 }
256
257 public V remove(Object key) {
258 throw new UnsupportedOperationException();
259 }
260
261 public void putAll(Map<? extends K, ? extends V> m) {
262 throw new UnsupportedOperationException();
263 }
264
265 public void clear() {
266 throw new UnsupportedOperationException();
267 }
268
269 public Set<K> keySet() {
270 throw new UnsupportedOperationException();
271 }
272
273 public Collection<V> values() {
274 throw new UnsupportedOperationException();
275 }
276
277 @Override
278 public int hashCode() {
279 throw new UnsupportedOperationException();
280 }
281
282 @Override
283 public boolean equals(Object obj) {
284 throw new UnsupportedOperationException();
285 }
286 }
287
288 static class SnapshotMapEntry<K, V> implements Entry<K, V> {
289
290 private final K key;
291 private final V value;
292
293 public SnapshotMapEntry(K key, V value) {
294 this.key = key;
295 this.value = value;
296 }
297
298 public K getKey() {
299 return key;
300 }
301
302 public V getValue() {
303 return value;
304 }
305
306 public V setValue(V value) {
307 throw new UnsupportedOperationException();
308 }
309
310 @Override
311 public int hashCode() {
312 return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
313 }
314
315 @Override
316 public boolean equals(Object obj) {
317 if (!(obj instanceof Entry))
318 return false;
319 Entry<?, ?> e = (Entry<?, ?>)obj;
320 return (
321 (key == null ? e.getKey() == null : key.equals(e.getKey())) &&
322 (value == null ? e.getValue() == null : value.equals(e.getValue()))
323 );
324 }
325 }
326 }