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
26
27 import com.google.common.base.Preconditions;
28 import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch;
29 import fr.ifremer.tutti.persistence.entities.protocol.CalcifiedPiecesSamplingDefinition;
30 import fr.ifremer.tutti.persistence.entities.protocol.Zone;
31 import fr.ifremer.tutti.persistence.entities.referential.Species;
32 import fr.ifremer.tutti.service.DecoratorService;
33 import fr.ifremer.tutti.service.sampling.CalcifiedPiecesSamplingAlgorithmEntryNotFoundException;
34 import fr.ifremer.tutti.service.sampling.IndividualObservationSamplingContext;
35 import fr.ifremer.tutti.service.sampling.IndividualObservationSamplingStatus;
36 import fr.ifremer.tutti.service.sampling.SizeNotDefinedOnIndividualObservationException;
37 import fr.ifremer.tutti.service.sampling.ZoneNotDefinedOnFishingOperationException;
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.nuiton.decorator.Decorator;
41
42 import javax.swing.JLabel;
43 import javax.swing.ListSelectionModel;
44 import javax.swing.event.ListSelectionListener;
45 import java.awt.Color;
46 import java.beans.PropertyChangeListener;
47 import java.io.Closeable;
48 import java.util.Objects;
49
50 import static org.nuiton.i18n.I18n.t;
51
52
53
54
55
56
57
58
59 public class SamplingNotificationZoneHandler implements Closeable {
60
61
62 private static final Log log = LogFactory.getLog(SamplingNotificationZoneHandler.class);
63
64 private final SpeciesFrequencyUIModel uiModel;
65 private final SamplingNotificationZoneModel model;
66 private final IndividualObservationBatchTableModel individualObservationTableModel;
67 private final ListSelectionModel listSelectionModel;
68
69 private final IndividualObservationUICache individualObservationUICache;
70
71 private final JLabel samplingWarningLabel;
72 private final JLabel samplingSummaryLabel;
73
74 private final ListSelectionListener listSelectionListener;
75 private final PropertyChangeListener modelSummaryTextChanged;
76 private final PropertyChangeListener modelSelectedRowChanged;
77 private final PropertyChangeListener modelUpdatedRowChanged;
78 private final PropertyChangeListener modelStatusChanged;
79
80 private final Decorator<Integer> infiniteDecorator;
81 private final Decorator<Species> speciesDecorator;
82 private final Decorator<Zone> zoneDecorator;
83
84 private final Color colorHighlightInfoForeground;
85 private final Color colorHighlightInfoBackground;
86
87 public SamplingNotificationZoneHandler(SpeciesFrequencyUI ui, SamplingNotificationZoneModel model, IndividualObservationUICache individualObservationUICache) {
88 this.uiModel = ui.getModel();
89 this.samplingWarningLabel = ui.getSamplingWarningLabel();
90 this.samplingSummaryLabel = ui.getSamplingResumeLabel();
91 this.individualObservationTableModel = (IndividualObservationBatchTableModel) ui.getObsTable().getModel();
92 this.model = model;
93 this.listSelectionModel = ui.getObsTable().getSelectionModel();
94
95 SpeciesFrequencyUIHandler uiHandler = ui.getHandler();
96 this.individualObservationUICache = individualObservationUICache;
97 this.infiniteDecorator = uiHandler.getDecorator(Integer.class, DecoratorService.NULL_INFINITE);
98 this.speciesDecorator = uiHandler.getDecorator(Species.class, DecoratorService.WITH_SURVEY_CODE);
99 this.zoneDecorator = uiHandler.getDecorator(Zone.class, null);
100 this.colorHighlightInfoForeground = uiHandler.getConfig().getColorHighlightInfoForeground();
101 this.colorHighlightInfoBackground = uiHandler.getConfig().getColorHighlightInfoBackground();
102
103
104 this.modelStatusChanged = event -> {
105
106 SamplingNotificationZoneStatus newValue = (SamplingNotificationZoneStatus) event.getNewValue();
107
108 switch (newValue) {
109
110 case DISABLED:
111
112 samplingWarningLabel.setText(t("tutti.editSpeciesFrequencies.samplingNotification.warning.samplingDisabled"));
113 samplingWarningLabel.setForeground(null);
114 samplingWarningLabel.setBackground(Color.LIGHT_GRAY);
115
116 break;
117 case NOT_USING_SAMPLING:
118
119 samplingWarningLabel.setText(t("tutti.editSpeciesFrequencies.samplingNotification.warning.samplingNotUsed"));
120 samplingWarningLabel.setForeground(null);
121 samplingWarningLabel.setBackground(Color.LIGHT_GRAY);
122
123 break;
124 case NEED_SAMPLING:
125
126 samplingWarningLabel.setText(t("tutti.editSpeciesFrequencies.samplingNotification.warning.samplingNeeded"));
127 samplingWarningLabel.setForeground(colorHighlightInfoForeground);
128 samplingWarningLabel.setBackground(colorHighlightInfoBackground);
129
130 break;
131 case NO_SAMPLING_REQUIRED:
132
133 samplingWarningLabel.setText(t("tutti.editSpeciesFrequencies.samplingNotification.warning.noSamplingRequired"));
134 samplingWarningLabel.setForeground(null);
135 samplingWarningLabel.setBackground(Color.LIGHT_GRAY);
136
137 break;
138 case COUNT_ATTAINED:
139
140 samplingWarningLabel.setText(t("tutti.editSpeciesFrequencies.samplingNotification.warning.samplingTotalCountAttained"));
141 samplingWarningLabel.setForeground(null);
142 samplingWarningLabel.setBackground(Color.LIGHT_GRAY);
143
144 break;
145
146 case NONE:
147
148 samplingWarningLabel.setText(null);
149 samplingWarningLabel.setForeground(null);
150 samplingWarningLabel.setBackground(null);
151
152 break;
153 }
154 };
155
156
157 this.modelSummaryTextChanged = event -> {
158
159 String newValue = (String) event.getNewValue();
160 samplingSummaryLabel.setText(newValue);
161
162 };
163
164
165 this.modelSelectedRowChanged = event -> {
166
167 IndividualObservationBatchRowModel selectedRow = (IndividualObservationBatchRowModel) event.getNewValue();
168
169 if (selectedRow == null) {
170
171 hideAll();
172 return;
173 }
174
175 IndividualObservationSamplingStatus status = getIndividualObservationSamplingStatus(selectedRow);
176
177 if (status != null) {
178
179
180 String summaryText = getSummaryText(status);
181 model.setSummaryText(summaryText);
182
183
184 SamplingNotificationZoneStatus samplingNotificationZoneStatus;
185
186 if (status.isOneTotalCountIsAttained()) {
187
188
189 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.COUNT_ATTAINED;
190 } else if (status.isNotUsingSampling()) {
191
192
193 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.NOT_USING_SAMPLING;
194 } else {
195
196
197 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.NONE;
198 }
199
200 model.setSamplingNotificationZoneStatus(samplingNotificationZoneStatus);
201
202 }
203
204 };
205
206
207 this.modelUpdatedRowChanged = event -> {
208
209 IndividualObservationBatchRowModel updatedRow = (IndividualObservationBatchRowModel) event.getNewValue();
210
211 Objects.requireNonNull(updatedRow);
212
213
214 IndividualObservationSamplingStatus status = getIndividualObservationSamplingStatus(updatedRow);
215
216 if (status != null) {
217
218
219 String summaryText = getSummaryText(status);
220 model.setSummaryText(summaryText);
221
222
223 SamplingNotificationZoneStatus samplingNotificationZoneStatus;
224
225 if (status.isNeedSampling()) {
226
227
228 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.NEED_SAMPLING;
229 } else if (status.isOneTotalCountIsAttained()) {
230
231
232 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.COUNT_ATTAINED;
233 } else if (status.isNotUsingSampling()) {
234
235
236 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.NOT_USING_SAMPLING;
237 } else if (updatedRow.withSamplingCode()) {
238
239
240 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.NONE;
241 } else {
242
243
244 samplingNotificationZoneStatus = SamplingNotificationZoneStatus.NO_SAMPLING_REQUIRED;
245 }
246
247 model.setSamplingNotificationZoneStatus(samplingNotificationZoneStatus);
248
249 }
250
251 };
252
253
254 this.listSelectionListener = event -> {
255
256 ListSelectionModel source = (ListSelectionModel) event.getSource();
257
258 if (model.isValueAdjusting()) {
259
260
261 return;
262 }
263
264 if (event.getValueIsAdjusting()) {
265
266
267 return;
268 }
269
270 if (source.isSelectionEmpty()) {
271
272
273 model.setSelectedRow(null);
274 return;
275 }
276
277 if (getSelectedRowCount(source) > 1) {
278
279
280 hideAll();
281 return;
282 }
283
284 IndividualObservationBatchRowModel selectedRow = individualObservationTableModel.getEntry(source.getMinSelectionIndex());
285 model.setSelectedRow(selectedRow);
286
287 };
288
289 }
290
291 public void editBatch(SpeciesBatch speciesBatch) {
292
293 if (log.isInfoEnabled()) {
294 log.info("Edit batch for " + speciesBatch);
295 }
296
297
298 listSelectionModel.removeListSelectionListener(listSelectionListener);
299 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SELECTED_ROW, modelSelectedRowChanged);
300 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_UPDATED_ROW, modelUpdatedRowChanged);
301 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SAMPLING_NOTIFICATION_ZONE_STATUS, modelStatusChanged);
302 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SUMMARY_TEXT, modelSummaryTextChanged);
303
304
305 model.addPropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SELECTED_ROW, modelSelectedRowChanged);
306 model.addPropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_UPDATED_ROW, modelUpdatedRowChanged);
307 model.addPropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SAMPLING_NOTIFICATION_ZONE_STATUS, modelStatusChanged);
308 model.addPropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SUMMARY_TEXT, modelSummaryTextChanged);
309
310 if (!uiModel.isProtocolFilled()) {
311
312
313 stopUsingStatusNotication(t("tutti.editSpeciesFrequencies.samplingNotification.warning.noProtocol"));
314 return;
315 }
316
317 if (!uiModel.isProtocolUseCalcifiedPieceSampling()) {
318
319
320 stopUsingStatusNotication(t("tutti.editSpeciesFrequencies.samplingNotification.warning.notUsingAlgorithm"));
321 return;
322 }
323
324 if (!individualObservationUICache.isFishingOperationWithZone()) {
325
326
327 stopUsingStatusNotication(t("tutti.editSpeciesFrequencies.samplingNotification.warning.fishingOperationNotInAZone"));
328 return;
329 }
330
331 if (!individualObservationUICache.isSpeciesDefinedInCalcifiedPiecesSampling()) {
332
333
334 stopUsingStatusNotication(t("tutti.editSpeciesFrequencies.samplingNotification.warning.speciesNotInAlgorithm"));
335 return;
336 }
337
338 Preconditions.checkState(individualObservationUICache.useCruiseSamplingCache());
339
340 model.setSelectedRow(null);
341
342 listSelectionModel.addListSelectionListener(listSelectionListener);
343
344 }
345
346 @Override
347 public void close() {
348
349 listSelectionModel.removeListSelectionListener(listSelectionListener);
350 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SELECTED_ROW, modelSelectedRowChanged);
351 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_UPDATED_ROW, modelUpdatedRowChanged);
352 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SAMPLING_NOTIFICATION_ZONE_STATUS, modelStatusChanged);
353 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SUMMARY_TEXT, modelSummaryTextChanged);
354
355 }
356
357 private void hideAll() {
358
359 model.setSummaryText(null);
360 model.setSamplingNotificationZoneStatus(SamplingNotificationZoneStatus.NONE);
361
362 }
363
364 private void whenCanNotUseSampling(String message) {
365
366 model.setSummaryText(message);
367 model.setSamplingNotificationZoneStatus(SamplingNotificationZoneStatus.DISABLED);
368
369 }
370
371 private void stopUsingStatusNotication(String message) {
372
373 whenCanNotUseSampling(message);
374 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SELECTED_ROW, modelSelectedRowChanged);
375 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_UPDATED_ROW, modelUpdatedRowChanged);
376 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SAMPLING_NOTIFICATION_ZONE_STATUS, modelStatusChanged);
377 model.removePropertyChangeListener(SamplingNotificationZoneModel.PROPERTY_SUMMARY_TEXT, modelSummaryTextChanged);
378
379 }
380
381 private String getSummaryText(IndividualObservationSamplingStatus status) {
382
383 IndividualObservationSamplingContext individualObservationSamplingContext = status.getIndividualObservationSamplingContext();
384
385 CalcifiedPiecesSamplingDefinition calcifiedPiecesSamplingDefinition = status.getCalcifiedPiecesSamplingDefinition();
386
387 int nbForOperation = status.getSamplingCountInFishingOperation();
388 int nbForZone = status.getSamplingCountInZone();
389 int nbForCruise = status.getSamplingCountInCruise();
390
391 String nbForOperationLabel = getLabelForSamplingNumber(nbForOperation, calcifiedPiecesSamplingDefinition.getOperationLimitation());
392 String nbForZoneLabel = getLabelForSamplingNumber(nbForZone, calcifiedPiecesSamplingDefinition.getZoneLimitation());
393 String nbForCruiseLabel = getLabelForSamplingNumber(nbForCruise, calcifiedPiecesSamplingDefinition.getMaxByLenghtStep());
394
395 String key = speciesDecorator.toString(individualObservationSamplingContext.getSpecies())
396 + " " + uiModel.convertFromMm(individualObservationSamplingContext.getLengthStep())
397 + " " + uiModel.getLengthStepCaracteristicUnit();
398 if (individualObservationSamplingContext.withGender()) {
399 key += " " + individualObservationSamplingContext.getGender().getDescription();
400 }
401 if (individualObservationSamplingContext.withMaturity()) {
402 if (individualObservationSamplingContext.getMaturity()) {
403 key += " " + t("tutti.editSpeciesFrequencies.samplingNeeded.mature");
404 } else {
405 key += " " + t("tutti.editSpeciesFrequencies.samplingNeeded.immature");
406 }
407 }
408
409 String zone = zoneDecorator.toString(individualObservationSamplingContext.getZone());
410
411 return t("tutti.editSpeciesFrequencies.samplingNeeded.summary", key, nbForOperationLabel, zone, nbForZoneLabel, nbForCruiseLabel);
412
413 }
414
415
416
417
418
419
420 private int getSelectedRowCount(ListSelectionModel selectionModel) {
421 int iMin = selectionModel.getMinSelectionIndex();
422 int iMax = selectionModel.getMaxSelectionIndex();
423 int count = 0;
424
425 for (int i = iMin; i <= iMax; i++) {
426 if (selectionModel.isSelectedIndex(i)) {
427 count++;
428 }
429 }
430 return count;
431 }
432
433 private String getLabelForSamplingNumber(int value, Integer max) {
434 return "<strong>" + infiniteDecorator.toString(value) + "</strong> (" + infiniteDecorator.toString(max) + ")";
435 }
436
437 private IndividualObservationSamplingStatus getIndividualObservationSamplingStatus(IndividualObservationBatchRowModel selectedRow) {
438
439 IndividualObservationSamplingStatus individualObservationSamplingStatus = null;
440
441 try {
442
443 individualObservationSamplingStatus = individualObservationUICache.getIndividualObservationSamplingStatus(selectedRow);
444
445 } catch (CalcifiedPiecesSamplingAlgorithmEntryNotFoundException e) {
446 whenCanNotUseSampling(t("tutti.editSpeciesFrequencies.samplingNotification.warning.noAlgorithmEntry"));
447 } catch (SizeNotDefinedOnIndividualObservationException e) {
448 whenCanNotUseSampling(t("tutti.editSpeciesFrequencies.samplingNotification.warning.sizeNotDefined"));
449 } catch (ZoneNotDefinedOnFishingOperationException e) {
450 whenCanNotUseSampling(t("tutti.editSpeciesFrequencies.samplingNotification.warning.fishingOperationNotInAZone"));
451 }
452
453 return individualObservationSamplingStatus;
454
455 }
456
457 }