1 package fr.ifremer.tutti.ui.swing.content.protocol;
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.base.Preconditions;
26 import com.google.common.base.Predicate;
27 import com.google.common.collect.HashMultimap;
28 import com.google.common.collect.ImmutableMap;
29 import com.google.common.collect.Lists;
30 import com.google.common.collect.Maps;
31 import com.google.common.collect.Multimap;
32 import com.google.common.collect.Sets;
33 import fr.ifremer.tutti.persistence.entities.TuttiEntities;
34 import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
35 import fr.ifremer.tutti.persistence.entities.data.FishingOperations;
36 import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
37 import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModelEntry;
38 import fr.ifremer.tutti.persistence.entities.protocol.CalcifiedPiecesSamplingDefinition;
39 import fr.ifremer.tutti.persistence.entities.protocol.CaracteristicMappingRow;
40 import fr.ifremer.tutti.persistence.entities.protocol.CaracteristicType;
41 import fr.ifremer.tutti.persistence.entities.protocol.MaturityCaracteristic;
42 import fr.ifremer.tutti.persistence.entities.protocol.OperationFieldMappingRow;
43 import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol;
44 import fr.ifremer.tutti.persistence.entities.protocol.Strata;
45 import fr.ifremer.tutti.persistence.entities.protocol.SubStrata;
46 import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol;
47 import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocols;
48 import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
49 import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue;
50 import fr.ifremer.tutti.persistence.entities.referential.Species;
51 import fr.ifremer.tutti.persistence.entities.referential.Speciess;
52 import fr.ifremer.tutti.persistence.entities.referential.TuttiLocation;
53 import fr.ifremer.tutti.service.DecoratorService;
54 import fr.ifremer.tutti.service.TuttiDecorator;
55 import fr.ifremer.tutti.ui.swing.content.home.actions.CloneProtocolAction;
56 import fr.ifremer.tutti.ui.swing.content.home.actions.EditProtocolAction;
57 import fr.ifremer.tutti.ui.swing.content.home.actions.ImportProtocolAction;
58 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchRowHelper;
59 import fr.ifremer.tutti.ui.swing.content.protocol.calcifiedpiecessampling.CalcifiedPiecesSamplingEditorRowModel;
60 import fr.ifremer.tutti.ui.swing.content.protocol.calcifiedpiecessampling.CalcifiedPiecesSamplingEditorTableModel;
61 import fr.ifremer.tutti.ui.swing.content.protocol.calcifiedpiecessampling.CalcifiedPiecesSamplingEditorUI;
62 import fr.ifremer.tutti.ui.swing.content.protocol.rtp.RtpCellEditor;
63 import fr.ifremer.tutti.ui.swing.content.protocol.rtp.RtpCellRenderer;
64 import fr.ifremer.tutti.ui.swing.content.protocol.zones.tree.AvailableStratasTreeModel;
65 import fr.ifremer.tutti.ui.swing.content.protocol.zones.tree.ZonesTreeModel;
66 import fr.ifremer.tutti.ui.swing.content.protocol.zones.tree.node.StrataNode;
67 import fr.ifremer.tutti.ui.swing.util.AbstractTuttiUIHandler;
68 import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil;
69 import jaxx.runtime.SwingUtil;
70 import jaxx.runtime.swing.JAXXWidgetUtil;
71 import jaxx.runtime.swing.editor.bean.BeanDoubleList;
72 import jaxx.runtime.swing.editor.bean.BeanDoubleListModel;
73 import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox;
74 import jaxx.runtime.swing.editor.bean.BeanUIUtil;
75 import jaxx.runtime.validator.swing.SwingValidator;
76 import org.apache.commons.collections4.CollectionUtils;
77 import org.apache.commons.lang3.StringUtils;
78 import org.apache.commons.logging.Log;
79 import org.apache.commons.logging.LogFactory;
80 import org.jdesktop.swingx.JXTable;
81 import org.jdesktop.swingx.autocomplete.ComboBoxCellEditor;
82 import org.jdesktop.swingx.autocomplete.ObjectToStringConverter;
83 import org.jdesktop.swingx.decorator.HighlightPredicate;
84 import org.jdesktop.swingx.decorator.Highlighter;
85 import org.jdesktop.swingx.table.DefaultTableColumnModelExt;
86 import org.jdesktop.swingx.table.TableColumnExt;
87 import org.nuiton.decorator.Decorator;
88 import org.nuiton.jaxx.application.swing.AbstractApplicationUIHandler;
89 import org.nuiton.jaxx.application.swing.table.ColumnIdentifier;
90 import org.nuiton.jaxx.application.swing.util.CloseableUI;
91
92 import javax.swing.JComboBox;
93 import javax.swing.JComponent;
94 import javax.swing.JList;
95 import javax.swing.JMenuItem;
96 import javax.swing.JOptionPane;
97 import javax.swing.JTabbedPane;
98 import javax.swing.JTable;
99 import javax.swing.JTree;
100 import javax.swing.ListCellRenderer;
101 import javax.swing.ListSelectionModel;
102 import javax.swing.event.ListSelectionListener;
103 import javax.swing.event.TableModelEvent;
104 import javax.swing.event.TreeModelEvent;
105 import javax.swing.event.TreeModelListener;
106 import javax.swing.table.DefaultTableCellRenderer;
107 import javax.swing.table.JTableHeader;
108 import javax.swing.table.TableCellRenderer;
109 import javax.swing.table.TableColumnModel;
110 import java.awt.Color;
111 import java.awt.Component;
112 import java.beans.PropertyChangeEvent;
113 import java.beans.PropertyChangeListener;
114 import java.util.ArrayList;
115 import java.util.Collection;
116 import java.util.HashSet;
117 import java.util.LinkedHashSet;
118 import java.util.List;
119 import java.util.Map;
120 import java.util.Objects;
121 import java.util.Set;
122 import java.util.TreeSet;
123 import java.util.stream.Collectors;
124
125 import static org.nuiton.i18n.I18n.n;
126 import static org.nuiton.i18n.I18n.t;
127
128
129
130
131
132
133 public class EditProtocolUIHandler extends AbstractTuttiUIHandler<EditProtocolUIModel, EditProtocolUI> implements CloseableUI {
134
135
136 private static final Log log = LogFactory.getLog(EditProtocolUIHandler.class);
137
138 public static String getTitle(boolean exist) {
139
140 String result;
141 if (exist) {
142 result = t("tutti.editProtocol.title.edit.protocol");
143 } else {
144 result = t("tutti.editProtocol.title.create.protocol");
145 }
146 return result;
147 }
148
149
150
151 protected SampleCategoryModel sampleCategoryModel;
152
153 protected List<BeanDoubleList<Caracteristic>> allDoubleLists;
154
155 public JXTable getSpeciesTable() {
156 return ui.getSpeciesTable();
157 }
158
159 public JXTable getBenthosTable() {
160 return ui.getBenthosTable();
161 }
162
163 public JXTable getCaracteristicsMappingTable() {
164 return ui.getCaracteristicsMappingTable();
165 }
166
167 public JXTable getOperationFieldsMappingTable() {
168 return ui.getOperationFieldsMappingTable();
169 }
170
171 public EditProtocolSpeciesTableModel getSpeciesTableModel() {
172 return (EditProtocolSpeciesTableModel) getSpeciesTable().getModel();
173 }
174
175 public EditProtocolSpeciesTableModel getBenthosTableModel() {
176 return (EditProtocolSpeciesTableModel) getBenthosTable().getModel();
177 }
178
179 public boolean isSpeciesSelected(Object selectedItem) {
180 return selectedItem != null && selectedItem instanceof Species;
181 }
182
183 public EditProtocolCaracteristicsTableModel getCaracteristicMappingTableModel() {
184 return (EditProtocolCaracteristicsTableModel) getCaracteristicsMappingTable().getModel();
185 }
186
187 public EditProtocolOperationFieldsTableModel getEditProtocolOperationFieldsMappingTableModel() {
188 return (EditProtocolOperationFieldsTableModel) getOperationFieldsMappingTable().getModel();
189 }
190
191
192
193
194
195 @Override
196 public SwingValidator<EditProtocolUIModel> getValidator() {
197 return ui.getValidator();
198 }
199
200 private Multimap<TuttiLocation, TuttiLocation> programStratasAndSubstratas;
201
202 @Override
203 public void beforeInit(EditProtocolUI ui) {
204 super.beforeInit(ui);
205
206 this.sampleCategoryModel = getContext().getDataContext().getSampleCategoryModel();
207
208 incrementsMessage("Chargement des réferentiels");
209
210 getDataContext().resetValidationDataContext();
211
212 EditProtocolUIModel model = new EditProtocolUIModel(sampleCategoryModel);
213
214
215
216 List<Species> allSpecies = new ArrayList<>(getDataContext().getSpecies());
217 model.setAllSpecies(allSpecies);
218
219 Multimap<String, Species> allSpeciesByTaxonId = Speciess.splitByReferenceTaxonId(allSpecies);
220 model.setAllSpeciesByTaxonId(allSpeciesByTaxonId);
221
222 List<Species> referentSpecies = getDataContext().getReferentSpecies();
223 Map<String, Species> allReferentSpeciesByTaxonId = Speciess.splitReferenceSpeciesByReferenceTaxonId(referentSpecies);
224 model.setAllReferentSpeciesByTaxonId(allReferentSpeciesByTaxonId);
225
226 List<Caracteristic> caracteristics = new ArrayList<>(getDataContext().getCaracteristics());
227 model.setCaracteristics(caracteristics);
228
229 Map<String, Caracteristic> allCaracteristic = TuttiEntities.splitById(caracteristics);
230 model.setAllCaracteristic(allCaracteristic);
231
232
233
234
235
236
237 listModelIsModify(model);
238
239 TuttiLocation programZone = getDataContext().getProgram().getZone();
240
241 programStratasAndSubstratas = HashMultimap.create(getPersistenceService().getAllFishingOperationStratasAndSubstratas(programZone.getId()));
242
243 ImmutableMap.Builder<String, String> locationLabelCacheBuilder = ImmutableMap.builder();
244
245 programStratasAndSubstratas.keySet().forEach(strata -> {
246
247 locationLabelCacheBuilder.put(strata.getId(), strata.getLabel());
248 programStratasAndSubstratas.get(strata).stream().filter(Objects::nonNull)
249 .forEach(subStrata -> locationLabelCacheBuilder.put(subStrata.getId(), subStrata.getLabel()));
250
251 });
252
253 ImmutableMap<String, String> locationLabelCache = locationLabelCacheBuilder.build();
254 model.setLocationLabelCache(locationLabelCache);
255
256
257 model.addPropertyChangeListener(EditProtocolUIModel.PROPERTY_MODIFYING_ZONES, evt -> {
258
259 boolean newValue = (boolean) evt.getNewValue();
260 if (!newValue) {
261
262 if (log.isInfoEnabled()) {
263 log.info("Ask to release zone trees caches and revalidate protocol.");
264 }
265
266 EditProtocolUIModel source = (EditProtocolUIModel) evt.getSource();
267 boolean stratasAvailable = source.getAvailableStratasTreeModel().isAvailableStratas();
268 source.setAvailableStratas(stratasAvailable);
269
270
271 getValidator().doValidate();
272 }
273 });
274
275 this.ui.setContextValue(model);
276 }
277
278 @Override
279 public void afterInit(EditProtocolUI ui) {
280
281 initUI(this.ui);
282
283 EditProtocolUIModel model = getModel();
284
285 TuttiProtocol protocol;
286
287 if (getContext().isProtocolFilled()) {
288
289
290
291 incrementsMessage("Chargement du protocole");
292
293 protocol = getDataContext().getProtocol();
294
295 if (EditProtocolAction.CLEAN_PROTOCOL_ENTRY.getContextValue(this.ui) != null) {
296
297
298 protocol = EditProtocolAction.CLEAN_PROTOCOL_ENTRY.getContextValue(this.ui);
299
300 EditProtocolAction.CLEAN_PROTOCOL_ENTRY.removeContextValue(this.ui);
301
302 model.setCleaned(true);
303 this.ui.getSaveWarning().setText(t("tutti.editProtocol.warn.clean"));
304 }
305 model.fromEntity(protocol);
306
307 } else if ((protocol = ImportProtocolAction.IMPORT_PROTOCOL_ENTRY.getContextValue(this.ui)) != null) {
308
309 incrementsMessage("Import du protocole");
310
311
312
313 ImportProtocolAction.IMPORT_PROTOCOL_ENTRY.removeContextValue(this.ui);
314
315 model.fromEntity(protocol);
316 model.setImported(true);
317 this.ui.getSaveWarning().setText(t("tutti.editProtocol.warn.import"));
318
319 } else if ((protocol = CloneProtocolAction.CLONE_PROTOCOL_ENTRY.getContextValue(this.ui)) != null) {
320
321 incrementsMessage("Clone du protocole");
322
323
324
325 CloneProtocolAction.CLONE_PROTOCOL_ENTRY.removeContextValue(this.ui);
326
327 model.fromEntity(protocol);
328 model.setCloned(true);
329 this.ui.getSaveWarning().setText(t("tutti.editProtocol.warn.clone"));
330
331 } else {
332
333 incrementsMessage("Création d'un nouveau protocol");
334
335
336
337 if (log.isDebugEnabled()) {
338 log.debug("Will create a new protocol");
339 }
340 }
341
342 if (model.getLengthClassesPmfmId() == null) {
343 model.setLengthClassesPmfmId(new ArrayList<>());
344 }
345
346 model.setProgramId(getDataContext().getProgramId());
347
348 SwingValidator validator = this.ui.getValidator();
349 listenValidatorValid(validator, model);
350
351 registerValidators(validator);
352
353 Collection<Species> referents = model.getAllReferentSpeciesByTaxonId().values();
354
355 initBeanFilterableComboBox(this.ui.getSpeciesComboBox(), new ArrayList<>(referents), null);
356 initBeanFilterableComboBox(this.ui.getBenthosComboBox(), new ArrayList<>(referents), null);
357 initBeanFilterableComboBox(ui.getCaracteristicMappingComboBox(), new ArrayList<>(model.getCaracteristics()), null);
358
359 List<EditProtocolCaracteristicsRowModel> caracteristicMappingRows;
360 List<EditProtocolOperationFieldsRowModel> operationFieldMappingRows;
361 List<EditProtocolSpeciesRowModel> speciesRows;
362 List<EditProtocolSpeciesRowModel> benthosRows;
363
364 model.addPropertyChangeListener(EditProtocolUIModel.PROPERTY_IMPORT_COLUMNS, evt -> populateImportColumnTableEditors());
365
366 incrementsMessage("Préparation des interfaces graphiques");
367
368 List<CalcifiedPiecesSamplingEditorRowModel> cpsRows = new ArrayList<>();
369
370
371 if (protocol == null) {
372 caracteristicMappingRows = new ArrayList<>();
373 operationFieldMappingRows = new ArrayList<>();
374 speciesRows = new ArrayList<>();
375 benthosRows = new ArrayList<>();
376
377 } else {
378
379 caracteristicMappingRows = toProtocolCaracteristicRows(protocol.getCaracteristicMapping());
380 operationFieldMappingRows = toProtocolOperationFieldsRows(protocol.getOperationFieldMapping());
381
382 speciesRows = toSpeciesRows(protocol.getSpecies(), cpsRows);
383 benthosRows = toSpeciesRows(protocol.getBenthos(), cpsRows);
384
385 if (log.isDebugEnabled()) {
386 log.debug("Will edit protocol with " +
387 speciesRows.size() + " protocolSpecies and " +
388 benthosRows.size() + " benthos declared.");
389 }
390 }
391
392
393
394 cpsRows.sort(CalcifiedPiecesSamplingEditorRowModel.COMPARATOR);
395 getModel().setCpsRows(cpsRows);
396
397 model.setSpeciesRow(speciesRows);
398 model.setBenthosRow(benthosRows);
399 model.setCaracteristicMappingRows(caracteristicMappingRows);
400 model.setOperationFieldMappingRows(operationFieldMappingRows);
401
402 this.ui.getSpeciesComboBox().reset();
403 this.ui.getBenthosComboBox().reset();
404 this.ui.getCaracteristicMappingComboBox().reset();
405
406 {
407
408
409 JXTable table = getSpeciesTable();
410
411 DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt();
412
413 TableColumnExt speciesColumn = addColumnToModel(columnModel,
414 null,
415 newTableCellRender(Species.class),
416 EditProtocolSpeciesTableModel.SPECIES_ID);
417 speciesColumn.setSortable(true);
418 DecoratorService.SpeciesDecorator speciesDecorator = new DecoratorService.SpeciesDecorator();
419 speciesColumn.putClientProperty(SpeciesBatchRowHelper.SPECIES_DECORATOR, speciesDecorator);
420 speciesColumn.setCellRenderer(newTableCellRender(speciesDecorator));
421
422 TableColumnExt speciesSurveyCodeColumn = addColumnToModel(columnModel,
423 null,
424 null,
425 EditProtocolSpeciesTableModel.SURVEY_CODE_ID);
426 speciesSurveyCodeColumn.setSortable(true);
427
428 addLengthClassesColumnToModel(columnModel, model.getLengthClassesPmfmId());
429 addMaturityColumnToModel(columnModel, model.getMaturityPmfmId());
430 addCpsPmfmColumnToModel(columnModel);
431
432 addBooleanColumnToModel(columnModel, EditProtocolSpeciesTableModel.WEIGHT_ENABLED, table);
433
434 for (SampleCategoryModelEntry sampleCategoryModelEntry : sampleCategoryModel.getCategory()) {
435
436 if (sampleCategoryModelEntry.getOrder() == 0) {
437
438 continue;
439 }
440
441 MandatorySampleCategoryColumnIdentifier identifier = MandatorySampleCategoryColumnIdentifier.newId(
442 EditProtocolSpeciesRowModel.PROPERTY_MANDATORY_SAMPLE_CATEGORY_ID,
443 sampleCategoryModelEntry.getCategoryId(),
444 sampleCategoryModelEntry.getLabel(),
445 sampleCategoryModelEntry.getLabel()
446 );
447
448 addBooleanColumnToModel(columnModel, identifier, table);
449 }
450
451 addIndividualObservationColumnToModel(columnModel, table);
452
453 addColumnToModel(columnModel,
454 RtpCellEditor.newEditor(ui),
455 new RtpCellRenderer(),
456 EditProtocolSpeciesTableModel.USE_RTP);
457
458 initTable(table,
459 columnModel,
460 speciesColumn,
461 EditProtocolSpeciesTableModel.USE_RTP,
462 speciesRows,
463 e -> {
464 ListSelectionModel source = (ListSelectionModel) e.getSource();
465 getModel().setRemoveSpeciesEnabled(!source.isSelectionEmpty());
466 });
467 }
468
469 {
470
471
472 JXTable table = getBenthosTable();
473
474 DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt();
475
476 TableColumnExt speciesColumn = addColumnToModel(columnModel,
477 null,
478 newTableCellRender(Species.class),
479 EditProtocolSpeciesTableModel.SPECIES_ID);
480 speciesColumn.setSortable(true);
481 DecoratorService.SpeciesDecorator speciesDecorator = new DecoratorService.SpeciesDecorator();
482 speciesColumn.putClientProperty(SpeciesBatchRowHelper.SPECIES_DECORATOR, speciesDecorator);
483 speciesColumn.setCellRenderer(newTableCellRender(speciesDecorator));
484
485 TableColumnExt speciesSurveyCodeColumn = addColumnToModel(columnModel,
486 null,
487 null,
488 EditProtocolSpeciesTableModel.SURVEY_CODE_ID);
489 speciesSurveyCodeColumn.setSortable(true);
490
491 addLengthClassesColumnToModel(columnModel, model.getLengthClassesPmfmId());
492 addMaturityColumnToModel(columnModel, model.getMaturityPmfmId());
493 addCpsPmfmColumnToModel(columnModel);
494
495 addBooleanColumnToModel(columnModel, EditProtocolSpeciesTableModel.WEIGHT_ENABLED, table);
496
497 for (SampleCategoryModelEntry sampleCategoryModelEntry : sampleCategoryModel.getCategory()) {
498
499 if (sampleCategoryModelEntry.getOrder() == 0) {
500
501 continue;
502 }
503
504 MandatorySampleCategoryColumnIdentifier identifier = MandatorySampleCategoryColumnIdentifier.newId(
505 EditProtocolSpeciesRowModel.PROPERTY_MANDATORY_SAMPLE_CATEGORY_ID,
506 sampleCategoryModelEntry.getCategoryId(),
507 sampleCategoryModelEntry.getLabel(),
508 sampleCategoryModelEntry.getLabel()
509 );
510
511 addBooleanColumnToModel(columnModel, identifier, table);
512 }
513
514 addIndividualObservationColumnToModel(columnModel, table);
515
516 addColumnToModel(columnModel,
517 RtpCellEditor.newEditor(ui),
518 new RtpCellRenderer(),
519 EditProtocolSpeciesTableModel.USE_RTP);
520
521 initTable(table,
522 columnModel,
523 speciesColumn,
524 EditProtocolSpeciesTableModel.USE_RTP,
525 benthosRows,
526 e -> {
527 ListSelectionModel source = (ListSelectionModel) e.getSource();
528 getModel().setRemoveBenthosEnabled(!source.isSelectionEmpty());
529 });
530 }
531
532 BeanDoubleList<Caracteristic> maturityList = this.ui.getMaturityList();
533 model.getMaturityPmfmUsed().attachPredicateToUi(maturityList);
534
535 BeanDoubleList<Caracteristic> lengthClassesList = this.ui.getLengthClassesList();
536 model.getLengthStepPmfmUsed().attachPredicateToUi(lengthClassesList);
537
538 allDoubleLists = new ArrayList<>();
539 allDoubleLists.add(lengthClassesList);
540 allDoubleLists.add(ui.getIndividualObservationList());
541 allDoubleLists.add(maturityList);
542
543 initDoubleList(EditProtocolUIModel.PROPERTY_LENGTH_CLASSES_PMFM_ID,
544 lengthClassesList,
545 Lists.newArrayList(model.getCaracteristics()),
546 model.getLengthClassesPmfmId());
547
548 JList<Caracteristic> lengthClassesSelectedList = lengthClassesList.getSelectedList();
549 ListCellRenderer<? super Caracteristic> lengthClassesDefaultRenderer = lengthClassesSelectedList.getCellRenderer();
550 lengthClassesSelectedList.setCellRenderer(new LengthStepCaracteristicCellRenderer(getConfig().getColorWarningRow(), model.getLengthStepPmfmUsed(), lengthClassesDefaultRenderer));
551
552 initDoubleList(EditProtocolUIModel.PROPERTY_INDIVIDUAL_OBSERVATION_PMFM_ID,
553 this.ui.getIndividualObservationList(),
554 Lists.newArrayList(model.getCaracteristics()),
555 model.getIndividualObservationPmfmId());
556
557 initDoubleList(EditProtocolUIModel.PROPERTY_MATURITY_PMFM_ID,
558 maturityList,
559 model.getCaracteristics().stream().filter(caracteristic -> !caracteristic.isQualitativeValueEmpty()).collect(Collectors.toList()),
560 model.getMaturityPmfmId());
561
562 JList<Caracteristic> maturitySelectedList = maturityList.getSelectedList();
563 JMenuItem editMaturity = ui.getEditMaturityCaracteristicAction();
564 maturityList.getSelectedListPopup().add(editMaturity);
565
566
567 maturitySelectedList.addListSelectionListener(e -> {
568 boolean editMaturityEnabled = maturitySelectedList.getSelectedIndices().length == 1;
569 editMaturity.setEnabled(editMaturityEnabled);
570 });
571
572 ListCellRenderer<? super Caracteristic> maturityDefaultRenderer = maturitySelectedList.getCellRenderer();
573 maturitySelectedList.setCellRenderer(new MaturityCaracteristicCellRenderer(model.getMaturityPmfmUsed(), maturityDefaultRenderer));
574
575
576
577
578 ui.getTabPanel().addChangeListener(e -> {
579 JTabbedPane source = (JTabbedPane) e.getSource();
580 if (ui.getCaracteristicPanel().equals(source.getSelectedComponent())) {
581 lengthClassesList.getHandler().recomputeButtonStates();
582 maturityList.getHandler().recomputeButtonStates();
583 }
584 });
585
586
587 {
588 JXTable caracteristicsMappingTable = getCaracteristicsMappingTable();
589
590 DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt();
591
592 addColumnToModel(columnModel,
593 null,
594 newTableCellRender(Caracteristic.class),
595 EditProtocolCaracteristicsTableModel.PSFM_ID);
596
597 addComboDataColumnToModel(columnModel,
598 EditProtocolCaracteristicsTableModel.TYPE,
599 getDecorator(CaracteristicType.class, null),
600 Lists.newArrayList(CaracteristicType.getTabTypes()));
601
602 addColumnToModel(columnModel,
603 EditProtocolCaracteristicsTableModel.IMPORT_FILE_COLUMN);
604
605 List<Caracteristic> caracteristics = new ArrayList<>(getModel().getCaracteristics());
606 EditProtocolCaracteristicsTableModel tableModel = new EditProtocolCaracteristicsTableModel(columnModel, caracteristics);
607 caracteristicsMappingTable.setModel(tableModel);
608 caracteristicsMappingTable.setColumnModel(columnModel);
609
610
611 caracteristicsMappingTable.getTableHeader().setReorderingAllowed(false);
612
613 addHighlighters(caracteristicsMappingTable);
614
615 caracteristicsMappingTable.getSelectionModel().addListSelectionListener(e -> {
616
617 int rowIndex = getCaracteristicsMappingTable().getSelectedRow();
618
619 boolean enableRemoveCaracteristicMapping = false;
620 boolean enableMoveUpCaracteristicMapping = false;
621 boolean enableMoveDownCaracteristicMapping = false;
622
623 if (rowIndex != -1) {
624
625
626 enableRemoveCaracteristicMapping = true;
627
628 enableMoveUpCaracteristicMapping = rowIndex > 0;
629
630 enableMoveDownCaracteristicMapping = rowIndex < getCaracteristicsMappingTable().getModel().getRowCount() - 1;
631 }
632 EditProtocolUIModel model1 = getModel();
633 model1.setRemoveCaracteristicMappingEnabled(enableRemoveCaracteristicMapping);
634 model1.setMoveUpCaracteristicMappingEnabled(enableMoveUpCaracteristicMapping);
635 model1.setMoveDownCaracteristicMappingEnabled(enableMoveDownCaracteristicMapping);
636
637 });
638
639
640 SwingUtil.scrollToTableSelection(caracteristicsMappingTable);
641
642 tableModel.setRows(caracteristicMappingRows);
643 }
644
645
646 {
647 JXTable operationFieldsTable = getUI().getOperationFieldsMappingTable();
648
649 DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt();
650
651 addColumnToModel(columnModel,
652 null,
653 new DefaultTableCellRenderer() {
654
655 @Override
656 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
657 setText(t("tutti.editFishingOperation.field." + value.toString()));
658 return this;
659 }
660 },
661 EditProtocolOperationFieldsTableModel.FIELD);
662
663 addColumnToModel(columnModel,
664 EditProtocolOperationFieldsTableModel.IMPORT_FILE_COLUMN);
665
666 EditProtocolOperationFieldsTableModel tableModel = new EditProtocolOperationFieldsTableModel(columnModel);
667 operationFieldsTable.setModel(tableModel);
668 operationFieldsTable.setColumnModel(columnModel);
669
670
671 operationFieldsTable.getTableHeader().setReorderingAllowed(false);
672
673 addHighlighters(operationFieldsTable);
674
675 tableModel.setRows(operationFieldMappingRows);
676
677
678 SwingUtil.scrollToTableSelection(operationFieldsTable);
679 }
680
681 populateImportColumnTableEditors();
682
683 initZonesTree();
684
685 initAvailableStratasTree();
686
687
688
689 model.setModify(model.isCreate() || model.isCleaned());
690
691 this.ui.getCaracteristicPane().addChangeListener(e -> {
692 JTabbedPane tabPanel = (JTabbedPane) e.getSource();
693 int selectedIndex = tabPanel.getSelectedIndex();
694 BeanDoubleList<Caracteristic> selectedDoubleList;
695 log.debug("selected " + selectedIndex);
696 switch (selectedIndex) {
697 case 0:
698 selectedDoubleList = EditProtocolUIHandler.this.ui.getLengthClassesList();
699 break;
700
701 case 1:
702 selectedDoubleList = EditProtocolUIHandler.this.ui.getIndividualObservationList();
703 break;
704
705 case 2:
706 selectedDoubleList = EditProtocolUIHandler.this.ui.getMaturityList();
707 break;
708
709 default:
710 selectedDoubleList = null;
711 }
712 if (selectedDoubleList != null) {
713 selectedDoubleList.getHandler().refreshFilteredElements();
714
715 } else {
716
717 List<Caracteristic> selectedCaracteristics = new ArrayList<>(getModel().getCaracteristics());
718 for (BeanDoubleList<Caracteristic> doubleList : allDoubleLists) {
719 selectedCaracteristics.removeAll(doubleList.getModel().getSelected());
720 }
721 selectedCaracteristics.removeAll(getModel().getUsedCaracteristics());
722 getUI().getCaracteristicMappingComboBox().setData(selectedCaracteristics);
723 }
724 });
725
726 this.ui.getTabPanel().addChangeListener(e -> {
727 JTabbedPane tabPanel = (JTabbedPane) e.getSource();
728 int selectedIndex = tabPanel.getSelectedIndex();
729 if (log.isDebugEnabled()) {
730 log.debug("New tab selected: " + selectedIndex);
731 }
732 if (selectedIndex == 4) {
733
734 if (log.isDebugEnabled()) {
735 log.debug("Update species list on calcifiedPiecesSamplingEditorUI model.");
736 }
737
738
739 CalcifiedPiecesSamplingEditorUI calcifiedPiecesSamplingEditorUI = getUI().getCalcifiedPiecesSamplingEditorUI();
740
741 List<Species> protocolSpecies = new ArrayList<>();
742
743 List<EditProtocolSpeciesRowModel> speciesRows1 = getModel().getSpeciesRow();
744 if (speciesRows1 != null) {
745
746 protocolSpecies.addAll(speciesRows1.stream()
747 .filter(EditProtocolSpeciesRowModel::withLengthStepPmfm)
748 .map(EditProtocolSpeciesRowModel::toSpeciesWithSurveyCode)
749 .collect(Collectors.toList()));
750
751 }
752
753 List<EditProtocolSpeciesRowModel> benthosRows1 = getModel().getBenthosRow();
754 if (benthosRows1 != null) {
755
756 protocolSpecies.addAll(benthosRows1.stream()
757 .filter(EditProtocolSpeciesRowModel::withLengthStepPmfm)
758 .map(EditProtocolSpeciesRowModel::toSpeciesWithSurveyCode)
759 .collect(Collectors.toList()));
760
761 }
762
763 protocolSpecies.removeAll(getModel().getCpsRows()
764 .stream()
765 .map(CalcifiedPiecesSamplingEditorRowModel::getProtocolSpecies)
766 .map(EditProtocolSpeciesRowModel::getSpecies)
767 .collect(Collectors.toList()));
768
769
770 calcifiedPiecesSamplingEditorUI.getSpeciesComboBox().setData(null);
771 calcifiedPiecesSamplingEditorUI.getSpeciesComboBox().setData(protocolSpecies);
772
773 }
774 });
775
776 model.setVersion(TuttiProtocols.CURRENT_PROTOCOL_VERSION);
777
778 }
779
780 protected void addIndividualObservationColumnToModel(DefaultTableColumnModelExt columnModel, JXTable table) {
781 TableCellRenderer renderer = new TableCellRenderer() {
782
783 TableCellRenderer delegate = table.getDefaultRenderer(Boolean.class);
784
785 @Override
786 public Component getTableCellRendererComponent(JTable table,
787 Object value,
788 boolean isSelected,
789 boolean hasFocus,
790 int row, int column) {
791 Component result = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
792 result.setEnabled(table.isCellEditable(row, column));
793 return result;
794 }
795 };
796 addColumnToModel(columnModel,
797 table.getDefaultEditor(Boolean.class),
798 renderer,
799 EditProtocolSpeciesTableModel.INDIVIDUAL_OBSERVATION_ENABLED);
800 }
801
802 protected void initZonesTree() {
803
804 EditProtocolUIModel model = getModel();
805
806 ZonesTreeModel zonesTreeModel = model.getZonesTreeModel();
807
808 zonesTreeModel.setCreatingModel(true);
809
810 try {
811
812 model.getIncomingZones().forEach(zonesTreeModel::addZone);
813
814 } finally {
815 zonesTreeModel.setCreatingModel(false);
816 }
817
818
819 zonesTreeModel.addTreeModelListener(new TreeModelListener() {
820
821 @Override
822 public void treeNodesChanged(TreeModelEvent e) {
823 model.setModify(true);
824 }
825
826 @Override
827 public void treeNodesInserted(TreeModelEvent e) {
828 getUI().getZoneEditor().getZonesTree().expandPath(e.getTreePath());
829 }
830
831 @Override
832 public void treeNodesRemoved(TreeModelEvent e) {
833 }
834
835 @Override
836 public void treeStructureChanged(TreeModelEvent e) {
837 }
838 });
839
840 initJTree(ui.getZoneEditor().getZonesTree());
841
842
843 }
844
845 protected void initAvailableStratasTree() {
846
847 EditProtocolUIModel model = getModel();
848
849 Set<String> usedStrataLocations = new LinkedHashSet<>();
850 Set<String> usedSubStrataLocations = new LinkedHashSet<>();
851
852
853 model.getIncomingZones().forEach(zone -> {
854
855 Collection<Strata> zoneStratas = zone.getStrata();
856
857 Set<String> strataLocations = zoneStratas.stream()
858 .map(Strata::getId)
859 .collect(Collectors.toSet());
860 usedStrataLocations.addAll(strataLocations);
861
862 Set<String> subStrataLocations = zoneStratas.stream()
863 .map(Strata::getSubstrata)
864 .flatMap(Collection::stream)
865 .map(SubStrata::getId)
866 .collect(Collectors.toSet());
867 usedSubStrataLocations.addAll(subStrataLocations);
868
869 });
870
871 AvailableStratasTreeModel availableStratasTreeModel = model.getAvailableStratasTreeModel();
872
873 availableStratasTreeModel.setCreatingModel(true);
874
875 try {
876
877 programStratasAndSubstratas.keySet().stream().forEach(strataLocation -> {
878
879 String strataId = strataLocation.getId();
880
881 Collection<TuttiLocation> subStrataLocations = new HashSet<>(programStratasAndSubstratas.get(strataLocation));
882 subStrataLocations.remove(null);
883 List<String> subStratas = subStrataLocations.stream()
884 .map(TuttiLocation::getId)
885 .filter(id -> !usedSubStrataLocations.contains(id))
886 .collect(Collectors.toList());
887
888 if (!(subStratas.isEmpty() && usedStrataLocations.contains(strataLocation.getId()))) {
889
890 StrataNode strataNode = availableStratasTreeModel.getOrCreateStrataNode(strataId);
891 subStratas.forEach(subStrataId -> availableStratasTreeModel.addSubsStrata(strataNode, subStrataId));
892
893 }
894
895 });
896
897 } finally {
898
899 availableStratasTreeModel.setCreatingModel(false);
900
901 }
902
903 initJTree(ui.getZoneEditor().getAvailableStratasTree());
904
905 }
906
907 @Override
908 protected JComponent getComponentToFocus() {
909 return getUI().getNameField();
910 }
911
912 public List<EditProtocolSpeciesRowModel> toSpeciesRows(List<SpeciesProtocol> speciesProtocols) {
913 return toSpeciesRows(speciesProtocols, getModel().getCpsRows());
914 }
915
916 public List<EditProtocolSpeciesRowModel> toSpeciesRows(List<SpeciesProtocol> speciesProtocols,
917 List<CalcifiedPiecesSamplingEditorRowModel> cpsRows) {
918 BeanFilterableComboBox<Species> speciesComboBox = ui.getSpeciesComboBox();
919 Preconditions.checkNotNull(speciesComboBox.getData());
920 BeanFilterableComboBox<Species> benthosComboBox = ui.getBenthosComboBox();
921 Preconditions.checkNotNull(benthosComboBox.getData());
922
923 EditProtocolUIModel model = getModel();
924
925 Map<String, Species> allReferentSpeciesByTaxonId = model.getAllReferentSpeciesByTaxonId();
926 Map<String, Caracteristic> allCaracteristic = model.getAllCaracteristic();
927
928 List<Caracteristic> lengthClassesPmfmId = Lists.newArrayList();
929
930 Set<Species> speciesSet = Sets.newHashSet();
931 List<EditProtocolSpeciesRowModel> result = Lists.newArrayList();
932 if (CollectionUtils.isNotEmpty(speciesProtocols)) {
933 for (SpeciesProtocol speciesProtocol : speciesProtocols) {
934 Integer taxonId = speciesProtocol.getSpeciesReferenceTaxonId();
935
936 if (taxonId == null) {
937
938 continue;
939 }
940 String taxonIdStr = String.valueOf(taxonId);
941
942
943 Collection<Species> allSynonyms = model.getAllSynonyms(taxonIdStr);
944 model.getAllSynonyms().removeAll(allSynonyms);
945
946
947 Species species = allReferentSpeciesByTaxonId.get(taxonIdStr);
948
949
950 Preconditions.checkNotNull(species, "Espèce inconnue : " + taxonIdStr);
951 speciesSet.add(species);
952
953 EditProtocolSpeciesRowModel row = createNewProtocolSpeciesRow();
954 row.setSpecies(species);
955
956 String lengthStepPmfmId = speciesProtocol.getLengthStepPmfmId();
957 Caracteristic lengthStepPmfm = allCaracteristic.get(lengthStepPmfmId);
958 if (lengthStepPmfmId != null &&
959 !lengthClassesPmfmId.contains(lengthStepPmfm) &&
960 !model.containsLengthClassesPmfmId(lengthStepPmfmId)) {
961 if (log.isInfoEnabled()) {
962 log.info("Found a new lengthStep pmfm: " + lengthStepPmfmId);
963 }
964 lengthClassesPmfmId.add(lengthStepPmfm);
965 }
966 row.setLengthStepPmfm(lengthStepPmfm);
967
968 String maturityPmfmId = speciesProtocol.getMaturityPmfmId();
969 Caracteristic maturityPmfm = allCaracteristic.get(maturityPmfmId);
970 row.setMaturityPmfm(maturityPmfm);
971
972 row.fromEntity(speciesProtocol);
973
974
975 row.setMandatorySampleCategoryId(Lists.newArrayList(speciesProtocol.getMandatorySampleCategoryId()));
976 result.add(row);
977
978
979 Collection<CalcifiedPiecesSamplingDefinition> cpsDefs = speciesProtocol.getCalcifiedPiecesSamplingDefinition();
980 if (cpsDefs != null) {
981 cpsDefs.forEach(def -> {
982 CalcifiedPiecesSamplingEditorRowModel cpsRow = new CalcifiedPiecesSamplingEditorRowModel();
983 cpsRow.fromEntity(def);
984 cpsRow.setProtocolSpecies(row);
985 cpsRow.setValid(true);
986 cpsRows.add(cpsRow);
987 });
988 }
989
990 }
991
992
993 speciesComboBox.removeItems(speciesSet);
994 benthosComboBox.removeItems(speciesSet);
995 }
996
997 if (CollectionUtils.isNotEmpty(lengthClassesPmfmId)) {
998
999
1000
1001 model.addAllLengthClassesPmfmId(TuttiEntities.collecIds(lengthClassesPmfmId));
1002
1003
1004 BeanDoubleList<Caracteristic> lengthClassesList = ui.getLengthClassesList();
1005 lengthClassesList.getModel().addToSelected(lengthClassesPmfmId);
1006 }
1007 return result;
1008 }
1009
1010 public EditProtocolSpeciesRowModel createNewProtocolSpeciesRow() {
1011
1012 EditProtocolSpeciesRowModel result = getModel().newRow();
1013
1014 result.addPropertyChangeListener(EditProtocolSpeciesRowModel.PROPERTY_LENGTH_STEP_PMFM, evt -> {
1015
1016 Caracteristic newValue = (Caracteristic) evt.getNewValue();
1017 if (newValue == null) {
1018
1019 result.setIndividualObservationEnabled(false);
1020
1021 if (getModel().getCpsRows() != null) {
1022
1023 List<CalcifiedPiecesSamplingEditorRowModel> speciesCpsRows =
1024 getModel().getCpsRows()
1025 .stream()
1026 .filter(row -> row.getProtocolSpecies().equals(result))
1027 .collect(Collectors.toList());
1028
1029 if (!speciesCpsRows.isEmpty()) {
1030 String htmlMessage = String.format(
1031 AbstractApplicationUIHandler.CONFIRMATION_FORMAT,
1032 t("tutti.editProtocol.action.removeLengthStepPmfm.removeCpsRows.message"),
1033 t("jaxx.application.common.askBeforeDelete.help"));
1034 int i = JOptionPane.showConfirmDialog(
1035 getUI(),
1036 htmlMessage,
1037 t("tutti.editProtocol.action.removeLengthStepPmfm.removeCpsRows.title"),
1038 JOptionPane.OK_CANCEL_OPTION,
1039 JOptionPane.QUESTION_MESSAGE);
1040
1041 boolean deleteCpsRows = i == JOptionPane.OK_OPTION;
1042
1043 if (deleteCpsRows) {
1044
1045 deleteCpsRows(speciesCpsRows);
1046
1047 } else {
1048
1049 result.setLengthStepPmfm((Caracteristic) evt.getOldValue());
1050
1051 }
1052 }
1053 }
1054 }
1055 });
1056 return result;
1057 }
1058
1059 public void deleteCpsRows(Collection<CalcifiedPiecesSamplingEditorRowModel> cpsRowsToDelete) {
1060
1061 CalcifiedPiecesSamplingEditorUI cpsEditor = getUI().getCalcifiedPiecesSamplingEditorUI();
1062
1063 List<CalcifiedPiecesSamplingEditorRowModel> cpsRows = getModel().getCpsRows();
1064
1065 TreeSet<Integer> indexesToDelete =
1066 new TreeSet<>(cpsRowsToDelete.stream().map(cpsRows::indexOf).collect(Collectors.toSet()));
1067
1068 cpsRows.removeAll(cpsRowsToDelete);
1069
1070 CalcifiedPiecesSamplingEditorTableModel cpsTableModel =
1071 (CalcifiedPiecesSamplingEditorTableModel) cpsEditor.getCpsTable().getModel();
1072 cpsTableModel.fireTableRowsDeleted(indexesToDelete.first(), indexesToDelete.last());
1073 }
1074
1075 public List<EditProtocolCaracteristicsRowModel> toProtocolCaracteristicRows(List<CaracteristicMappingRow> caracteristicMappingRows) {
1076 BeanFilterableComboBox<Caracteristic> caracteristicMappingComboBox = ui.getCaracteristicMappingComboBox();
1077 Preconditions.checkNotNull(caracteristicMappingComboBox.getData());
1078
1079 EditProtocolUIModel model = getModel();
1080
1081 Set<Caracteristic> caracteristicSet = Sets.newHashSet();
1082 List<EditProtocolCaracteristicsRowModel> result = Lists.newArrayList();
1083 if (CollectionUtils.isNotEmpty(caracteristicMappingRows)) {
1084 for (CaracteristicMappingRow caracteristicMappingRow : caracteristicMappingRows) {
1085 String pmfmId = caracteristicMappingRow.getPmfmId();
1086
1087 if (pmfmId == null) {
1088
1089 continue;
1090 }
1091
1092
1093 caracteristicSet.add(model.getAllCaracteristic().get(pmfmId));
1094
1095 EditProtocolCaracteristicsRowModel row = createEditProtocolCaracteristicsRowModel();
1096 row.fromEntity(caracteristicMappingRow);
1097 row.setValid(row.getType() != null);
1098
1099 result.add(row);
1100 }
1101
1102 caracteristicMappingComboBox.removeItems(caracteristicSet);
1103 }
1104
1105 return result;
1106 }
1107
1108 public List<EditProtocolOperationFieldsRowModel> toProtocolOperationFieldsRows(Collection<OperationFieldMappingRow> operationFieldMappingRows) {
1109 List<EditProtocolOperationFieldsRowModel> result = Lists.newArrayList();
1110
1111 if (operationFieldMappingRows == null) {
1112 operationFieldMappingRows = new ArrayList<>();
1113 }
1114 Map<String, OperationFieldMappingRow> rowsByField = Maps.uniqueIndex(operationFieldMappingRows,
1115 OperationFieldMappingRow::getField);
1116
1117 n("tutti.editFishingOperation.field.gearShootingStartDay");
1118 n("tutti.editFishingOperation.field.gearShootingStartTime");
1119 n("tutti.editFishingOperation.field.gearShootingEndDay");
1120 n("tutti.editFishingOperation.field.gearShootingEndTime");
1121
1122 List<String> properties = Lists.newArrayList(
1123 FishingOperation.PROPERTY_STATION_NUMBER,
1124 FishingOperation.PROPERTY_FISHING_OPERATION_NUMBER,
1125 FishingOperations.PROPERTY_GEAR_SHOOTING_START_DAY,
1126 FishingOperations.PROPERTY_GEAR_SHOOTING_START_TIME,
1127 FishingOperation.PROPERTY_GEAR_SHOOTING_START_LATITUDE,
1128 FishingOperation.PROPERTY_GEAR_SHOOTING_START_LONGITUDE,
1129 FishingOperations.PROPERTY_GEAR_SHOOTING_END_DAY,
1130 FishingOperations.PROPERTY_GEAR_SHOOTING_END_TIME,
1131 FishingOperation.PROPERTY_GEAR_SHOOTING_END_LATITUDE,
1132 FishingOperation.PROPERTY_GEAR_SHOOTING_END_LONGITUDE,
1133 FishingOperation.PROPERTY_FISHING_OPERATION_RECTILIGNE,
1134 FishingOperation.PROPERTY_TRAWL_DISTANCE,
1135 FishingOperation.PROPERTY_FISHING_OPERATION_VALID,
1136 FishingOperation.PROPERTY_MULTIRIG_AGGREGATION,
1137 FishingOperation.PROPERTY_RECORDER_PERSON,
1138 FishingOperation.PROPERTY_GEAR,
1139 FishingOperation.PROPERTY_VESSEL,
1140 FishingOperation.PROPERTY_STRATA,
1141 FishingOperation.PROPERTY_SUB_STRATA,
1142 FishingOperation.PROPERTY_LOCATION,
1143 FishingOperation.PROPERTY_SECONDARY_VESSEL
1144 );
1145
1146
1147 for (String property : properties) {
1148 OperationFieldMappingRow row = rowsByField.get(property);
1149 EditProtocolOperationFieldsRowModel newRow = createOperationFieldRow(property, row != null ? row.getImportColumn() : null);
1150 result.add(newRow);
1151 }
1152 return result;
1153 }
1154
1155 @Override
1156 public void onCloseUI() {
1157 if (log.isDebugEnabled()) {
1158 log.debug("closing: " + ui);
1159 }
1160 clearValidators();
1161 ui.getTabPanel().setSelectedIndex(0);
1162
1163 closeUI(ui.getRtpEditorUI());
1164 closeUI(ui.getZoneEditor());
1165
1166 }
1167
1168 @Override
1169 public boolean quitUI() {
1170 return quitScreen(
1171 getModel().isValid(),
1172 getModel().isModify(),
1173 t("tutti.editProtocol.askCancelEditBeforeLeaving.cancelSaveProtocol"),
1174 t("tutti.editProtocol.askSaveBeforeLeaving.saveProtocol"),
1175 ui.getSaveButton().getAction()
1176 );
1177 }
1178
1179
1180
1181
1182
1183 public void addDoubleListListeners() {
1184 EditProtocolUIModel model = getModel();
1185
1186 for (BeanDoubleList<Caracteristic> list : allDoubleLists) {
1187 String id = (String) list.getClientProperty("_updateListenerId");
1188 UpdateSelectedList updateListener = (UpdateSelectedList) list.getClientProperty("_updateListener");
1189 model.addPropertyChangeListener(id, updateListener);
1190 }
1191 }
1192
1193 public void removeDoubleListListeners() {
1194 EditProtocolUIModel model = getModel();
1195
1196 for (BeanDoubleList<Caracteristic> list : allDoubleLists) {
1197 String id = (String) list.getClientProperty("_updateListenerId");
1198 UpdateSelectedList updateListener = (UpdateSelectedList) list.getClientProperty("_updateListener");
1199 model.removePropertyChangeListener(id, updateListener);
1200 }
1201 }
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 public EditProtocolCaracteristicsRowModel createEditProtocolCaracteristicsRowModel() {
1215 EditProtocolCaracteristicsRowModel newRow = new EditProtocolCaracteristicsRowModel(getModel().getCaracteristics());
1216
1217 newRow.addPropertyChangeListener(evt -> {
1218 EditProtocolCaracteristicsRowModel row = (EditProtocolCaracteristicsRowModel) evt.getSource();
1219 EditProtocolUIModel model = getModel();
1220
1221 if (EditProtocolCaracteristicsRowModel.PROPERTY_IMPORT_COLUMN.equals(evt.getPropertyName())) {
1222 String oldValue = (String) evt.getOldValue();
1223 if (oldValue != null) {
1224 model.decNumberOfRows(oldValue);
1225 }
1226 String newValue = (String) evt.getNewValue();
1227 if (newValue != null) {
1228 model.incNumberOfRows(newValue);
1229 }
1230
1231 recomputeRowsValidState();
1232
1233 } else {
1234 row.setValid(isCaracteristicsRowValid(row));
1235 }
1236
1237 if (row.isValid()) {
1238 model.setModify(true);
1239 }
1240 });
1241
1242 return newRow;
1243 }
1244
1245
1246
1247
1248
1249 protected void initDoubleList(String propertyId,
1250 BeanDoubleList<Caracteristic> widget,
1251 List<Caracteristic> availableCaracteristics,
1252 List<String> selectedCaracteristics) {
1253
1254 initBeanList(widget, availableCaracteristics, new ArrayList<>());
1255
1256 UpdateSelectedList listener = new UpdateSelectedList(widget, getModel().getAllCaracteristic());
1257 widget.putClientProperty("_updateListener", listener);
1258 widget.putClientProperty("_updateListenerId", propertyId);
1259 listener.select(selectedCaracteristics);
1260
1261
1262 List<BeanDoubleList<Caracteristic>> list = new ArrayList<>(allDoubleLists);
1263 list.remove(widget);
1264 widget.getHandler().addFilter(new SelectValuePredicate(list));
1265 widget.getHandler().addFilter(caracteristic -> !getModel().isCaracteristicUsedInMapping(caracteristic));
1266
1267 widget.getHandler().sortData();
1268 }
1269
1270 protected void selectCaracteristics(List<String> ids, JComboBox comboBox) {
1271
1272 Map<String, Caracteristic> allCaracteristic = getModel().getAllCaracteristic();
1273 List<Caracteristic> selection = new ArrayList<>();
1274 if (CollectionUtils.isNotEmpty(ids)) {
1275 for (String id : ids) {
1276 selection.add(allCaracteristic.get(id));
1277 }
1278 }
1279
1280 List<Caracteristic> dataToList = new ArrayList<>(selection);
1281
1282
1283 if (!dataToList.isEmpty() && dataToList.get(0) != null) {
1284 dataToList.add(0, null);
1285 }
1286 SwingUtil.fillComboBox(comboBox, dataToList, null);
1287 }
1288
1289 protected void addLengthClassesColumnToModel(TableColumnModel model, List<String> selectedIds) {
1290
1291 Decorator<Caracteristic> decorator = getDecorator(Caracteristic.class, null);
1292
1293 JComboBox<Caracteristic> comboBox = new JComboBox<>();
1294
1295 getModel().addPropertyChangeListener(EditProtocolUIModel.PROPERTY_LENGTH_CLASSES_PMFM_ID, evt -> {
1296 List<String> ids = (List<String>) evt.getNewValue();
1297 selectCaracteristics(ids, comboBox);
1298 });
1299 comboBox.setRenderer(newListCellRender(decorator));
1300
1301 selectCaracteristics(selectedIds, comboBox);
1302 ObjectToStringConverter converter = BeanUIUtil.newDecoratedObjectToStringConverter(decorator);
1303 BeanUIUtil.decorate(comboBox, converter);
1304 ComboBoxCellEditor editor = new ComboBoxCellEditor(comboBox);
1305
1306 addColumnToModel(model,
1307 editor,
1308 newTableCellRender(decorator),
1309 EditProtocolSpeciesTableModel.LENGTH_STEP_PMFM_ID);
1310 }
1311
1312 protected void addMaturityColumnToModel(TableColumnModel model, List<String> selectedIds) {
1313
1314 Decorator<Caracteristic> decorator = getDecorator(Caracteristic.class, null);
1315
1316 JComboBox<Caracteristic> comboBox = new JComboBox();
1317
1318 getModel().addPropertyChangeListener(EditProtocolUIModel.PROPERTY_MATURITY_PMFM_ID, evt -> {
1319 List<String> ids = (List<String>) evt.getNewValue();
1320 selectCaracteristics(ids, comboBox);
1321 });
1322
1323 comboBox.setRenderer(newListCellRender(decorator));
1324
1325 selectCaracteristics(selectedIds, comboBox);
1326 ObjectToStringConverter converter = BeanUIUtil.newDecoratedObjectToStringConverter(decorator);
1327 BeanUIUtil.decorate(comboBox, converter);
1328 ComboBoxCellEditor editor = new ComboBoxCellEditor(comboBox);
1329
1330 addColumnToModel(model,
1331 editor,
1332 newTableCellRender(decorator),
1333 EditProtocolSpeciesTableModel.MATURITY_PMFM_ID);
1334 }
1335
1336 protected void addCpsPmfmColumnToModel(TableColumnModel model) {
1337
1338 Decorator<CaracteristicQualitativeValue> caracteristicQualitativeValueDecorator =
1339 getDecorator(CaracteristicQualitativeValue.class, null);
1340
1341 addComboDataColumnToModel(model,
1342 EditProtocolSpeciesTableModel.CALCIFIED_PIECES_SAMPLING_TYPE_PMFM_ID,
1343 caracteristicQualitativeValueDecorator,
1344 getDataContext().getCpsTypeValues());
1345
1346 }
1347
1348 protected void initTable(final JXTable table,
1349 DefaultTableColumnModelExt columnModel,
1350 TableColumnExt speciesColumn,
1351 ColumnIdentifier rtpIdentifier,
1352 List<EditProtocolSpeciesRowModel> rows,
1353 ListSelectionListener selectionListener) {
1354
1355 EditProtocolSpeciesTableModel tableModel = new EditProtocolSpeciesTableModel(getModel()::newRow, columnModel);
1356 table.setModel(tableModel);
1357 table.setColumnModel(columnModel);
1358
1359 JTableHeader tableHeader = table.getTableHeader();
1360
1361
1362 tableHeader.setReorderingAllowed(false);
1363
1364 addHighlighters(table);
1365 if (rtpIdentifier != null) {
1366 addRtpHighlighter(table, rtpIdentifier);
1367 }
1368
1369
1370 SwingUtil.scrollToTableSelection(table);
1371
1372
1373 table.getSelectionModel().addListSelectionListener(selectionListener);
1374
1375
1376 tableModel.addTableModelListener(e -> {
1377 getModel().setModify(true);
1378
1379 int type = e.getType();
1380 if (type == TableModelEvent.DELETE ||
1381 type == TableModelEvent.INSERT ||
1382 e.getLastRow() == Integer.MAX_VALUE) {
1383
1384
1385 TableColumnExt tableColumn = (TableColumnExt) table.getColumns().get(0);
1386
1387
1388 TuttiDecorator.TuttiDecoratorComparator<Species> comparator =
1389 (TuttiDecorator.TuttiDecoratorComparator<Species>)
1390 tableColumn.getComparator();
1391
1392
1393 TuttiDecorator<Species> decorator =
1394 SpeciesBatchRowHelper.getSpeciesColumnDecorator(tableColumn);
1395
1396 boolean comparatorNull = comparator == null;
1397 if (comparatorNull) {
1398
1399
1400 comparator = decorator.getCurrentComparator();
1401 }
1402
1403
1404 comparator.init(decorator, tableModel.getSpeciesList());
1405
1406 if (comparatorNull) {
1407
1408
1409 tableColumn.setComparator(comparator);
1410 }
1411 }
1412 });
1413
1414
1415
1416 SpeciesBatchRowHelper.installSpeciesColumnComparatorPopup(
1417 table,
1418 speciesColumn,
1419 null,
1420 t("tutti.species.refTaxCode.tip"),
1421 t("tutti.species.name.tip")
1422 );
1423
1424
1425 tableModel.setRows(rows);
1426 }
1427
1428 protected void addRtpHighlighter(JXTable table, ColumnIdentifier identifier) {
1429 Color cellWithValueColor = getConfig().getColorCellWithValue();
1430
1431 Highlighter commentHighlighter = TuttiUIUtil.newBackgroundColorHighlighter(
1432 new HighlightPredicate.AndHighlightPredicate(
1433 new HighlightPredicate.IdentifierHighlightPredicate(identifier),
1434
1435 (renderer, adapter) -> (boolean) adapter.getValue()), cellWithValueColor);
1436 table.addHighlighter(commentHighlighter);
1437 }
1438
1439 protected EditProtocolOperationFieldsRowModel createOperationFieldRow(String property, String column) {
1440 EditProtocolOperationFieldsRowModel newRow = new EditProtocolOperationFieldsRowModel();
1441 newRow.addPropertyChangeListener(evt -> {
1442 EditProtocolUIModel model = getModel();
1443
1444
1445 if (EditProtocolOperationFieldsRowModel.PROPERTY_IMPORT_COLUMN.equals(evt.getPropertyName())) {
1446 String oldValue = (String) evt.getOldValue();
1447 if (oldValue != null) {
1448 model.decNumberOfRows(oldValue);
1449 }
1450 String newValue = (String) evt.getNewValue();
1451 if (newValue != null) {
1452 model.incNumberOfRows(newValue);
1453 }
1454
1455 recomputeRowsValidState();
1456 }
1457 });
1458 newRow.setValid(true);
1459 newRow.setField(property);
1460 newRow.setImportColumn(column);
1461 newRow.setValid(true);
1462 newRow.addPropertyChangeListener(evt -> getModel().setModify(true));
1463 return newRow;
1464 }
1465
1466 protected void recomputeRowsValidState() {
1467 EditProtocolUIModel model = getModel();
1468
1469 for (EditProtocolCaracteristicsRowModel row : model.getCaracteristicMappingRows()) {
1470 row.setValid(isCaracteristicsRowValid(row));
1471 }
1472
1473 for (EditProtocolOperationFieldsRowModel row : model.getOperationFieldMappingRows()) {
1474 row.setValid(isOperationFieldsRowValid(row));
1475 }
1476
1477 getCaracteristicsMappingTable().repaint();
1478 getOperationFieldsMappingTable().repaint();
1479 }
1480
1481 protected boolean isOperationFieldsRowValid(EditProtocolOperationFieldsRowModel row) {
1482 EditProtocolUIModel model = getModel();
1483 String importColumn = row.getImportColumn();
1484 return importColumn == null || model.numberOfRows(importColumn) < 2;
1485 }
1486
1487 protected boolean isCaracteristicsRowValid(EditProtocolCaracteristicsRowModel row) {
1488 EditProtocolUIModel model = getModel();
1489 String importColumn = row.getImportColumn();
1490 return row.getType() != null &&
1491 (importColumn == null || model.numberOfRows(importColumn) < 2);
1492 }
1493
1494 protected void populateImportColumnTableEditors() {
1495 Collection<String> importColumns = getModel().getImportColumns();
1496 ArrayList<String> dataToList = new ArrayList<>();
1497
1498 if (importColumns != null) {
1499 dataToList.addAll(importColumns);
1500
1501
1502 if (!dataToList.isEmpty() && dataToList.get(0) != null) {
1503 dataToList.add(0, null);
1504 }
1505
1506 } else {
1507 dataToList.add(null);
1508 }
1509
1510 populateImportColumnTableEditor(getUI().getCaracteristicsMappingTable(), 2, dataToList);
1511 populateImportColumnTableEditor(getUI().getOperationFieldsMappingTable(), 1, dataToList);
1512 }
1513
1514 protected void populateImportColumnTableEditor(JXTable table, int columnIndex, ArrayList<String> dataToList) {
1515 JComboBox comboBox = new JComboBox();
1516 SwingUtil.fillComboBox(comboBox, dataToList, null);
1517
1518 TableColumnExt col = table.getColumnExt(columnIndex);
1519 ComboBoxCellEditor editor = new ComboBoxCellEditor(comboBox);
1520 col.setCellEditor(editor);
1521 }
1522
1523 public void permuteCaracteristics(int selectedRow, int newRow) {
1524
1525 getCaracteristicMappingTableModel().permuteEntry(selectedRow, newRow);
1526 getCaracteristicsMappingTable().getSelectionModel().setSelectionInterval(newRow, newRow);
1527
1528
1529 getModel().setCaracteristicMappingRows(getCaracteristicMappingTableModel().getRows());
1530 getModel().setModify(true);
1531
1532 }
1533
1534 protected static class UpdateSelectedList implements PropertyChangeListener {
1535
1536 private final BeanDoubleListModel<Caracteristic> model;
1537
1538 private final Map<String, Caracteristic> caracteristicMap;
1539
1540 public UpdateSelectedList(BeanDoubleList<Caracteristic> doubleList,
1541 Map<String, Caracteristic> caracteristicMap) {
1542 this.model = doubleList.getModel();
1543 this.caracteristicMap = caracteristicMap;
1544 }
1545
1546 private boolean valueIsAdjusting;
1547
1548 @Override
1549 public void propertyChange(PropertyChangeEvent evt) {
1550
1551 if (!valueIsAdjusting) {
1552
1553 valueIsAdjusting = true;
1554
1555 try {
1556 List<String> selectedIds = (List<String>) evt.getNewValue();
1557 if (log.isInfoEnabled()) {
1558 log.info("[" + evt.getPropertyName() + "] selected ids: " + selectedIds);
1559 }
1560
1561 select(selectedIds);
1562 } finally {
1563 valueIsAdjusting = false;
1564 }
1565 }
1566 }
1567
1568 public void select(List<String> selectedIds) {
1569
1570 List<Caracteristic> selection = Lists.newArrayList();
1571 if (CollectionUtils.isNotEmpty(selectedIds)) {
1572 for (String selectedId : selectedIds) {
1573 Caracteristic e = caracteristicMap.get(selectedId);
1574 Preconditions.checkNotNull(e, "Could not find caracteristic with id: " + selectedId);
1575 selection.add(e);
1576 }
1577 }
1578 model.setSelected(selection);
1579 }
1580 }
1581
1582 protected static class SelectValuePredicate implements Predicate<Caracteristic> {
1583
1584 protected final List<BeanDoubleList<Caracteristic>> lists;
1585
1586 public SelectValuePredicate(List<BeanDoubleList<Caracteristic>> lists) {
1587 this.lists = lists;
1588 }
1589
1590 @Override
1591 public boolean apply(Caracteristic input) {
1592
1593 boolean result = true;
1594 for (BeanDoubleList<Caracteristic> list : lists) {
1595 if (list.getModel().getSelected().contains(input)) {
1596 result = false;
1597 break;
1598 }
1599 }
1600 return result;
1601 }
1602 }
1603
1604 protected void initJTree(JTree tree) {
1605 tree.getModel().addTreeModelListener(new ExpandOnInsertTreeModelListener(tree));
1606 JAXXWidgetUtil.expandTree(tree);
1607 }
1608
1609 private static class ExpandOnInsertTreeModelListener implements TreeModelListener {
1610
1611 private final JTree tree;
1612
1613 private ExpandOnInsertTreeModelListener(JTree tree) {
1614 this.tree = tree;
1615 }
1616
1617 @Override
1618 public void treeNodesChanged(TreeModelEvent e) {
1619 }
1620
1621 @Override
1622 public void treeNodesInserted(TreeModelEvent e) {
1623 tree.expandPath(e.getTreePath());
1624 }
1625
1626 @Override
1627 public void treeNodesRemoved(TreeModelEvent e) {
1628 }
1629
1630 @Override
1631 public void treeStructureChanged(TreeModelEvent e) {
1632 }
1633
1634 }
1635
1636 private static class LengthStepCaracteristicCellRenderer implements ListCellRenderer<Caracteristic> {
1637
1638 private final CaracteristicsCount caracteristicsCount;
1639 private final Color notRemovableColor;
1640
1641 private final ListCellRenderer<? super Caracteristic> defaultRenderer;
1642
1643 LengthStepCaracteristicCellRenderer(Color notRemovableColor, CaracteristicsCount caracteristicsCount, ListCellRenderer<? super Caracteristic> defaultRenderer) {
1644 this.notRemovableColor = notRemovableColor;
1645 this.caracteristicsCount = caracteristicsCount;
1646 this.defaultRenderer = defaultRenderer;
1647 }
1648
1649 @Override
1650 public Component getListCellRendererComponent(JList<? extends Caracteristic> list, Caracteristic value, int index, boolean isSelected, boolean cellHasFocus) {
1651 Component result = defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
1652
1653 if (isSelected && caracteristicsCount.isCaracteristicUsed(value)) {
1654 result.setBackground(notRemovableColor.darker());
1655 }
1656 return result;
1657 }
1658 }
1659
1660 private class MaturityCaracteristicCellRenderer implements ListCellRenderer<Caracteristic> {
1661
1662 public static final String TEXT_PATTERN = "<html><body><strong>%s</strong> :<ul><li>%s</li></ul><strong>%s</strong> :<ul><li>%s</li></ul></body></html>";
1663
1664 private final CaracteristicsCount caracteristicsCount;
1665 private final ListCellRenderer<? super Caracteristic> defaultRenderer;
1666
1667 private Color validColor = getConfig().getColorCellWithValue();
1668
1669 private Color invalidColor = getConfig().getColorRowInvalid();
1670
1671 private Color notRemovableColor = getConfig().getColorWarningRow();
1672
1673 MaturityCaracteristicCellRenderer(CaracteristicsCount caracteristicsCount, ListCellRenderer<? super Caracteristic> defaultRenderer) {
1674 this.caracteristicsCount = caracteristicsCount;
1675 this.defaultRenderer = defaultRenderer;
1676 }
1677
1678 @Override
1679 public Component getListCellRendererComponent(JList<? extends Caracteristic> list, Caracteristic value, int index, boolean isSelected, boolean cellHasFocus) {
1680 Component result = defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
1681
1682 Color backgroud;
1683 if (isSelected && caracteristicsCount.isCaracteristicUsed(value)) {
1684 backgroud = notRemovableColor;
1685
1686 } else if (!EditProtocolUIHandler.this.getModel().isMaturityValid(value)) {
1687 backgroud = invalidColor;
1688 } else {
1689 backgroud = validColor;
1690 }
1691 if (isSelected) {
1692 backgroud = backgroud.darker();
1693 }
1694 result.setBackground(backgroud);
1695
1696 if (result instanceof JComponent) {
1697
1698 ((JComponent) result).setToolTipText(createToolTipText(value));
1699 }
1700 return result;
1701 }
1702
1703 private String createToolTipText(Caracteristic caracteristic) {
1704 String tooltip = null;
1705
1706 if (caracteristic != null && getModel().isMaturityValid(caracteristic.getId())) {
1707
1708 MaturityCaracteristic maturityCaracteristic = getModel().getMaturityCaracteristic(caracteristic.getId());
1709 List<String> matureStates = new ArrayList<>();
1710 List<String> immatureStates = new ArrayList<>();
1711
1712 caracteristic.getQualitativeValue().forEach(state -> {
1713 if (maturityCaracteristic.containsMatureStateIds(state.getId())) {
1714 matureStates.add(decorate(state));
1715 } else {
1716 immatureStates.add(decorate(state));
1717 }
1718 });
1719
1720 tooltip = String.format(TEXT_PATTERN, t("tutti.editProtocol.field.maturity.immature.tip"), StringUtils.join(immatureStates, "</li><li>"),
1721 t("tutti.editProtocol.field.maturity.mature.tip"), StringUtils.join(matureStates, "</li><li>"));
1722 }
1723
1724 return tooltip;
1725 }
1726
1727 }
1728 }