1 package fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency;
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 fr.ifremer.tutti.caliper.feed.event.CaliperFeedReaderEvent;
26 import fr.ifremer.tutti.caliper.feed.event.CaliperFeedReaderListener;
27 import fr.ifremer.tutti.caliper.feed.record.CaliperFeedReaderMeasureRecord;
28 import fr.ifremer.tutti.ichtyometer.feed.event.IchtyometerFeedReaderEvent;
29 import fr.ifremer.tutti.ichtyometer.feed.event.IchtyometerFeedReaderListener;
30 import fr.ifremer.tutti.ichtyometer.feed.record.IchtyometerFeedReaderMeasureRecord;
31 import fr.ifremer.tutti.persistence.ProgressionModel;
32 import fr.ifremer.tutti.persistence.entities.TuttiEntities;
33 import fr.ifremer.tutti.persistence.entities.data.CopyIndividualObservationMode;
34 import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
35 import fr.ifremer.tutti.persistence.entities.data.SampleCategoryModel;
36 import fr.ifremer.tutti.persistence.entities.protocol.Rtp;
37 import fr.ifremer.tutti.persistence.entities.protocol.SpeciesProtocol;
38 import fr.ifremer.tutti.persistence.entities.protocol.TuttiProtocol;
39 import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
40 import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue;
41 import fr.ifremer.tutti.persistence.entities.referential.Sexs;
42 import fr.ifremer.tutti.persistence.entities.referential.Species;
43 import fr.ifremer.tutti.persistence.entities.referential.TaxonCache;
44 import fr.ifremer.tutti.persistence.entities.referential.TaxonCaches;
45 import fr.ifremer.tutti.service.DecoratorService;
46 import fr.ifremer.tutti.service.TuttiDataContext;
47 import fr.ifremer.tutti.service.cruise.CruiseCache;
48 import fr.ifremer.tutti.service.cruise.CruiseCacheLoader;
49 import fr.ifremer.tutti.type.WeightUnit;
50 import fr.ifremer.tutti.ui.swing.TuttiUIContext;
51 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.EditSpeciesBatchPanelUI;
52 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.SpeciesOrBenthosBatchUISupport;
53 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchRowModel;
54 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency.SpeciesFrequencyCellComponent.FrequencyCellEditor;
55 import fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency.actions.ApplySpeciesFrequencyRafaleAction;
56 import fr.ifremer.tutti.ui.swing.util.SoundEngine;
57 import fr.ifremer.tutti.ui.swing.util.TuttiBeanMonitor;
58 import fr.ifremer.tutti.ui.swing.util.TuttiUI;
59 import fr.ifremer.tutti.ui.swing.util.TuttiUIUtil;
60 import fr.ifremer.tutti.ui.swing.util.caracteristics.CaracteristicMapColumnRowModel;
61 import fr.ifremer.tutti.ui.swing.util.caracteristics.CaracteristicMapColumnUIHandler;
62 import fr.ifremer.tutti.ui.swing.util.caracteristics.CaracteristicMapEditorUI;
63 import fr.ifremer.tutti.ui.swing.util.table.AbstractTuttiTableUIHandler;
64 import fr.ifremer.tutti.ui.swing.util.table.CaracteristicColumnIdentifier;
65 import fr.ifremer.tutti.util.Units;
66 import jaxx.runtime.swing.editor.bean.BeanFilterableComboBox;
67 import jaxx.runtime.validator.swing.SwingValidator;
68 import org.apache.commons.collections4.CollectionUtils;
69 import org.apache.commons.io.IOUtils;
70 import org.apache.commons.logging.Log;
71 import org.apache.commons.logging.LogFactory;
72 import org.jdesktop.swingx.JXTable;
73 import org.jdesktop.swingx.decorator.ComponentAdapter;
74 import org.jdesktop.swingx.decorator.HighlightPredicate;
75 import org.jdesktop.swingx.decorator.Highlighter;
76 import org.jdesktop.swingx.table.DefaultTableColumnModelExt;
77 import org.jdesktop.swingx.table.TableColumnExt;
78 import org.jdesktop.swingx.table.TableColumnModelExt;
79 import org.nuiton.decorator.Decorator;
80 import org.nuiton.jaxx.application.ApplicationBusinessException;
81 import org.nuiton.jaxx.application.swing.AbstractApplicationUIHandler;
82 import org.nuiton.jaxx.application.swing.action.ApplicationUIAction;
83 import org.nuiton.jaxx.application.swing.table.ColumnIdentifier;
84
85 import javax.swing.JComponent;
86 import javax.swing.JLabel;
87 import javax.swing.JOptionPane;
88 import javax.swing.JSplitPane;
89 import javax.swing.JTable;
90 import javax.swing.JTextField;
91 import javax.swing.SwingUtilities;
92 import javax.swing.table.TableCellEditor;
93 import javax.swing.table.TableCellRenderer;
94 import javax.swing.table.TableColumnModel;
95 import java.awt.Color;
96 import java.awt.Component;
97 import java.awt.Font;
98 import java.awt.event.ActionEvent;
99 import java.awt.event.KeyAdapter;
100 import java.awt.event.KeyEvent;
101 import java.beans.PropertyChangeEvent;
102 import java.beans.PropertyChangeListener;
103 import java.beans.PropertyVetoException;
104 import java.io.Serializable;
105 import java.util.ArrayList;
106 import java.util.List;
107 import java.util.Map;
108 import java.util.Objects;
109 import java.util.Optional;
110 import javax.swing.KeyStroke;
111
112 import static org.nuiton.i18n.I18n.t;
113
114
115
116
117
118 public class SpeciesFrequencyUIHandler extends AbstractTuttiTableUIHandler<SpeciesFrequencyRowModel, SpeciesFrequencyUIModel, SpeciesFrequencyUI>
119 implements CaracteristicMapColumnUIHandler {
120
121
122 private static final Log log = LogFactory.getLog(SpeciesFrequencyUIHandler.class);
123
124 public static final String OBS_TABLE_CARD = "obsTableCard";
125 public static final String EDIT_CARACTERISTICS_CARD = "editCaracteristicsCard";
126
127 private FrequencyCellEditor frequencyEditor;
128
129 private TaxonCache taxonCache;
130
131 private Map<String, Caracteristic> lengthStepCaracteristics;
132
133
134
135
136
137
138 protected WeightUnit weightUnit;
139
140
141
142
143 protected final IchtyometerFeedReaderListener ichtyometerFeedReaderListener;
144
145
146
147 protected final CaliperFeedReaderListener caliperFeedReaderListener;
148
149
150
151 protected final PropertyChangeListener listenIchtyomerIsConnected;
152
153
154
155 protected final PropertyChangeListener listenCaliperIsConnected;
156
157 protected ApplySpeciesFrequencyRafaleAction applySpeciesFrequencyRafaleAction;
158
159 protected SpeciesOrBenthosBatchUISupport speciesOrBenthosBatchUISupport;
160
161 protected IndividualObservationBatchTableHandler individualObservationBatchTableHandler;
162 protected AverageWeightsHistogramHandler averageWeightsHistogramHandler;
163 protected FrequenciesHistogramHandler frequenciesHistogramHandler;
164 protected SamplingNotificationZoneHandler samplingNotificationZoneHandler;
165
166 protected Decorator<Caracteristic> caracteristicDecorator;
167 protected Decorator<Caracteristic> caracteristicTipDecorator;
168 protected Decorator<CaracteristicQualitativeValue> caracteristicQualitativeDecorator;
169 protected SoundEngine soundEngine;
170 protected PropertyChangeListener listenFishingOperationReloadInDataContext;
171
172 public SpeciesFrequencyUIHandler() {
173
174 super(SpeciesFrequencyRowModel.PROPERTY_LENGTH_STEP,
175 SpeciesFrequencyRowModel.PROPERTY_NUMBER,
176 SpeciesFrequencyRowModel.PROPERTY_WEIGHT);
177
178 this.ichtyometerFeedReaderListener = new IchtyometerFeedReaderListener() {
179
180 @Override
181 public void recordRead(IchtyometerFeedReaderEvent event) {
182 final IchtyometerFeedReaderMeasureRecord record = event.getRecord();
183
184 SwingUtilities.invokeLater(
185 () -> {
186 if (!getModel().isSimpleCountingMode()) {
187
188
189 consumeIchtyometerFeedRecord(record);
190 }
191 }
192 );
193 }
194 };
195
196 this.caliperFeedReaderListener = new CaliperFeedReaderListener() {
197
198 @Override
199 public void recordRead(CaliperFeedReaderEvent event) {
200 final CaliperFeedReaderMeasureRecord record = event.getRecord();
201
202 SwingUtilities.invokeLater(
203 () -> {
204 if (!getModel().isSimpleCountingMode()) {
205
206
207 consumeCaliperFeedRecord(record);
208 }
209 }
210 );
211 }
212 };
213
214 this.listenIchtyomerIsConnected = new PropertyChangeListener() {
215 @Override
216 public void propertyChange(PropertyChangeEvent evt) {
217 boolean connected = (boolean) evt.getNewValue();
218
219 if (connected && SpeciesFrequencyUIHandler.this.frequencyEditor != null) {
220
221
222 SpeciesFrequencyUIHandler.this.listenItchtyometer();
223 }
224
225 SwingUtilities.invokeLater(SpeciesFrequencyUIHandler.this::updateLogVisibility);
226 }
227 };
228
229 this.listenCaliperIsConnected = new PropertyChangeListener() {
230 @Override
231 public void propertyChange(PropertyChangeEvent evt) {
232 boolean connected = (boolean) evt.getNewValue();
233
234 if (connected && SpeciesFrequencyUIHandler.this.frequencyEditor != null) {
235
236
237 SpeciesFrequencyUIHandler.this.listenCaliper();
238 }
239
240 SwingUtilities.invokeLater(SpeciesFrequencyUIHandler.this::updateLogVisibility);
241 }
242 };
243
244
245 this.listenFishingOperationReloadInDataContext = new PropertyChangeListener() {
246 @Override
247 public void propertyChange(PropertyChangeEvent event) {
248 TuttiDataContext source = (TuttiDataContext) event.getSource();
249 FishingOperation fishingOperation = source.getFishingOperation();
250 if (log.isInfoEnabled()) {
251 log.info("Reloading fishing operation in model: " + fishingOperation);
252 }
253 SpeciesFrequencyUIHandler.this.getModel().setFishingOperation(fishingOperation);
254 }
255 };
256
257 }
258
259
260
261
262
263 @Override
264 public SpeciesFrequencyTableModel getTableModel() {
265 return (SpeciesFrequencyTableModel) getTable().getModel();
266 }
267
268 @Override
269 public JXTable getTable() {
270 return ui.getTable();
271 }
272
273 @Override
274 public boolean isRowValid(SpeciesFrequencyRowModel row) {
275
276 SpeciesFrequencyUIModel model = getModel();
277 return model.isRowValid(row);
278
279 }
280
281 @Override
282 public CaracteristicMapEditorUI getCaracteristicMapEditor() {
283 return ui.getObsCaracteristicCaracteristicMapEditor();
284 }
285
286 @Override
287 public void showCaracteristicMapEditor(CaracteristicMapColumnRowModel editRow) {
288 IndividualObservationBatchRowModel row = (IndividualObservationBatchRowModel) editRow;
289 WeightUnit individualObservationWeightUnit = getConfig().getIndividualObservationWeightUnit();
290 String title = String.format("<html><body style='color:black;'><strong>%s - %s %s - %s %s</strong> - %s</body></html>",
291 row.getRankOrder(),
292 row.getSize(),
293 getModel().getLengthStepCaracteristicUnit(),
294 individualObservationWeightUnit.renderWeight(row.getWeight()),
295 individualObservationWeightUnit.getShortLabel(),
296 t("tutti.editIndividualObservationBatch.table.header.otherCaracteristics"));
297 ui.getObsCaracteristicMapEditorReminderLabel().setTitle(title);
298 ui.getObsPanelLayout().setSelected(EDIT_CARACTERISTICS_CARD);
299
300 }
301
302 @Override
303 public void hideCaracteristicMapEditor() {
304 ui.getObsPanelLayout().setSelected(OBS_TABLE_CARD);
305 }
306
307 @Override
308 protected void onModelRowsChanged(List<SpeciesFrequencyRowModel> rows) {
309
310 SpeciesFrequencyUIModel model = getModel();
311
312 model.reloadRows();
313
314 getTableModel().setRows(rows);
315
316
317 SpeciesFrequencyLogsTableModel logsTableModel = (SpeciesFrequencyLogsTableModel) ui.getLogsTable().getModel();
318 logsTableModel.setRows(new ArrayList<>());
319
320 getModel().setModify(false);
321
322 }
323
324 @Override
325 protected void onRowModified(int rowIndex,
326 SpeciesFrequencyRowModel row,
327 String propertyName,
328 Object oldValue,
329 Object newValue) {
330
331
332
333
334 }
335
336 @Override
337 protected void saveSelectedRowIfRequired(TuttiBeanMonitor<SpeciesFrequencyRowModel> rowMonitor,
338 SpeciesFrequencyRowModel row) {
339 }
340
341 @Override
342 protected void onRowValidStateChanged(int rowIndex,
343 SpeciesFrequencyRowModel row,
344 Boolean oldValue,
345 Boolean newValue) {
346 super.onRowValidStateChanged(rowIndex, row, oldValue, newValue);
347 ui.getValidator().doValidate();
348 }
349
350
351
352
353
354 @Override
355 public SwingValidator<SpeciesFrequencyUIModel> getValidator() {
356 return ui.getValidator();
357 }
358
359 @Override
360 public void beforeInit(SpeciesFrequencyUI ui) {
361
362 super.beforeInit(ui);
363
364 this.speciesOrBenthosBatchUISupport = ui.getContextValue(SpeciesOrBenthosBatchUISupport.class, ui.getSpeciesOrBenthosContext());
365
366 this.weightUnit = speciesOrBenthosBatchUISupport.getWeightUnit();
367 this.caracteristicDecorator = getDecorator(Caracteristic.class, DecoratorService.CARACTERISTIC_PARAMETER_ONLY_WITH_UNIT);
368 this.caracteristicTipDecorator = getDecorator(Caracteristic.class, DecoratorService.CARACTERISTIC_WITH_UNIT);
369 this.caracteristicQualitativeDecorator = getDecorator(CaracteristicQualitativeValue.class, null);
370 this.soundEngine = getContext().getSoundEngine();
371
372 Caracteristic sexCaracteristic = getPersistenceService().getSexCaracteristic();
373
374 TuttiDataContext dataContext = getDataContext();
375 SampleCategoryModel sampleCategoryModel = dataContext.getSampleCategoryModel();
376
377
378 List<Caracteristic> protocolIndividualObservationCaracteristics = new ArrayList<>(dataContext.getDefaultIndividualObservationCaracteristics());
379
380 Optional<CruiseCache> optionalCruiseCache = dataContext.getOptionalCruiseCache();
381 if (!optionalCruiseCache.isPresent()) {
382
383
384
385 TuttiUIContext uiContext = getContext();
386 ProgressionModel progressionModel = new ProgressionModel();
387 progressionModel.setTotal(1);
388
389 CruiseCacheLoader cruiseCacheLoader = uiContext.createCruiseCacheLoader(progressionModel);
390 dataContext.loadCruiseCache(cruiseCacheLoader);
391 optionalCruiseCache = dataContext.getOptionalCruiseCache();
392 if(log.isDebugEnabled()) {
393 log.debug("Cruise cache" + optionalCruiseCache.get());
394 }
395 }
396
397 TuttiProtocol protocol = dataContext.isProtocolFilled() ? dataContext.getProtocol() : null;
398
399 SpeciesFrequencyUIModel model = new SpeciesFrequencyUIModel(speciesOrBenthosBatchUISupport,
400 getConfig().getIndividualObservationWeightUnit(),
401 sampleCategoryModel,
402 sexCaracteristic,
403 protocolIndividualObservationCaracteristics,
404 optionalCruiseCache.get(),
405 dataContext.getCruiseId(),
406 protocol);
407
408 this.ui.setContextValue(model);
409
410
411 getContext().addPropertyChangeListener(TuttiUIContext.PROPERTY_ICHTYOMETER_CONNECTED, listenIchtyomerIsConnected);
412
413
414 getContext().addPropertyChangeListener(TuttiUIContext.PROPERTY_CALIPER_CONNECTED, listenCaliperIsConnected);
415
416
417 getDataContext().addPropertyChangeListener(TuttiDataContext.PROPERTY_FISHING_OPERATION_ID, listenFishingOperationReloadInDataContext);
418
419 }
420
421 @Override
422 public void afterInit(SpeciesFrequencyUI ui) {
423
424
425 getUI().getSearchSpeciesInPrevCatchesButton().setAccelerator(
426 KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.CTRL_MASK));
427 getUI().getSearchSpeciesInNextCatchesButton().setAccelerator(
428 KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
429
430 applySpeciesFrequencyRafaleAction = new ApplySpeciesFrequencyRafaleAction(ui);
431
432 initUI(ui);
433
434 List<Caracteristic> lengthStepCaracteristics = new ArrayList<>(getDataContext().getLengthStepCaracteristics());
435
436 this.lengthStepCaracteristics = TuttiEntities.splitById(lengthStepCaracteristics);
437
438 SpeciesFrequencyUIModel model = getModel();
439
440
441 if (SpeciesOrBenthosBatchUISupport.SPECIES.equals(ui.getSpeciesOrBenthosContext())) {
442 taxonCache = TaxonCaches.createSpeciesCacheWithoutVernacularCode(getPersistenceService(), getDataContext().getProtocol());
443 } else {
444 taxonCache = TaxonCaches.createBenthosCacheWithoutVernacularCode(getPersistenceService(), getDataContext().getProtocol());
445 }
446
447 Caracteristic modelCaracteristic = model.getLengthStepCaracteristic();
448 initBeanFilterableComboBox(this.ui.getLengthStepCaracteristicComboBox(),
449 lengthStepCaracteristics,
450 modelCaracteristic);
451
452
453 model.setStep(modelCaracteristic);
454
455 model.setMinStep(null);
456 model.setMaxStep(null);
457
458 ui.getRafaleStepField().getTextField().addKeyListener(new KeyAdapter() {
459
460 @Override
461 public void keyReleased(KeyEvent e) {
462 if (e.getKeyCode() == KeyEvent.VK_ENTER) {
463 e.consume();
464 Float step = (Float) SpeciesFrequencyUIHandler.this.ui.getRafaleStepField().getModel().getNumberValue();
465
466 applySpeciesFrequencyRafaleAction.applyRafaleStep(step, false);
467
468
469 JTextField field = (JTextField) e.getSource();
470 field.selectAll();
471 }
472 }
473 });
474
475
476 model.addPropertyChangeListener(SpeciesFrequencyUIModel.PROPERTY_LENGTH_STEP_CARACTERISTIC, evt -> {
477 Caracteristic newValue = (Caracteristic) evt.getNewValue();
478
479 model.setStep(newValue);
480
481 if (CollectionUtils.isNotEmpty(getModel().getRows())) {
482 for (SpeciesFrequencyRowModel rowModel : getModel().getRows()) {
483 rowModel.setLengthStepCaracteristic(newValue);
484 recomputeRowValidState(rowModel);
485 }
486 }
487
488 if (!model.isInitBatchEdition()) {
489
490
491 SpeciesFrequencyUIHandler.this.ui.getValidator().doValidate();
492 }
493
494
495 });
496
497
498 model.addPropertyChangeListener(SpeciesFrequencyUIModel.PROPERTY_LENGTH_STEP_CARACTERISTIC_UNIT, evt -> {
499
500 String unit = (String) evt.getNewValue();
501
502 if (unit == null) {
503
504 unit = t("tutti.editSpeciesFrequencies.unkownStepUnit");
505 }
506
507 getUI().getMinStepLabel().setText(Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.field.minStep"), unit));
508 getUI().getMinStepLabel().setToolTipText(Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.field.minStep.tip"), unit));
509
510 getUI().getMaxStepLabel().setText(Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.field.maxStep"), unit));
511 getUI().getMaxStepLabel().setToolTipText(Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.field.maxStep.tip"), unit));
512
513 getUI().getRafaleStepLabel().setText(Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.field.rafaleStep"), unit));
514 getUI().getRafaleStepLabel().setToolTipText(Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.field.rafaleStep.tip"), unit));
515
516 TableColumnExt column = (TableColumnExt) getUI().getTable().getColumn(SpeciesFrequencyTableModel.LENGTH_STEP);
517 String lengthStepLabelWithUnit = Units.getLabelWithUnit(t("tutti.editSpeciesFrequencies.table.header.lengthStep"), unit);
518 column.setHeaderValue(lengthStepLabelWithUnit);
519 column.setToolTipText(lengthStepLabelWithUnit);
520
521 column = (TableColumnExt) getUI().getObsTable().getColumn(IndividualObservationBatchTableModel.SIZE);
522 column.setHeaderValue(Units.getLabelWithUnit(t("tutti.editIndividualObservationBatch.table.header.size"), unit));
523 column.setToolTipText(Units.getLabelWithUnit(t("tutti.editIndividualObservationBatch.table.header.size"), unit));
524
525 });
526
527
528 model.addPropertyChangeListener(SpeciesFrequencyUIModel.PROPERTY_FREQUENCIES_CONFIGURATION_MODE, evt -> {
529 FrequencyConfigurationMode newValue = (FrequencyConfigurationMode) evt.getNewValue();
530 SwingUtilities.invokeLater(
531 () -> {
532 JComponent componentToFocus = getComponentToFocus(newValue);
533 if (componentToFocus != null) {
534 componentToFocus.grabFocus();
535 }
536 updateLogVisibility();
537 }
538 );
539 });
540
541
542 model.addVetoableChangeListener(SpeciesFrequencyUIModel.PROPERTY_COPY_RTP_WEIGHTS, evt -> {
543
544 boolean newCopyRtpWeights = (boolean) evt.getNewValue();
545
546 if (newCopyRtpWeights) {
547
548 long rowsWithUserData = model.getRows().stream().filter(SpeciesFrequencyRowModel::withWeight).count();
549
550 if (rowsWithUserData > 0) {
551
552 String htmlMessage = String.format(
553 CONFIRMATION_FORMAT,
554 t("tutti.editSpeciesFrequencies.changeCopyRtpWeights.confirm.message"),
555 t("tutti.editSpeciesFrequencies.changeCopyRtpWeights.confirm.help"));
556 int i = JOptionPane.showConfirmDialog(
557 getTopestUI(),
558 htmlMessage,
559 t("tutti.editSpeciesFrequencies.changeCopyRtpWeights.confirm.title"),
560 JOptionPane.OK_CANCEL_OPTION,
561 JOptionPane.QUESTION_MESSAGE);
562
563 if (i == JOptionPane.CANCEL_OPTION) {
564 throw new PropertyVetoException("The user does not want to erase his data.", evt);
565 }
566 }
567 }
568 });
569
570 model.addPropertyChangeListener(SpeciesFrequencyUIModel.PROPERTY_COPY_RTP_WEIGHTS, evt -> {
571 SpeciesFrequencyUIModel source = (SpeciesFrequencyUIModel) evt.getSource();
572 source.getRows().forEach(source::computeRowWeightWithRtp);
573 source.reloadRows();
574 source.getFrequencyTableModel().fireTableDataChanged();
575 });
576
577
578 model.getIndividualObservationModel().addPropertyChangeListener(IndividualObservationBatchUIModel.PROPERTY_ROWS_IN_ERROR, evt -> {
579 IndividualObservationBatchUIModel source = (IndividualObservationBatchUIModel) evt.getSource();
580 if (source.getRows() != null) {
581 boolean nonEmptyRow = source.isNonEmptyRowInError();
582 model.setNonEmptyIndividualObservationRowsInError(nonEmptyRow);
583 }
584 });
585
586
587
588 ui.getSimpleCountingWeightField().setNumberPattern(weightUnit.getNumberEditorPattern());
589
590 initDataTable();
591
592 initLogTable();
593
594 this.individualObservationBatchTableHandler = new IndividualObservationBatchTableHandler(ui);
595 this.averageWeightsHistogramHandler = new AverageWeightsHistogramHandler(ui);
596 this.frequenciesHistogramHandler = new FrequenciesHistogramHandler(ui);
597 this.samplingNotificationZoneHandler = new SamplingNotificationZoneHandler(ui,
598 model.getIndividualObservationModel().getSamplingNotificationZoneModel(),
599 model.getIndividualObservationUICache());
600
601 listenValidatorValid(ui.getValidator(), model);
602
603 final Color bgSaveBt = ui.getSaveAndStayButton().getBackground();
604 final boolean opacity = ui.getSaveAndStayButton().isOpaque();
605 model.addPropertyChangeListener(SpeciesFrequencyUIModel.PROPERTY_MODIFY, evt -> {
606 if (Boolean.FALSE.equals(evt.getNewValue())) {
607 ui.getSaveAndStayButton().setOpaque(opacity);
608 ui.getSaveAndStayButton().setBackground(bgSaveBt);
609 } else {
610 ui.getSaveAndStayButton().setOpaque(true);
611 ui.getSaveAndStayButton().setBackground(Color.RED);
612 }
613 });
614
615 }
616
617 @Override
618 protected JComponent getComponentToFocus() {
619 FrequencyConfigurationMode configurationMode = getModel().getConfigurationMode();
620 JComponent componentToFocus = getComponentToFocus(configurationMode);
621 if (componentToFocus == null) {
622 componentToFocus = getUI().getLengthStepCaracteristicComboBox();
623 }
624 return componentToFocus;
625 }
626
627 @Override
628 public void onCloseUI() {
629 if (log.isDebugEnabled()) {
630 log.debug("closing: " + ui);
631 }
632
633 getDataContext().removePropertyChangeListener(TuttiDataContext.PROPERTY_FISHING_OPERATION_ID, listenFishingOperationReloadInDataContext);
634
635 TuttiUIContext context = getContext();
636 context.removePropertyChangeListener(TuttiUIContext.PROPERTY_ICHTYOMETER_CONNECTED, listenIchtyomerIsConnected);
637 context.removePropertyChangeListener(TuttiUIContext.PROPERTY_CALIPER_CONNECTED, listenCaliperIsConnected);
638
639 if (context.isIchtyometerConnected()) {
640
641 context.getIchtyometerReader().removeFeedModeReaderListener(ichtyometerFeedReaderListener);
642 }
643
644 if (context.isCaliperConnected()) {
645
646 context.getCaliperReader().removeFeedModeReaderListener(caliperFeedReaderListener);
647 }
648
649 SpeciesFrequencyUIModel model = getModel();
650
651 IOUtils.closeQuietly(individualObservationBatchTableHandler);
652 IOUtils.closeQuietly(averageWeightsHistogramHandler);
653 IOUtils.closeQuietly(frequenciesHistogramHandler);
654 IOUtils.closeQuietly(samplingNotificationZoneHandler);
655
656 frequencyEditor = null;
657
658
659 ui.getValidator().setBean(null);
660 clearValidators();
661
662
663 model.setValid(false);
664 model.setSimpleCount(null);
665 model.setModify(false);
666
667 EditSpeciesBatchPanelUI parent = getParentContainer(EditSpeciesBatchPanelUI.class);
668 parent.switchToEditBatch();
669
670 }
671
672 public void editBatch(FrequencyCellEditor editor, String title) {
673
674 SpeciesBatchRowModel speciesBatch = editor.getEditRow();
675 Objects.requireNonNull(speciesBatch, "Impossible d'éditer un lot non renseigné");
676
677 SpeciesFrequencyUIModel model = getModel();
678
679 Objects.requireNonNull(title, "title can't be null here ?!");
680
681 model.getAverageWeightsHistogramModel().setTitle(title);
682 model.getFrequenciesHistogramModel().setTitle(title);
683
684 frequencyEditor = editor;
685
686 model.setNextEditableRowIndex(frequencyEditor.getNextEditableRowIndex());
687
688 List<SpeciesFrequencyRowModel> frequency = speciesBatch.getFrequency();
689 List<IndividualObservationBatchRowModel> individualObservations = speciesBatch.getIndividualObservation();
690
691
692 model.setBatch(speciesBatch);
693 model.setFishingOperation(getDataContext().getFishingOperation());
694 model.setMinStep(null);
695 model.setMaxStep(null);
696 model.setRtp(null);
697 model.setCopyRtpWeights(false);
698
699
700 SpeciesProtocol speciesProtocol = getDataContext().isProtocolFilled() ? speciesOrBenthosBatchUISupport.getSpeciesProtocol(speciesBatch.getSpecies()) : null;
701
702
703 Rtp rtp = null;
704
705 if (speciesProtocol != null) {
706
707 Caracteristic sexCaracteristic = model.getIndividualObservationModel().getSexCaracteristic();
708 CaracteristicQualitativeValue sampleCategoryValue = (CaracteristicQualitativeValue) speciesBatch.getSampleCategoryValue(sexCaracteristic.getIdAsInt());
709
710 if (sampleCategoryValue != null) {
711
712 if (Sexs.isMale(sampleCategoryValue)) {
713 rtp = speciesProtocol.getRtpMale();
714 } else if (Sexs.isFemale(sampleCategoryValue)) {
715 rtp = speciesProtocol.getRtpFemale();
716 } else {
717 rtp = speciesProtocol.getRtpUndefined();
718 }
719
720 } else {
721 rtp = speciesProtocol.getRtpUndefined();
722 }
723
724 }
725
726 model.setRtp(rtp);
727
728 individualObservationBatchTableHandler.initMaturityCaracteristic(speciesProtocol);
729 individualObservationBatchTableHandler.initDefaultCaracteristics(speciesBatch);
730
731 model.getIndividualObservationUICache().initFishingOperation(model.getFishingOperation());
732
733 loadFrequenciesAndObservations(frequency, individualObservations, false);
734
735 samplingNotificationZoneHandler.editBatch(speciesBatch);
736
737 if (getContext().isIchtyometerConnected()) {
738
739
740 listenItchtyometer();
741
742 }
743
744 if (getContext().isCaliperConnected()) {
745
746
747 listenCaliper();
748
749 }
750
751 model.setModify(false);
752
753 }
754
755 public boolean leaveIfConfirmed() {
756
757 boolean result = !getModel().isModify() || askCancelEditBeforeLeaving();
758
759 if (result) {
760
761
762 ApplicationUIAction action = (ApplicationUIAction) getUI().getCancelButton().getAction();
763 getContext().getActionEngine().runInternalAction(action.getLogicAction());
764
765 } else {
766
767
768 if (log.isInfoEnabled()) {
769 log.info("Use cancel change on tab, stay on frequencies screen.");
770 }
771
772 }
773
774 return result;
775
776 }
777
778 public boolean askCancelEditBeforeLeaving() {
779
780 String htmlMessage = String.format(AbstractApplicationUIHandler.CONFIRMATION_FORMAT,
781 t("tutti.askToCancelEditFrequencies.message"),
782 t("tutti.askToCancelEditFrequencies.help"));
783
784 int saveResponse = JOptionPane.showOptionDialog(getTopestUI(),
785 htmlMessage,
786 t("tutti.askToCancelEditFrequencies.title"),
787 JOptionPane.OK_CANCEL_OPTION,
788 JOptionPane.QUESTION_MESSAGE,
789 null,
790 new String[]{t("tutti.option.continue"), t("tutti.option.cancel")},
791 t("tutti.option.cancel"));
792
793 return saveResponse == 0;
794 }
795
796 public void setCopyIndividualObservationMode(CopyIndividualObservationMode newCopyMode) {
797
798 SpeciesFrequencyUIModel model = getModel();
799
800 if (model.isInitBatchEdition()) {
801
802 if (log.isInfoEnabled()) {
803 log.info("Skip ask user to confirm copyIndividualObservationMode changed from " + model.getCopyIndividualObservationMode() + " to " + newCopyMode);
804 }
805 return;
806 }
807
808
809 if (!model.isCopyIndividualObservationAll()) {
810
811 long rowsWithUserData;
812
813
814 if (model.isCopyIndividualObservationSize()) {
815 rowsWithUserData = model.getRows().stream()
816 .filter(SpeciesFrequencyRowModel::withWeight)
817 .count();
818
819 } else {
820 rowsWithUserData = model.getRows().stream()
821 .filter(row -> row.withLengthStep() || row.withNumber() || row.withWeight())
822 .count();
823 }
824
825 if (rowsWithUserData > 0) {
826
827 String htmlMessage = String.format(
828 CONFIRMATION_FORMAT,
829 t("tutti.editSpeciesFrequencies.changeCopyMode.confirm.message"),
830 t("tutti.editSpeciesFrequencies.changeCopyMode.confirm.help"));
831 int i = JOptionPane.showConfirmDialog(
832 ui.getHandler().getTopestUI(),
833 htmlMessage,
834 t("tutti.editSpeciesFrequencies.changeCopyMode.confirm.title"),
835 JOptionPane.OK_CANCEL_OPTION,
836 JOptionPane.QUESTION_MESSAGE);
837
838 if (i == JOptionPane.CANCEL_OPTION) {
839 if (log.isDebugEnabled()) {
840 log.debug("User cancel modification...");
841 }
842
843
844
845 switch (model.getCopyIndividualObservationMode()) {
846 case ALL:
847 ui.getCopyAllButton().setSelected(true);
848 break;
849 case NOTHING:
850 ui.getCopyNothingButton().setSelected(true);
851 break;
852 case SIZE:
853 ui.getCopySizesButton().setSelected(true);
854 break;
855 }
856
857 return;
858 }
859 }
860
861 }
862
863 model.setCopyIndividualObservationMode(newCopyMode);
864 }
865
866
867
868
869
870 protected void initDataTable() {
871 JXTable table = getTable();
872
873
874 DefaultTableColumnModelExt columnModel = new DefaultTableColumnModelExt();
875
876 {
877
878 addFloatColumnToModel(columnModel,
879 SpeciesFrequencyTableModel.LENGTH_STEP,
880 TuttiUI.DECIMAL1_PATTERN,
881 table);
882 }
883
884 {
885
886 addIntegerColumnToModel(columnModel,
887 SpeciesFrequencyTableModel.NUMBER,
888 TuttiUI.INT_6_DIGITS_PATTERN,
889 table);
890 }
891
892 {
893 addFloatColumnToModel(columnModel, SpeciesFrequencyTableModel.WEIGHT, weightUnit, table);
894 }
895
896 {
897
898 Color computedDataColor = getConfig().getColorComputedWeights();
899 TableCellRenderer renderer = new TableCellRenderer() {
900
901 TableCellRenderer delegate = newWeightCellRenderer(table.getDefaultRenderer(Number.class), weightUnit);
902
903 @Override
904 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
905 Component result = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
906 if (result instanceof JLabel) {
907 JLabel jLabel = (JLabel) result;
908 jLabel.setForeground(computedDataColor);
909 jLabel.setFont(jLabel.getFont().deriveFont(Font.ITALIC));
910 }
911 return result;
912 }
913 };
914
915 addColumnToModel(columnModel,
916 null,
917 renderer,
918 SpeciesFrequencyTableModel.RTP_COMPUTED_WEIGHT,
919 weightUnit);
920 }
921
922
923 SpeciesFrequencyTableModel tableModel = new SpeciesFrequencyTableModel(weightUnit,
924 getConfig().getIndividualObservationWeightUnit(),
925 columnModel,
926 getModel());
927 getModel().setFrequencyTableModel(tableModel);
928
929 table.setModel(tableModel);
930 table.setColumnModel(columnModel);
931
932 initTable(table);
933
934 installTableKeyListener(columnModel, table);
935 }
936
937 @Override
938 protected void addHighlighters(final JXTable table) {
939
940 super.addHighlighters(table);
941
942 HighlightPredicate notSelectedPredicate = new HighlightPredicate.NotHighlightPredicate(HighlightPredicate.IS_SELECTED);
943 HighlightPredicate weightTooDifferentFromRtpPredicate = (Component renderer, ComponentAdapter adapter) -> {
944
945 boolean result = false;
946 if (table.getModel() instanceof SpeciesFrequencyTableModel) {
947
948 SpeciesFrequencyTableModel tableModel = (SpeciesFrequencyTableModel) table.getModel();
949 int viewRow = adapter.row;
950 int modelRow = adapter.convertRowIndexToModel(viewRow);
951 SpeciesFrequencyRowModel row = tableModel.getEntry(modelRow);
952
953 Float rate = getConfig().getDifferenceRateBetweenWeightAndRtpWeight();
954 result = row.withWeight() && row.withRtpComputedWeight()
955 && Math.abs(row.getWeight() - row.getRtpComputedWeight()) >= row.getWeight() * rate / 100;
956 }
957
958 return result;
959 };
960
961
962 Highlighter weightTooDifferentFromRtpHighlighter = TuttiUIUtil.newBackgroundColorHighlighter(
963 new HighlightPredicate.AndHighlightPredicate(
964 notSelectedPredicate,
965 weightTooDifferentFromRtpPredicate),
966 getConfig().getColorWarningRow());
967 table.addHighlighter(weightTooDifferentFromRtpHighlighter);
968
969
970 Highlighter weightTooDifferentFromRtpSelectedHighlighter = TuttiUIUtil.newBackgroundColorHighlighter(
971 new HighlightPredicate.AndHighlightPredicate(
972 HighlightPredicate.IS_SELECTED,
973 weightTooDifferentFromRtpPredicate),
974 getConfig().getColorWarningRow().darker());
975 table.addHighlighter(weightTooDifferentFromRtpSelectedHighlighter);
976
977 }
978
979 protected void initLogTable() {
980 JXTable logTable = ui.getLogsTable();
981
982
983 DefaultTableColumnModelExt logColumnModel = new DefaultTableColumnModelExt();
984
985 {
986 addColumnToModel(logColumnModel,
987 SpeciesFrequencyLogCellComponent.newEditor(ui),
988 SpeciesFrequencyLogCellComponent.newRender(),
989 SpeciesFrequencyLogsTableModel.LABEL);
990 }
991
992
993 SpeciesFrequencyLogsTableModel logTableModel = new SpeciesFrequencyLogsTableModel(logColumnModel);
994 logTableModel.setRows(new ArrayList<>());
995
996 logTable.setModel(logTableModel);
997 logTable.setColumnModel(logColumnModel);
998
999
1000 logTable.getTableHeader().setReorderingAllowed(false);
1001 Highlighter evenHighlighter = TuttiUIUtil.newBackgroundColorHighlighter(
1002 HighlightPredicate.ODD,
1003 getConfig().getColorAlternateRow());
1004 logTable.addHighlighter(evenHighlighter);
1005 }
1006
1007 protected CaracteristicColumnIdentifier<IndividualObservationBatchRowModel> addCaracteristicColumnToModel(JXTable table,
1008 TableColumnModelExt columnModel,
1009 Caracteristic caracteristic) {
1010
1011 String header = caracteristicDecorator.toString(caracteristic);
1012 String headerTip = caracteristicTipDecorator.toString(caracteristic);
1013
1014 CaracteristicColumnIdentifier<IndividualObservationBatchRowModel> id = CaracteristicColumnIdentifier.newCaracteristicId(
1015 caracteristic,
1016 IndividualObservationBatchRowModel.PROPERTY_DEFAULT_CARACTERISTICS,
1017 header,
1018 headerTip
1019 );
1020
1021 if (columnModel.getColumnExt(id) == null) {
1022
1023 switch (caracteristic.getCaracteristicType()) {
1024
1025 case NUMBER:
1026
1027 addFloatColumnToModel(columnModel,
1028 id,
1029 TuttiUI.DECIMAL3_PATTERN,
1030 table);
1031
1032 break;
1033 case QUALITATIVE:
1034 List<CaracteristicQualitativeValue> values = caracteristic.getQualitativeValue();
1035 addComboDataColumnToModel(columnModel,
1036 id,
1037 caracteristicQualitativeDecorator,
1038 values);
1039 break;
1040 case TEXT:
1041
1042 addColumnToModel(columnModel, id);
1043
1044 break;
1045 }
1046 }
1047
1048 return id;
1049 }
1050
1051
1052 @Override
1053 protected <R> TableColumnExt addColumnToModel(TableColumnModel model,
1054 TableCellEditor editor,
1055 TableCellRenderer renderer,
1056 ColumnIdentifier<R> identifier) {
1057
1058
1059 TableColumnExt col = new TableColumnExt(((DefaultTableColumnModelExt) model).getColumnCount(true));
1060 col.setCellEditor(editor);
1061 col.setCellRenderer(renderer);
1062 String label = t(identifier.getHeaderI18nKey());
1063
1064 col.setHeaderValue(label);
1065 String tip = t(identifier.getHeaderTipI18nKey());
1066
1067 col.setToolTipText(tip);
1068
1069 col.setIdentifier(identifier);
1070 model.addColumn(col);
1071
1072 col.setSortable(false);
1073 return col;
1074 }
1075
1076 protected void consumeIchtyometerFeedRecord(IchtyometerFeedReaderMeasureRecord record) {
1077 if (record.isValid()) {
1078
1079 float length = getModel().convertFromMm(record.getMeasure());
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098 applySpeciesFrequencyRafaleAction.applyRafaleStep(length, true);
1099
1100 } else {
1101
1102 soundEngine.beepOnExternalDeviceErrorReception();
1103
1104 throw new ApplicationBusinessException(t("tutti.editSpeciesFrequencies.error.itchyometer.bad.record", record.getRecord()));
1105 }
1106 }
1107
1108 protected void consumeCaliperFeedRecord(CaliperFeedReaderMeasureRecord record) {
1109 if (record.isValid()) {
1110
1111 float length = getModel().convertFromMm(record.getMeasure());
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 applySpeciesFrequencyRafaleAction.applyRafaleStep(length, true);
1132
1133 } else {
1134
1135 soundEngine.beepOnExternalDeviceErrorReception();
1136
1137 throw new ApplicationBusinessException(t("tutti.editSpeciesFrequencies.error.caliper.bad.record", record.getRecord()));
1138 }
1139 }
1140
1141 protected void listenItchtyometer() {
1142
1143
1144 getContext().getIchtyometerReader().removeAllFeedModeReaderListeners();
1145 if (log.isInfoEnabled()) {
1146 log.info("Start listen ichtyometer");
1147 }
1148 getContext().getIchtyometerReader().addFeedModeReaderListener(ichtyometerFeedReaderListener);
1149 }
1150
1151 protected void listenCaliper() {
1152
1153
1154 getContext().getCaliperReader().removeAllFeedModeReaderListeners();
1155 if (log.isInfoEnabled()) {
1156 log.info("Start listen caliper");
1157 }
1158 getContext().getCaliperReader().addFeedModeReaderListener(caliperFeedReaderListener);
1159 }
1160
1161 protected JComponent getComponentToFocus(FrequencyConfigurationMode mode) {
1162 JComponent componentToFocus = null;
1163 if (mode != null) {
1164 boolean withLengthStepCaracteristic =
1165 getModel().getLengthStepCaracteristic() != null;
1166 switch (mode) {
1167 case AUTO_GEN:
1168 if (withLengthStepCaracteristic) {
1169
1170 componentToFocus = ui.getMinStepField();
1171 } else {
1172 componentToFocus = ui.getLengthStepCaracteristicComboBox();
1173 }
1174 break;
1175 case RAFALE:
1176
1177 if (withLengthStepCaracteristic) {
1178
1179 componentToFocus = ui.getRafaleStepField();
1180 } else {
1181 componentToFocus = ui.getLengthStepCaracteristicComboBox();
1182 }
1183
1184 break;
1185 case SIMPLE_COUNTING:
1186 componentToFocus = ui.getSimpleCountingNumberField();
1187 break;
1188 default:
1189 componentToFocus = null;
1190 }
1191 }
1192 return componentToFocus;
1193 }
1194
1195 protected void updateLogVisibility() {
1196
1197 boolean logVisible = getModel().isRafaleMode() || getContext().isIchtyometerConnected() || getContext().isCaliperConnected();
1198 JSplitPane firstSplitPane = ui.getFirstSplitPane();
1199 JSplitPane secondSplitPane = ui.getSecondSplitPane();
1200
1201 int lastDividerLocation = secondSplitPane.getLastDividerLocation();
1202 if (lastDividerLocation == 0) {
1203 lastDividerLocation = 200;
1204 }
1205 secondSplitPane.setDividerLocation(logVisible ? lastDividerLocation : 0);
1206 secondSplitPane.setDividerSize(logVisible ? firstSplitPane.getDividerSize() : 0);
1207
1208 ui.getLogsScrollPane().setVisible(logVisible);
1209
1210 }
1211
1212 @Override
1213 public <E> void initBeanFilterableComboBox(BeanFilterableComboBox<E> comboBox, List<E> data, E selectedData) {
1214 super.initBeanFilterableComboBox(comboBox, data, selectedData);
1215 }
1216
1217 public FrequencyCellEditor getFrequencyEditor() {
1218 return frequencyEditor;
1219 }
1220
1221 @Override
1222 protected void beforeOpenPopup(int modelRowIndex, int modelColumnIndex) {
1223 super.beforeOpenPopup(modelRowIndex, modelColumnIndex);
1224
1225 boolean sampleCodeMenusEnabled = individualObservationBatchTableHandler.isSampleCodeMenusEnabled(modelRowIndex);
1226
1227 ui.getEditSampleCodeMenu().setEnabled(sampleCodeMenusEnabled);
1228 ui.getDeleteSampleCodeMenu().setEnabled(sampleCodeMenusEnabled);
1229 }
1230
1231 public void loadFrequenciesAndObservations(List<SpeciesFrequencyRowModel> frequency, List<IndividualObservationBatchRowModel> individualObservations, boolean addToCache) {
1232
1233 SpeciesFrequencyUIModel model = getModel();
1234 SpeciesBatchRowModel speciesBatch = model.getBatch();
1235
1236 model.setInitBatchEdition(true);
1237
1238 try {
1239
1240 model.loadSpeciesBatch(speciesBatch);
1241
1242 Species species = speciesBatch.getSpecies();
1243
1244
1245 model.setFrequenciesConfigurationMode(FrequencyConfigurationMode.RAFALE);
1246
1247 SpeciesProtocol speciesProtocol =
1248 speciesOrBenthosBatchUISupport.getSpeciesProtocol(species);
1249 model.setAddIndividualObservationOnRafale(
1250 speciesProtocol != null && speciesProtocol.isIndividualObservationEnabled());
1251
1252 List<SpeciesFrequencyRowModel> frequencyRows = getTableModel().loadRows(frequency);
1253
1254 List<IndividualObservationBatchRowModel> individualObservationRows = individualObservationBatchTableHandler.loadRows(species, individualObservations);
1255
1256 if (log.isDebugEnabled()) {
1257 log.debug("Will edit batch row: " + speciesBatch + " with " + frequencyRows.size() + " frequencies and " + individualObservationRows.size() + " individual observations.");
1258 }
1259
1260 CopyIndividualObservationMode copyIndividualObservationMode =
1261 computeCopyIndividualObservationMode(
1262 model.isAddIndividualObservationOnRafale(),
1263 frequencyRows, individualObservationRows);
1264
1265 if (log.isInfoEnabled()) {
1266 log.info("copyIndividualObservationMode: " + copyIndividualObservationMode);
1267 }
1268
1269 Caracteristic lengthStepCaracteristic = computeLengthStepCaracteristic(species, frequencyRows, individualObservationRows);
1270
1271 if (log.isInfoEnabled()) {
1272 log.info("lengthStepCaracteristic: " + lengthStepCaracteristic);
1273 }
1274
1275
1276 model.setLengthStepCaracteristic(lengthStepCaracteristic);
1277
1278 FrequencyConfigurationMode configurationMode = model.guessFrequencyConfigurationMode();
1279
1280 if (log.isInfoEnabled()) {
1281 log.info("configurationMode: " + configurationMode);
1282 }
1283
1284
1285 model.setConfigurationMode(null);
1286 model.setConfigurationMode(configurationMode);
1287
1288 model.setFrequenciesConfigurationMode(null);
1289
1290 model.setFrequenciesConfigurationMode(FrequencyConfigurationMode.RAFALE);
1291
1292
1293
1294
1295 ui.getValidator().setBean(model);
1296
1297 model.setRows(frequencyRows);
1298
1299
1300 model.setCopyIndividualObservationMode(null);
1301 model.setCopyIndividualObservationMode(copyIndividualObservationMode);
1302
1303
1304 individualObservationBatchTableHandler.loadSpeciesBatch(speciesBatch, individualObservationRows, addToCache);
1305
1306 model.computeRowWeightWithRtp();
1307
1308 } finally {
1309
1310 model.setInitBatchEdition(false);
1311
1312 }
1313 }
1314
1315
1316
1317 @Override
1318 protected <R> TableColumnExt addIntegerColumnToModel(TableColumnModel model,
1319 ColumnIdentifier<R> identifier,
1320 String numberPattern,
1321 JTable table) {
1322 return super.addIntegerColumnToModel(model, identifier, numberPattern, table);
1323 }
1324
1325 @Override
1326 protected <R> TableColumnExt addFloatColumnToModel(TableColumnModel model,
1327 ColumnIdentifier<R> identifier,
1328 String numberPattern,
1329 JTable table) {
1330 return super.addFloatColumnToModel(model, identifier, numberPattern, table);
1331 }
1332
1333 @Override
1334 protected <R> TableColumnExt addFloatColumnToModel(TableColumnModel model, ColumnIdentifier<R> identifier, WeightUnit weightUnit, JTable table) {
1335 return super.addFloatColumnToModel(model, identifier, weightUnit, table);
1336 }
1337
1338 @Override
1339 protected <R, B> TableColumnExt addComboDataColumnToModel(TableColumnModel model,
1340 ColumnIdentifier<R> identifier,
1341 Decorator<B> decorator,
1342 List<B> data) {
1343 return super.addComboDataColumnToModel(model, identifier, decorator, data);
1344 }
1345
1346 @Override
1347 protected void installTableKeyListener(TableColumnModel columnModel, JTable table, boolean enterToChangeRow) {
1348 super.installTableKeyListener(columnModel, table, enterToChangeRow);
1349 }
1350
1351 @Override
1352 protected String decorate(Serializable object, String context) {
1353 return super.decorate(object, context);
1354 }
1355
1356 private CopyIndividualObservationMode computeCopyIndividualObservationMode(
1357 boolean isAddIndividualObservationOnRafale,
1358 List<SpeciesFrequencyRowModel> frequencyRows,
1359 List<IndividualObservationBatchRowModel> individualObservationRows) {
1360 CopyIndividualObservationMode result = CopyIndividualObservationMode.NOTHING;
1361 if (frequencyRows.isEmpty() && individualObservationRows.isEmpty()) {
1362
1363 if (isAddIndividualObservationOnRafale) {
1364 result = CopyIndividualObservationMode.SIZE;
1365 }
1366 } else if (!individualObservationRows.isEmpty()) {
1367 IndividualObservationBatchRowModel firstIndividualObservationRow =
1368 individualObservationRows.get(0);
1369 result = firstIndividualObservationRow.getCopyIndividualObservationMode();
1370 }
1371 return result;
1372 }
1373
1374 private Caracteristic computeLengthStepCaracteristic(Species species, List<SpeciesFrequencyRowModel> frequencyRows, List<IndividualObservationBatchRowModel> individualObservationRows) {
1375
1376 Caracteristic lengthStepCaracteristic = null;
1377
1378 if (!frequencyRows.isEmpty()) {
1379
1380 SpeciesFrequencyRowModel firstFrequencyRow = frequencyRows.get(0);
1381 lengthStepCaracteristic = firstFrequencyRow.getLengthStepCaracteristic();
1382 if (log.isInfoEnabled()) {
1383 log.info("Use existing lengthStep caracteristic / step from first existing frequency: " + decorate(lengthStepCaracteristic));
1384 }
1385
1386 }
1387
1388 if (lengthStepCaracteristic == null) {
1389
1390 if (!individualObservationRows.isEmpty()) {
1391 IndividualObservationBatchRowModel firstIndividualObservationRow = individualObservationRows.get(0);
1392
1393 lengthStepCaracteristic = firstIndividualObservationRow.getLengthStepCaracteristic();
1394
1395 if (log.isInfoEnabled()) {
1396 log.info("Use existing lengthStep caracteristic / step from first individual observation : " + decorate(lengthStepCaracteristic));
1397 }
1398 }
1399
1400 }
1401
1402 SpeciesBatchRowModel previousSiblingRow = frequencyEditor.getPreviousSiblingRow();
1403
1404 if (lengthStepCaracteristic == null && previousSiblingRow != null) {
1405
1406
1407 List<SpeciesFrequencyRowModel> previousFrequency = previousSiblingRow.getFrequency();
1408
1409 if (CollectionUtils.isNotEmpty(previousFrequency)) {
1410
1411
1412 SpeciesFrequencyRowModel rowModel = previousFrequency.get(0);
1413 lengthStepCaracteristic = rowModel.getLengthStepCaracteristic();
1414 if (log.isInfoEnabled()) {
1415 log.info("Use previous sibling existing lengthStep caracteristic / step " + decorate(lengthStepCaracteristic));
1416 }
1417 }
1418 }
1419
1420 if (lengthStepCaracteristic == null) {
1421
1422 if (taxonCache.containsLengthStepPmfmId(species)) {
1423
1424 String lengthStepPmfmId = taxonCache.getLengthStepPmfmId(species);
1425
1426 lengthStepCaracteristic = lengthStepCaracteristics.get(lengthStepPmfmId);
1427
1428 if (log.isInfoEnabled()) {
1429 log.info("Use existing from protocol lengthStep caracteristic / step " + decorate(lengthStepCaracteristic));
1430 }
1431 }
1432
1433 }
1434
1435 return lengthStepCaracteristic;
1436
1437 }
1438
1439 }