1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.model;
20
21 import java.io.Externalizable;
22 import java.io.IOException;
23 import java.io.ObjectInput;
24 import java.io.ObjectOutput;
25
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.LinkedHashSet;
29 import java.util.Iterator;
30 import java.util.NoSuchElementException;
31 import java.util.Set;
32
33 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
34
35
36
37
38
39
40
41
42
43
44
45
46 public final class RowKeySetImpl extends RowKeySet implements Externalizable
47 {
48
49
50
51 public RowKeySetImpl()
52 {
53 this(false);
54 }
55
56
57
58
59
60 public RowKeySetImpl(boolean addAll)
61 {
62 _default = addAll;
63 _set = Collections.emptySet();
64 _model = null;
65 }
66
67
68
69
70
71 @Override
72 public boolean contains(Object rowKey)
73 {
74 return _isSelected(rowKey);
75 }
76
77
78
79
80
81 @Override
82 public boolean add(Object rowKey)
83 {
84 return _setSelected(rowKey, true);
85 }
86
87
88
89
90
91 @Override
92 public boolean remove(Object rowKey)
93 {
94 return _setSelected(rowKey, false);
95 }
96
97
98
99
100
101
102 @Override
103 public boolean invert(Object rowKey)
104 {
105 Set<Object> set = _getSet(true);
106 if (!set.add(rowKey))
107 {
108 set.remove(rowKey);
109 return _default;
110 }
111 else
112 {
113 return !_default;
114 }
115 }
116
117
118
119
120
121
122
123 @Override
124 public void invertAll()
125 {
126 _default = !_default;
127 }
128
129
130
131
132
133 @Override
134 public void addAll()
135 {
136 _selectAll(true);
137 }
138
139 @Override
140 public boolean isContainedByDefault()
141 {
142 return _default;
143 }
144
145
146
147
148
149 @Override
150 public void clear()
151 {
152 _selectAll(false);
153 }
154
155 @Override
156 public boolean removeAll(Collection<?> c)
157 {
158 if (c instanceof RowKeySetImpl)
159 {
160 RowKeySetImpl other = (RowKeySetImpl) c;
161 if (other._default)
162 {
163
164
165
166 return _processAll(other, false);
167 }
168 }
169 return super.removeAll(c);
170 }
171
172 @Override
173 public boolean addAll(Collection<? extends Object> c)
174 {
175 if (c instanceof RowKeySetImpl)
176 {
177 RowKeySetImpl other = (RowKeySetImpl) c;
178 if (other._default)
179 {
180
181
182
183 return _processAll(other, true);
184 }
185 }
186 return super.addAll(c);
187 }
188
189 private boolean _processAll(RowKeySetImpl other, boolean addAll)
190 {
191 Set<Object> set = _getSet(false);
192 Set<Object> otherSet = other._getSet(false);
193 if (_default == addAll)
194 {
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210 return set.retainAll(otherSet);
211 }
212 else
213 {
214
215
216
217
218
219
220
221
222
223
224
225
226
227 _default = addAll;
228
229
230 otherSet = _clone(otherSet);
231
232 otherSet.removeAll(set);
233 _set = otherSet;
234 return true;
235 }
236 }
237
238
239
240
241
242
243
244
245
246
247 @Override
248 public final void setCollectionModel(CollectionModel model)
249 {
250 _model = model;
251 if (model == null)
252 {
253
254
255 _LOG.fine("COLLECTIONMODEL_SET_NULL");
256 }
257 }
258
259
260
261
262
263 @Override
264 public int getSize()
265 {
266 return _getSize(false);
267 }
268
269 @Override
270 public int size()
271 {
272 return _getSize(true);
273 }
274
275 @Override
276 public boolean isEmpty()
277 {
278 return (getSize() == 0);
279 }
280
281
282
283
284
285
286
287 @Override
288 public Iterator<Object> iterator()
289 {
290 return _default ? _getNotInSetRowKeyIterator() : _getInSetRowKeyIterator();
291 }
292
293
294
295
296
297
298
299
300
301 private int _getSize(boolean fetchAll)
302 {
303 int setSize = _getSet(false).size();
304 if (_default)
305 {
306 CollectionModel model = getCollectionModel();
307
308
309 int total = model.getRowCount();
310 if (total < 0)
311 {
312 if (fetchAll)
313 {
314
315
316
317
318 total = ModelUtils.getRowCount(model);
319 }
320 else
321 return -1;
322 }
323 return total - setSize;
324 }
325 return setSize;
326 }
327
328
329
330
331
332
333
334 private boolean _setSelected(Object rowKey, boolean isSelected)
335 {
336 if (isSelected == _default)
337 {
338 if (!_set.isEmpty())
339 {
340 return _set.remove(rowKey);
341 }
342 return false;
343 }
344 else
345 {
346 return _getSet(true).add(rowKey);
347 }
348 }
349
350 @SuppressWarnings("unchecked")
351 private Iterator<Object> _getNotInSetRowKeyIterator()
352 {
353 CollectionModel table = getCollectionModel();
354 final Iterator<Object> rowKeyIterator = ModelUtils.getRowKeyIterator(table);
355 final Set<Object> set = _getSet(false);
356 Iterator<Object> iter = new Iterator<Object>()
357 {
358 public Object next()
359 {
360 if (!hasNext())
361 throw new NoSuchElementException();
362 _current = _next;
363 _next = _next();
364 _first = false;
365 return _current;
366 }
367
368 public void remove()
369 {
370 if (_current == null)
371 throw new IllegalStateException(_LOG.getMessage(
372 "NO_ELEMENT_TO_REMOVE"));
373 Set<Object> mutable = _getSet(true);
374
375
376 mutable.add(_current);
377 _current = null;
378 }
379
380 public boolean hasNext()
381 {
382 return (_next != null || _first);
383 }
384
385 private Object _next()
386 {
387 while(rowKeyIterator.hasNext())
388 {
389 Object rowKey = rowKeyIterator.next();
390 if (!set.contains(rowKey))
391 return rowKey;
392 }
393 return null;
394 }
395
396 private boolean _first = true;
397 private Object _next = null;
398 private Object _current = null;
399 };
400
401 iter.next();
402 return iter;
403 }
404
405 private Iterator<Object> _getInSetRowKeyIterator()
406 {
407 return _getSet(false).iterator();
408 }
409
410 private void _selectAll(boolean isSelected)
411 {
412 _default = isSelected;
413 _set = Collections.emptySet();
414 }
415
416 private Set<Object> _getSet(boolean create)
417 {
418 if (create && (_set == Collections.emptySet()))
419 {
420 _set = _createSet(10);
421 }
422 return _set;
423 }
424
425 private Set<Object> _createSet(int sz)
426 {
427
428 return new LinkedHashSet<Object>(sz);
429 }
430
431 private boolean _isSelected(Object rowKey)
432 {
433 Set<Object> set = _getSet(false);
434 boolean isInSet = set.contains(rowKey);
435 return isInSet ^ _default;
436 }
437
438
439 public void writeExternal(ObjectOutput out) throws IOException
440 {
441 out.writeBoolean(_default);
442 Set<Object> set = _getSet(false);
443 int sz = set.size();
444 out.writeInt(sz);
445 Iterator<Object> iter = set.iterator();
446 for(int i=0; i<sz; i++)
447 {
448 out.writeObject(iter.next());
449 }
450 }
451
452
453 public void readExternal(ObjectInput in)
454 throws IOException, ClassNotFoundException
455 {
456 _default = in.readBoolean();
457 int sz = in.readInt();
458 if (sz>0)
459 {
460 _set = _createSet(sz);
461 for(int i=0; i<sz; i++)
462 {
463 _set.add(in.readObject());
464 }
465 }
466 else
467 _set = Collections.emptySet();
468 }
469
470
471
472
473
474
475 @Override
476 public RowKeySetImpl clone()
477 {
478 RowKeySetImpl clone = (RowKeySetImpl) super.clone();
479 Set<Object> set = _getSet(false);
480 clone._set = _clone(set);
481 return clone;
482 }
483
484
485
486
487
488
489
490 @SuppressWarnings("unchecked")
491 private <T> Set<T> _clone(Set<T> other)
492 {
493 if (other.isEmpty())
494 return Collections.emptySet();
495 else
496 return (Set<T>) ((LinkedHashSet<T>) other).clone();
497 }
498
499
500
501
502
503
504 @Override
505 protected CollectionModel getCollectionModel()
506 {
507
508
509
510
511 return _model;
512 }
513
514
515 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(RowKeySetImpl.class);
516
517 private boolean _default;
518 private Set<Object> _set;
519 private transient CollectionModel _model;
520 private static final long serialVersionUID = 1L;
521 }