1 package fr.ifremer.tutti.ui.swing.content.operation.catches.species.split;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.collect.Maps;
26 import fr.ifremer.tutti.persistence.entities.data.SampleCategory;
27 import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
28 import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModelEntry;
29 import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
30 import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue;
31 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.EditSpeciesBatchPanelUI;
32 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.SpeciesOrBenthosBatchUISupport;
33 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchRowModel;
34 import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor;
35 import fr.ifremer.tutti.ui.swing.util.TuttiUI;
36 import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableUIHandler;
37 import jaxx.runtime.validator.swing.SwingValidator;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.jdesktop.swingx.JXTable;
41 import org.jdesktop.swingx.table.DefaultTableColumnModelExt;
42
43 import javax.swing.DefaultComboBoxModel;
44 import javax.swing.JComboBox;
45 import javax.swing.JComponent;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.beans.PropertyChangeEvent;
49 import java.beans.PropertyChangeListener;
50 import java.io.Serializable;
51 import java.util.ArrayList;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Objects;
55 import java.util.Optional;
56
57
58
59
60
61
62
63 public class SplitSpeciesBatchUIHandler extends AbstractTuttiTableUIHandler<SplitSpeciesBatchRowModel, SplitSpeciesBatchUIModel, SplitSpeciesBatchUI> {
64
65
66 private static final Log log =
67 LogFactory.getLog(SplitSpeciesBatchUIHandler.class);
68
69 protected final PropertyChangeListener PROPERTY_CATEGORY_CHANGED_LISTENER = new PropertyChangeListener() {
70
71 @Override
72 public void propertyChange(PropertyChangeEvent evt) {
73
74 SplitSpeciesBatchUIModel source =
75 (SplitSpeciesBatchUIModel) evt.getSource();
76
77
78 source.setSelectedCategory(null);
79
80
81 List<SampleCategoryModelEntry> data = (List<SampleCategoryModelEntry>) evt.getNewValue();
82 SplitSpeciesBatchUIHandler.this.ui.getCategoryComboBox().setModel(new DefaultComboBoxModel(data.toArray()));
83 }
84 };
85
86 protected final PropertyChangeListener PROPERTY_SELECTED_CATEGORY_CHANGED_LISTENER = new PropertyChangeListener() {
87
88 @Override
89 public void propertyChange(PropertyChangeEvent evt) {
90
91 SplitSpeciesBatchUIModel source =
92 (SplitSpeciesBatchUIModel) evt.getSource();
93
94
95 source.setSampleWeight(null);
96
97 SampleCategoryModelEntry newValue =
98 (SampleCategoryModelEntry) evt.getNewValue();
99 generateTableModel(newValue);
100 }
101 };
102
103 protected final ActionListener CATEGORY_ACTION_LISTENER = new ActionListener() {
104
105 public void actionPerformed(ActionEvent e) {
106 JComboBox comboBox = (JComboBox) e.getSource();
107 getModel().setSelectedCategory((SampleCategoryModelEntry) comboBox.getSelectedItem());
108 }
109 };
110
111 protected final PropertyChangeListener PROPERTY_WEIGHT_CHANGED_LISTENER = new PropertyChangeListener() {
112
113 @Override
114 public void propertyChange(PropertyChangeEvent evt) {
115 if (evt.getNewValue() != null) {
116 ((SplitSpeciesBatchRowModel) evt.getSource()).setSelected(true);
117 }
118 }
119 };
120
121
122
123 public SplitSpeciesBatchUIHandler() {
124 super(SplitSpeciesBatchRowModel.PROPERTY_SELECTED,
125 SplitSpeciesBatchRowModel.PROPERTY_CATEGORY_VALUE,
126 SplitSpeciesBatchRowModel.PROPERTY_WEIGHT);
127 }
128
129
130
131
132
133 @Override
134 public SplitSpeciesBatchTableModel getTableModel() {
135 return (SplitSpeciesBatchTableModel) getTable().getModel();
136 }
137
138 @Override
139 public JXTable getTable() {
140 return ui.getTable();
141 }
142
143 @Override
144 protected boolean isRowValid(SplitSpeciesBatchRowModel row) {
145 return row.isSelected();
146 }
147
148 @Override
149 protected void saveSelectedRowIfRequired(TuttiBeanMonitor<SplitSpeciesBatchRowModel> rowMonitor,
150 SplitSpeciesBatchRowModel row) {
151 if (rowMonitor.wasModified()) {
152
153 if (row.isValid()) {
154 if (log.isInfoEnabled()) {
155 log.info("Change row that was modified and valid");
156 }
157 }
158
159 rowMonitor.clearModified();
160 }
161 }
162
163 @Override
164 protected void onAfterSelectedRowChanged(int oldRowIndex,
165 SplitSpeciesBatchRowModel oldRow,
166 int newRowIndex,
167 SplitSpeciesBatchRowModel newRow) {
168 super.onAfterSelectedRowChanged(oldRowIndex, oldRow, newRowIndex, newRow);
169 if (newRow != null) {
170
171
172 recomputeRowValidState(newRow);
173
174
175 computeSampleWeight();
176 }
177 }
178
179 @Override
180 protected void onRowModified(int rowIndex,
181 SplitSpeciesBatchRowModel row,
182 String propertyName,
183 Object oldValue,
184 Object newValue) {
185
186
187 recomputeRowValidState(row);
188
189
190 computeSampleWeight();
191 }
192
193
194
195
196
197 @Override
198 public SwingValidator<SplitSpeciesBatchUIModel> getValidator() {
199 return ui.getValidator();
200 }
201
202 @Override
203 public void beforeInit(SplitSpeciesBatchUI ui) {
204 super.beforeInit(ui);
205 SampleCategoryModel sampleCategoryModel = getDataContext().getSampleCategoryModel();
206
207 SpeciesOrBenthosBatchUISupport speciesOrBenthosBatchUISupport = ui.getContextValue(SpeciesOrBenthosBatchUISupport.class, ui.getSpeciesOrBenthosContext());
208
209 SplitSpeciesBatchUIModel model = new SplitSpeciesBatchUIModel(speciesOrBenthosBatchUISupport, sampleCategoryModel);
210
211 ui.setContextValue(model);
212 }
213
214 @Override
215 public void afterInit(SplitSpeciesBatchUI ui) {
216
217 initUI(ui);
218
219 SplitSpeciesBatchUIModel model = getModel();
220
221
222 model.addPropertyChangeListener(SplitSpeciesBatchUIModel.PROPERTY_CATEGORY, PROPERTY_CATEGORY_CHANGED_LISTENER);
223
224
225
226 model.addPropertyChangeListener(SplitSpeciesBatchUIModel.PROPERTY_SELECTED_CATEGORY, PROPERTY_SELECTED_CATEGORY_CHANGED_LISTENER);
227
228 ui.getCategoryComboBox().setRenderer(newListCellRender(SampleCategoryModelEntry.class));
229
230 ui.getCategoryComboBox().addActionListener(CATEGORY_ACTION_LISTENER);
231
232 generateTableModel(null);
233
234 initTable(getTable());
235
236 listenValidatorValid(ui.getValidator(), model);
237 }
238
239 @Override
240 protected JComponent getComponentToFocus() {
241 return getUI().getCategoryComboBox();
242 }
243
244 @Override
245 public void onCloseUI() {
246 if (log.isDebugEnabled()) {
247 log.debug("closing: " + ui);
248 }
249
250
251 ui.getValidator().setBean(null);
252
253 clearValidators();
254
255
256 getModel().setValid(false);
257 getModel().setSelectedCategory(null);
258
259 EditSpeciesBatchPanelUI parent = getParentContainer(EditSpeciesBatchPanelUI.class);
260 parent.switchToEditBatch();
261
262 }
263
264
265
266
267
268 public void editBatch(SpeciesBatchRowModel batch) {
269
270
271 List<SampleCategoryModelEntry> categories = new ArrayList<>();
272
273 SplitSpeciesBatchUIModel model = getModel();
274
275 SampleCategoryModelEntry bestSampleCategory = null;
276 if (batch != null) {
277
278
279 SampleCategoryModel sampleCategoryModel = getModel().getSampleCategoryModel();
280
281
282 categories.addAll(sampleCategoryModel.getCategory());
283
284 SampleCategory<?> lastCategory = batch.getFinestCategory();
285
286 Objects.requireNonNull(lastCategory, "Can't split a species batch with no sample category.");
287
288 int firstOrder = lastCategory.getCategoryDef().getOrder();
289
290 for (Integer sampleCategoryId : sampleCategoryModel.getSamplingOrder()) {
291 SampleCategory<?> sampleCategory = batch.getSampleCategoryById(sampleCategoryId);
292 int order = sampleCategory.getCategoryDef().getOrder();
293 if (order < firstOrder || sampleCategory.isValid()) {
294
295
296
297 categories.remove(sampleCategory.getCategoryDef());
298 }
299 }
300
301 bestSampleCategory = model.getSpeciesOrBenthosBatchUISupport().getBestFirstSampleCategory(categories, batch.getSpecies());
302 }
303
304
305 ui.getValidator().setBean(model);
306
307 model.setSampleWeight(null);
308 model.setCategory(categories);
309 model.setSelectedCategory(bestSampleCategory);
310
311
312 model.setBatch(batch);
313 }
314
315 public void editBatch(SpeciesBatchRowModel batch, int sampleCategoryId) {
316
317 Objects.requireNonNull(batch);
318 Objects.requireNonNull(sampleCategoryId);
319
320 List<SpeciesBatchRowModel> rows = batch.getChildBatch();
321 Objects.requireNonNull(rows);
322
323
324 List<SampleCategoryModelEntry> categories = new ArrayList<>();
325
326
327 SampleCategoryModel sampleCategoryModel = getModel().getSampleCategoryModel();
328
329
330 SampleCategoryModelEntry selectedCategory = sampleCategoryModel.getCategoryById(sampleCategoryId);
331 categories.add(selectedCategory);
332
333 SplitSpeciesBatchUIModel model = getModel();
334
335
336 ui.getValidator().setBean(model);
337
338 model.setSampleWeight(null);
339 model.setCategory(categories);
340 model.setSelectedCategory(selectedCategory);
341
342
343 model.setBatch(batch);
344
345
346 Map<Serializable, SplitSpeciesBatchRowModel> rowsByValue = Maps.uniqueIndex(model.getRows(), SplitSpeciesBatchRowModel::getCategoryValue);
347 for (SpeciesBatchRowModel row : rows) {
348
349 SampleCategory<?> sampleCategory = row.getSampleCategoryById(sampleCategoryId);
350 Serializable categoryValue = sampleCategory.getCategoryValue();
351 SplitSpeciesBatchRowModel splitRow = rowsByValue.get(categoryValue);
352 splitRow.setWeight(sampleCategory.getCategoryWeight());
353 splitRow.setSelected(true);
354 splitRow.setEditable(false);
355 }
356
357 computeSampleWeight();
358
359 getTableModel().fireTableDataChanged();
360 }
361
362
363
364
365
366 protected void computeSampleWeight() {
367
368 Optional<Float> result = getTableModel().getTotalWeight();
369
370
371
372
373
374
375
376
377
378
379
380
381 getModel().setSampleWeight(result.orElse(null));
382 }
383
384 protected void generateTableModel(SampleCategoryModelEntry category) {
385
386
387 getModel().setRows(null);
388
389 Caracteristic data = null;
390
391 JXTable table = getTable();
392
393 DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt();
394
395 {
396
397 addBooleanColumnToModel(columnModel, SplitSpeciesBatchTableModel.SELECTED, table);
398 }
399
400 boolean editableCategoryValue = false;
401
402 log.debug("category " + category);
403 if (category != null) {
404 log.debug("category " + category.getLabel());
405 if (!category.getCaracteristic().isQualitativeValueEmpty()) {
406
407
408 data = category.getCaracteristic();
409
410 log.debug("data " + data);
411
412 } else {
413 editableCategoryValue = true;
414 addFloatColumnToModel(columnModel,
415 SplitSpeciesBatchTableModel.EDITABLE_CATEGORY_VALUE,
416 TuttiUI.DECIMAL1_PATTERN,
417 table);
418 }
419
420 if (data != null) {
421
422 if (log.isDebugEnabled()) {
423 log.debug("Got " + data.sizeQualitativeValue() + " qualitative data to add");
424 }
425 addColumnToModel(columnModel,
426 null,
427 newTableCellRender(CaracteristicQualitativeValue.class),
428 SplitSpeciesBatchTableModel.READ_ONLY_CATEGORY_VALUE);
429 }
430 {
431
432 addFloatColumnToModel(columnModel,
433 SplitSpeciesBatchTableModel.WEIGHT,
434 getConfig().getSpeciesWeightUnit(),
435 table);
436 }
437 }
438
439
440 SplitSpeciesBatchTableModel tableModel = new SplitSpeciesBatchTableModel(columnModel,
441 getModel(),
442 editableCategoryValue,
443 getModel().isSplitMode());
444
445
446 uninstallTableSaveOnRowChangedSelectionListener();
447 uninstallTableKeyListener(getTable());
448
449 if (log.isDebugEnabled()) {
450 log.debug("Install new table model " + tableModel);
451 }
452 table.setModel(tableModel);
453 table.setColumnModel(columnModel);
454
455
456 installTableSaveOnRowChangedSelectionListener();
457 installTableKeyListener(columnModel, table);
458
459
460
461 List<SplitSpeciesBatchRowModel> rows = new ArrayList<>();
462
463 if (data != null) {
464
465
466 for (CaracteristicQualitativeValue qualitativeValue : data.getQualitativeValue()) {
467 log.debug("QV: " + qualitativeValue);
468 if (log.isDebugEnabled()) {
469 log.debug("Add QV: " + qualitativeValue);
470 }
471 SplitSpeciesBatchRowModel newRow = tableModel.createNewRow();
472 newRow.setCategoryValue(qualitativeValue);
473 newRow.addPropertyChangeListener(SplitSpeciesBatchRowModel.PROPERTY_WEIGHT, PROPERTY_WEIGHT_CHANGED_LISTENER);
474 rows.add(newRow);
475 }
476 }
477
478 if (log.isDebugEnabled()) {
479 log.debug("Will add " + rows.size() + " rows in table model " +
480 "(can add a first empty row? " + editableCategoryValue + ").");
481 }
482
483 getModel().setRows(rows);
484 }
485
486 }