1 package fr.ifremer.quadrige2.ui.swing.common.table;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 import com.google.common.base.Preconditions;
28 import com.google.common.collect.Lists;
29 import com.google.common.collect.Sets;
30 import fr.ifremer.quadrige2.ui.swing.common.model.AbstractBeanUIModel;
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 import java.beans.PropertyChangeEvent;
36 import java.beans.PropertyChangeListener;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.Set;
41
42
43
44
45
46
47
48
49
50 public abstract class AbstractTableUIModel<B, R extends AbstractRowUIModel, M extends AbstractTableUIModel<B, R, M>>
51 extends AbstractBeanUIModel<B, M> {
52
53 private static final long serialVersionUID = 1L;
54
55 private static final Log LOG = LogFactory.getLog(AbstractTableUIModel.class);
56
57
58 public static final String PROPERTY_ROWS = "rows";
59
60
61 public static final String PROPERTY_BEANS_LOADED = "rowsLoaded";
62
63
64 public static final String PROPERTY_SINGLE_ROW_SELECTED = "singleSelectedRow";
65
66
67 public static final String PROPERTY_SELECTED_ROWS = "selectedRows";
68
69
70 public static final String PROPERTY_ROWS_IN_ERROR = "rowsInError";
71
72
73 public static final String PROPERTY_ROWS_ADDED = "rowsAdded";
74
75
76 public static final String PROPERTY_ROWS_DELETED = "rowsDeleted";
77
78 protected List<R> rows;
79
80 protected R singleSelectedRow;
81
82 protected Set<R> selectedRows;
83
84 protected Set<R> rowsInError;
85
86 private AbstractTableModel tableModel;
87
88
89
90
91 protected AbstractTableUIModel() {
92 super(null, null);
93
94 rows = Lists.newArrayList();
95 selectedRows = Sets.newHashSet();
96
97 addPropertyChangeListener(PROPERTY_ROWS_IN_ERROR, new PropertyChangeListener() {
98
99 @Override
100 public void propertyChange(PropertyChangeEvent evt) {
101 if (LOG.isDebugEnabled()) {
102 LOG.debug(PROPERTY_ROWS_IN_ERROR + " changed " + rowsInError.size());
103 }
104 setValid(CollectionUtils.isEmpty(rowsInError));
105 }
106 });
107 setRowsInError(Sets.<R>newHashSet());
108 }
109
110
111
112
113
114
115 public AbstractTableUIModel getInstance() {
116 return this;
117 }
118
119
120
121
122
123
124 public void setInstance(AbstractTableUIModel model) {
125
126 }
127
128
129
130
131
132
133 public AbstractTableModel getTableModel() {
134 return tableModel;
135 }
136
137
138
139
140
141
142 public void setTableModel(AbstractTableModel tableModel) {
143 this.tableModel = tableModel;
144 }
145
146
147
148
149
150
151 @Override
152 protected final B newBean() {
153 return null;
154 }
155
156
157
158
159
160
161 public List<R> getRows() {
162 return rows;
163 }
164
165
166
167
168
169
170 public void setRows(List<R> rows) {
171 if (rows == null) {
172 this.rows = Lists.newArrayList();
173 } else {
174 this.rows = Lists.newArrayList(rows);
175 }
176 onRowsChanged();
177 }
178
179
180
181
182
183
184 public void addRow(R row) {
185 addRows(Collections.singletonList(row));
186 }
187
188
189
190
191
192
193 public void addRows(List<R> rows) {
194 if (CollectionUtils.isEmpty(rows)) {
195 return;
196 }
197 this.rows.addAll(rows);
198 firePropertyChange(PROPERTY_ROWS_ADDED, null, rows);
199 onRowsChanged();
200 }
201
202
203
204
205
206
207 public void insertRowAfterSelected(R row) {
208 if (row == null) {
209 return;
210 }
211 if (singleSelectedRow == null || rows.indexOf(singleSelectedRow) + 1 >= rows.size()) {
212 addRow(row);
213 } else {
214 rows.add(rows.indexOf(singleSelectedRow) + 1, row);
215 firePropertyChange(PROPERTY_ROWS_ADDED, null, Collections.singletonList(row));
216 onRowsChanged();
217 }
218
219 }
220
221 private void onRowsChanged() {
222 rowsInError.clear();
223 if (CollectionUtils.isNotEmpty(rows)) {
224 for (R row : rows) {
225 if (!row.isValid()) {
226 rowsInError.add(row);
227 }
228 }
229 }
230 setRowsInError(rowsInError);
231
232
233 firePropertyChange(PROPERTY_ROWS, null, rows);
234
235 populateSelectedRows();
236 }
237
238
239 @Override
240 public void setBean(B bean) {
241 setBeans(Collections.singletonList(bean));
242 }
243
244
245
246
247
248
249 public void setBeans(Collection<B> beans) {
250 setBeans(beans, null);
251 }
252
253
254
255
256
257
258
259 public void setBeans(Collection<B> beans, Boolean calculated) {
260 List<R> newRows = convertBeans(beans, calculated);
261 setRows(newRows);
262 firePropertyChange(PROPERTY_BEANS_LOADED, null, rows);
263 }
264
265
266
267
268
269
270 public void addBean(B bean) {
271 addBeans(Collections.singletonList(bean));
272 }
273
274
275
276
277
278
279
280 public void addBean(B bean, Boolean calculated) {
281 addBeans(Collections.singletonList(bean), calculated);
282 }
283
284
285
286
287
288
289 public void addBeans(List<B> beans) {
290 addBeans(beans, null);
291 }
292
293
294
295
296
297
298
299 public void addBeans(List<B> beans, Boolean calculated) {
300 List<R> newRows = convertBeans(beans, calculated);
301 addRows(newRows);
302 }
303
304
305
306
307
308
309 public R addNewRow() {
310 return addNewRow(null);
311 }
312
313
314
315
316
317
318
319 public R addNewRow(B bean) {
320 R row = convertBean(bean, null);
321 addRow(row);
322 return row;
323 }
324
325
326
327
328
329
330 public R insertNewRowAfterSelected() {
331 R row = convertBean(null, null);
332 insertRowAfterSelected(row);
333 return row;
334 }
335
336 private List<R> convertBeans(Collection<B> beans, Boolean calculated) {
337 List<R> newRows = Lists.newArrayList();
338 if (CollectionUtils.isNotEmpty(beans)) {
339 for (B bean : beans) {
340 R row = convertBean(bean, calculated);
341 if (row != null) {
342 newRows.add(row);
343 }
344 }
345 }
346 return newRows;
347 }
348
349 @SuppressWarnings("unchecked")
350 private R convertBean(B bean, Boolean calculated) {
351 R row = null;
352 if (getTableModel() != null) {
353 row = (R) getTableModel().createNewRow();
354 }
355 if (row != null) {
356 if (bean != null) {
357 row.fromBean(bean);
358 row.setValid(true);
359 } else {
360 row.setValid(false);
361 }
362 if (calculated != null) {
363 row.setCalculated(calculated);
364 }
365 } else {
366 if (LOG.isWarnEnabled()) {
367 LOG.warn("convertBean can't create a new row! check the underlying table model and its createNewRow method");
368 }
369 }
370 return row;
371 }
372
373
374
375
376
377
378 public List<B> getBeans() {
379 List<B> beans = Lists.newArrayList();
380 if (CollectionUtils.isNotEmpty(rows)) {
381 for (R row : rows) {
382 beans.add(convertRow(row));
383 }
384 }
385 return beans;
386 }
387
388 @SuppressWarnings("unchecked")
389 private B convertRow(R row) {
390 return (B) row.toBean();
391 }
392
393
394
395
396
397
398 public int getRowCount() {
399 return rows.size();
400 }
401
402
403
404
405
406
407 public Set<R> getRowsInError() {
408 return rowsInError;
409 }
410
411
412
413
414
415
416 public final void setRowsInError(Set<R> rowsInError) {
417 this.rowsInError = rowsInError;
418 firePropertyChange(PROPERTY_ROWS_IN_ERROR, null, null);
419 }
420
421
422
423
424
425
426 public void addRowInError(R row) {
427 rowsInError.add(row);
428 firePropertyChange(PROPERTY_ROWS_IN_ERROR, null, null);
429 }
430
431
432
433
434
435
436 public void removeRowInError(R row) {
437 rowsInError.remove(row);
438 firePropertyChange(PROPERTY_ROWS_IN_ERROR, null, null);
439 }
440
441
442
443
444
445
446 public boolean hasNoRowInError() {
447 return CollectionUtils.isEmpty(rowsInError);
448 }
449
450
451
452
453
454
455 public boolean hasAllRowMandatoryValid() {
456 for (R row: rows) {
457 if (!row.isMandatoryValid()) return false;
458 }
459 return true;
460 }
461
462
463
464
465
466
467 public Set<R> getSelectedRows() {
468 return selectedRows;
469 }
470
471
472
473
474
475
476 public List<B> getSelectedBeans() {
477 List<B> beans = Lists.newArrayList();
478 if (CollectionUtils.isNotEmpty(selectedRows)) {
479 for (R row : selectedRows) {
480 beans.add(convertRow(row));
481 }
482 }
483 return beans;
484 }
485
486
487
488
489 public void populateSelectedRows() {
490 int previousHashCode = selectedRows.hashCode();
491 selectedRows = Sets.newHashSet();
492 if (CollectionUtils.isNotEmpty(rows)) {
493 for (R row : rows) {
494 if (row.isSelected()) {
495 selectedRows.add(row);
496 }
497 }
498 }
499 if (previousHashCode != selectedRows.hashCode()) {
500 firePropertyChange(PROPERTY_SELECTED_ROWS, null, selectedRows);
501 }
502 }
503
504
505
506
507
508
509 public void deleteRow(R rowToDelete) {
510 deleteRows(Collections.singletonList(rowToDelete));
511 }
512
513
514
515
516
517
518 public void deleteRows(List<R> rowsToDelete) {
519 if (CollectionUtils.isNotEmpty(rows) && rowsToDelete != null) {
520 Set<R> rowSet = Sets.newHashSet(rowsToDelete);
521 rowsInError.removeAll(rowSet);
522 firePropertyChange(PROPERTY_ROWS_IN_ERROR, null, null);
523 rows.removeAll(rowSet);
524 firePropertyChange(PROPERTY_ROWS_DELETED, null, rowSet);
525 onRowsChanged();
526 }
527 }
528
529
530
531
532 public void deleteSelectedRows() {
533 if (CollectionUtils.isNotEmpty(rows)) {
534 rowsInError.removeAll(selectedRows);
535 firePropertyChange(PROPERTY_ROWS_IN_ERROR, null, null);
536 rows.removeAll(selectedRows);
537 firePropertyChange(PROPERTY_ROWS_DELETED, null, selectedRows);
538 onRowsChanged();
539 }
540 }
541
542
543
544
545
546
547
548 @SuppressWarnings("unchecked")
549 public void updateBean(R oldRow, B newRowBean) {
550 Preconditions.checkNotNull(oldRow);
551 Preconditions.checkState(rows.contains(oldRow));
552 Preconditions.checkNotNull(newRowBean);
553
554 oldRow.fromBean(newRowBean);
555 }
556
557
558
559
560
561
562 public R getSingleSelectedRow() {
563 return singleSelectedRow;
564 }
565
566
567
568
569
570
571 public void setSingleSelectedRow(R singleSelectedRow) {
572 R oldValue = getSingleSelectedRow();
573 this.singleSelectedRow = singleSelectedRow;
574 firePropertyChange(PROPERTY_SINGLE_ROW_SELECTED, oldValue, singleSelectedRow);
575 }
576
577 }