View Javadoc
1   package fr.ifremer.tutti.ui.swing.content.operation.catches.actions;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.collect.Multimap;
26  import fr.ifremer.tutti.persistence.entities.data.BatchContainer;
27  import fr.ifremer.tutti.persistence.entities.data.CatchBatch;
28  import fr.ifremer.tutti.persistence.entities.data.FishingOperation;
29  import fr.ifremer.tutti.persistence.entities.data.MarineLitterBatch;
30  import fr.ifremer.tutti.persistence.entities.data.SampleCategory;
31  import fr.ifremer.tutti.persistence.entities.data.SpeciesBatch;
32  import fr.ifremer.tutti.service.PersistenceService;
33  import fr.ifremer.tutti.service.catches.BenthosWeightComputingException;
34  import fr.ifremer.tutti.service.catches.CatchWeightComputingException;
35  import fr.ifremer.tutti.service.catches.MarineLitterWeightComputingException;
36  import fr.ifremer.tutti.service.catches.SpeciesWeightComputingException;
37  import fr.ifremer.tutti.service.catches.TuttiWeightComputingException;
38  import fr.ifremer.tutti.service.catches.WeightCleaningService;
39  import fr.ifremer.tutti.service.catches.WeightComputingService;
40  import fr.ifremer.tutti.ui.swing.content.operation.catches.EditCatchesUI;
41  import fr.ifremer.tutti.ui.swing.content.operation.catches.EditCatchesUIHandler;
42  import fr.ifremer.tutti.ui.swing.content.operation.catches.EditCatchesUIModel;
43  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SampleCategoryColumnIdentifier;
44  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchNaturalOrderComparator;
45  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchRowModel;
46  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchTableModel;
47  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchUI;
48  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchUIHandler;
49  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesBatchUIModel;
50  import fr.ifremer.tutti.ui.swing.content.operation.catches.species.edit.SpeciesSortMode;
51  import fr.ifremer.tutti.ui.swing.util.AbstractTuttiUIHandler;
52  import fr.ifremer.tutti.ui.swing.util.actions.LongActionSupport;
53  import fr.ifremer.tutti.util.Numbers;
54  import jaxx.runtime.swing.JTables;
55  import org.jdesktop.swingx.JXTable;
56  import org.jdesktop.swingx.table.TableColumnExt;
57  import org.nuiton.jaxx.application.swing.table.ColumnIdentifier;
58  
59  import javax.swing.JOptionPane;
60  import javax.swing.table.TableColumn;
61  import java.util.ArrayList;
62  import java.util.List;
63  import java.util.Optional;
64  import java.util.Set;
65  
66  import static org.nuiton.i18n.I18n.t;
67  
68  /**
69   * @author Kevin Morin - kmorin@codelutin.com
70   * @since 1.0
71   */
72  public class ComputeBatchWeightsAction extends LongActionSupport<EditCatchesUIModel, EditCatchesUI, EditCatchesUIHandler> {
73      
74      protected final WeightCleaningService cleaningService;
75      protected final PersistenceService persistenceService;
76  
77      protected List<SpeciesBatchRowModel> speciesBatchRows;
78      protected List<SpeciesBatchRowModel> benthosBatchRows;
79  
80      protected CatchBatch catchBatch;
81  
82      protected Boolean modified;
83      protected Integer tabInError;
84  
85      public ComputeBatchWeightsAction(EditCatchesUIHandler handler) {
86          super(handler, true);
87          this.cleaningService = getContext().getWeightCleaningService();
88          this.persistenceService = getContext().getPersistenceService();
89      }
90  
91      @Override
92      public boolean prepareAction() throws Exception {
93  
94          // Clean internal states
95  
96          speciesBatchRows = null;
97          benthosBatchRows = null;
98          catchBatch = null;
99          modified = null;
100         tabInError = null;
101 
102         boolean doAction = super.prepareAction();
103         if (doAction) {
104 
105             // do a check of double weights
106             FishingOperation fishingOperation = getModel().getFishingOperation();
107             Multimap<String, String> errors = cleaningService.checkFishingOperation(fishingOperation.getIdAsInt());
108 
109             if (errors.isEmpty()) {
110 
111                 // no errors
112 
113                 sendMessage(t("tutti.editCatchBatch.action.computeWeights.no.double.weight.detected"));
114             } else {
115 
116                 // show errors to user as warning
117 
118                 String errorsStr = cleaningService.errorsToString(errors);
119                 String htmlMessage = t("tutti.editCatchBatch.action.computeWeights.double.weight.detected", errorsStr);
120 
121                 JOptionPane.showMessageDialog(getContext().getActionUI(),
122                                               htmlMessage,
123                                               t("tutti.editCatchBatch.action.computeWeights.double.weight.detected.title"),
124                                               JOptionPane.WARNING_MESSAGE);
125 
126 
127             }
128         }
129         return doAction;
130     }
131 
132     @Override
133     public void doAction() throws Exception {
134 
135         WeightComputingService computingService = getContext().getWeightComputingService();
136 
137         EditCatchesUIModel model = getModel();
138         Integer operationId = model.getFishingOperation().getIdAsInt();
139 
140         // ---------
141         // Compute species batches
142         // ---------
143 
144         BatchContainer<SpeciesBatch> computedSpeciesBatches = computingService.getComputedSpeciesBatches(operationId);
145 
146         Float totalSpeciesSortedWeight;
147         if (computedSpeciesBatches == null) {
148             totalSpeciesSortedWeight = 0f;
149         } else {
150             totalSpeciesSortedWeight = computeSpeciesBatches(getSpeciesBatchUI(), computedSpeciesBatches, speciesBatchRows = new ArrayList<>());
151         }
152 
153         // ---------
154         // Compute benthos batches
155         // ---------
156 
157         BatchContainer<SpeciesBatch> computedBenthosBatches = computingService.getComputedBenthosBatches(operationId);
158 
159         Float totalBenthosSortedWeight;
160         if (computedBenthosBatches == null) {
161             totalBenthosSortedWeight = 0f;
162         } else {
163             totalBenthosSortedWeight = computeSpeciesBatches(getBenthosBatchUI(), computedBenthosBatches, benthosBatchRows = new ArrayList<>());
164         }
165 
166         // ---------
167         // Compute marine litter batches
168         // ---------
169 
170         BatchContainer<MarineLitterBatch> computedMarineLitterBatches = computingService.getComputedMarineLitterBatches(operationId, model.getMarineLitterTotalWeight());
171 
172         modified = model.isModify();
173         catchBatch = model.toEntity();
174 
175         // ---------
176         // Check species rates
177         // ---------
178 
179         Float rate = getConfig().getDifferenceRateBetweenSortedAndTotalWeights();
180         //FIXME Do this in Weights
181         if (model.getSpeciesTotalSortedWeight() != null
182                 && model.getSpeciesTotalSortedWeight() >= totalSpeciesSortedWeight
183                 && model.getSpeciesTotalSortedWeight() < (1 + rate / 100) * totalSpeciesSortedWeight) {
184 
185             // Si  le "Poids total VRAC" est saisi est que sa valeur
186             // est supérieure de moins de x% (x en configuration)
187             // du "Poids total Vrac trié", demander confirmation que
188             // le "Poids total VRAC" est bien une valeur observée
189             // sinon la remplacer par le "Poids total Vrac trié"
190 
191             getUI().getTabPane().setSelectedIndex(1);
192 
193             String htmlMessage = String.format(
194                     AbstractTuttiUIHandler.CONFIRMATION_FORMAT,
195                     t("tutti.editCatchBatch.action.computeWeights.replaceTotalSortedWeight.message.species", rate),
196                     t("tutti.editCatchBatch.action.computeWeights.replaceTotalSortedWeight.help"));
197 
198             int answer = JOptionPane.showConfirmDialog(getContext().getActionUI(),
199                                                        htmlMessage,
200                                                        t("tutti.editCatchBatch.action.computeWeights.replaceTotalSortedWeight.title"),
201                                                        JOptionPane.YES_NO_OPTION,
202                                                        JOptionPane.QUESTION_MESSAGE);
203 
204             if (answer == JOptionPane.NO_OPTION) {
205 
206                 catchBatch.setSpeciesTotalSortedWeight(null);
207                 catchBatch.setSpeciesTotalSortedComputedWeight(totalSpeciesSortedWeight);
208                 modified = true;
209 
210             }
211 
212         }
213 
214         // ---------
215         // Check benthos rates
216         // ---------
217 
218         //FIXME Do this in Weights
219         if (model.getBenthosTotalSortedWeight() != null
220                 && model.getBenthosTotalSortedWeight() >= totalBenthosSortedWeight
221                 && model.getBenthosTotalSortedWeight() < (1 + rate / 100) * totalBenthosSortedWeight) {
222 
223             // Si  le "Poids total VRAC" est saisi est que sa valeur
224             // est supérieure de moins de x% (x en configuration)
225             // du "Poids total Vrac trié", demander confirmation que
226             // le "Poids total VRAC" est bien une valeur observée
227             // sinon la remplacer par le "Poids total Vrac trié"
228 
229             getUI().getTabPane().setSelectedIndex(2);
230 
231             String htmlMessage = String.format(
232                     AbstractTuttiUIHandler.CONFIRMATION_FORMAT,
233                     t("tutti.editCatchBatch.action.computeWeights.replaceTotalSortedWeight.message.benthos", rate),
234                     t("tutti.editCatchBatch.action.computeWeights.replaceTotalSortedWeight.help"));
235 
236             int answer = JOptionPane.showConfirmDialog(getContext().getActionUI(),
237                                                        htmlMessage,
238                                                        t("tutti.editCatchBatch.action.computeWeights.replaceTotalSortedWeight.title"),
239                                                        JOptionPane.YES_NO_OPTION,
240                                                        JOptionPane.QUESTION_MESSAGE);
241 
242             if (answer == JOptionPane.NO_OPTION) {
243 
244                 catchBatch.setBenthosTotalSortedWeight(null);
245                 catchBatch.setBenthosTotalSortedComputedWeight(totalBenthosSortedWeight);
246                 modified = true;
247 
248             }
249         }
250 
251         computingService.computeCatchBatchWeights(catchBatch,
252                                                   computedSpeciesBatches,
253                                                   computedBenthosBatches,
254                                                   computedMarineLitterBatches);
255 
256     }
257 
258     @Override
259     public void postSuccessAction() {
260         super.postSuccessAction();
261 
262         afterAction();
263 
264         getUI().repaint();
265     }
266 
267     protected void afterAction() {
268 
269         EditCatchesUIModel editCatchesUIModel = getModel();
270 
271         editCatchesUIModel.setLoadingData(true);
272 
273         SpeciesBatchUI speciesBatchUI = getSpeciesBatchUI();
274         SpeciesBatchUI benthosBatchesUI = getBenthosBatchUI();
275 
276         try {
277 
278             if (speciesBatchRows != null) {
279 
280                 SpeciesBatchUIHandler handler = speciesBatchUI.getHandler();
281                 handler.sortAndSetRow(speciesBatchUI.getModel(), speciesBatchRows);
282 
283             }
284 
285             if (benthosBatchRows != null) {
286 
287                 SpeciesBatchUIHandler handler = benthosBatchesUI.getHandler();
288                 handler.sortAndSetRow(benthosBatchesUI.getModel(), benthosBatchRows);
289 
290             }
291 
292             if (catchBatch != null) {
293 
294                 editCatchesUIModel.fromEntity(catchBatch);
295 
296             }
297 
298             if (modified != null) {
299 
300                 editCatchesUIModel.setModify(modified);
301 
302             }
303 
304         } finally {
305 
306             editCatchesUIModel.setLoadingData(false);
307 
308         }
309 
310 //        // keep sortMode
311 //        // see https://forge.codelutin.com/issues/5699
312 //        {
313 //            SpeciesBatchUIModel model = speciesBatchUI.getModel();
314 //            SpeciesSortMode sortMode = model.getSpeciesSortMode();
315 //            if (sortMode != SpeciesSortMode.NONE) {
316 //
317 //                // must reload order
318 //                model.setSpeciesSortMode(SpeciesSortMode.NONE);
319 //                model.setSpeciesSortMode(sortMode);
320 //
321 //            }
322 //        }
323 //
324 //        {
325 //            SpeciesBatchUIModel model = benthosBatchesUI.getModel();
326 //            SpeciesSortMode sortMode = model.getSpeciesSortMode();
327 //            if (sortMode != SpeciesSortMode.NONE) {
328 //
329 //                // must reload order
330 //                model.setSpeciesSortMode(SpeciesSortMode.NONE);
331 //                model.setSpeciesSortMode(sortMode);
332 //
333 //            }
334 //        }
335 
336     }
337 
338     @Override
339     public void postFailedAction(Throwable error) {
340 
341         afterAction();
342 
343         if (error instanceof CatchWeightComputingException) {
344 
345             getUI().getTabPane().setSelectedIndex(0);
346 
347         }
348 
349         if (error instanceof SpeciesWeightComputingException) {
350 
351             SpeciesWeightComputingException e = (SpeciesWeightComputingException) error;
352 
353             getUI().getTabPane().setSelectedIndex(1);
354 
355             treatSpeciesBatchError(getSpeciesBatchUI(), e);
356 
357         }
358 
359         if (error instanceof BenthosWeightComputingException) {
360 
361             BenthosWeightComputingException e = (BenthosWeightComputingException) error;
362 
363             getUI().getTabPane().setSelectedIndex(2);
364 
365             treatSpeciesBatchError(getBenthosBatchUI(), e);
366 
367         }
368 
369         if (error instanceof MarineLitterWeightComputingException) {
370 
371             MarineLitterWeightComputingException e = (MarineLitterWeightComputingException) error;
372 
373             getUI().getTabPane().setSelectedIndex(3);
374 
375             Optional<Integer> optionalRowIndex = e.getIndex();
376 
377             if (optionalRowIndex.isPresent()) {
378 
379                 JTables.doSelectCell(getUI().getMarineLitterTabContent().getTable(), optionalRowIndex.get(), 3);
380 
381             }
382 
383         }
384 
385     }
386 
387     //------------------------------------------------------------------------//
388     //-- Internal methods                                                   --//
389     //------------------------------------------------------------------------//
390 
391     protected Float computeSpeciesBatches(SpeciesBatchUI ui, BatchContainer<SpeciesBatch> computedSpeciesBatches, List<SpeciesBatchRowModel> speciesBatchRows) {
392 
393         Float totalSortedWeight = 0f;
394 
395         for (SpeciesBatch speciesBatch : computedSpeciesBatches.getChildren()) {
396             SpeciesBatchRowModel row = ui.getHandler().loadBatch(speciesBatch, null, speciesBatchRows);
397             if (persistenceService.isVracBatch(speciesBatch)) {
398                 SampleCategory<?> sampleCategory = row.getFirstSampleCategory();
399                 Float weight = Numbers.getValueOrComputedValue(sampleCategory.getCategoryWeight(), sampleCategory.getComputedWeight());
400                 totalSortedWeight += weight;
401             }
402         }
403 
404         return totalSortedWeight;
405 
406     }
407 
408     protected void treatSpeciesBatchError(SpeciesBatchUI ui, TuttiWeightComputingException e) {
409 
410         Optional<Integer> optionalRowIndex = e.getIndex();
411 
412         Optional<String> optionalProperty = e.getProperty();
413 
414         if (optionalRowIndex.isPresent() && optionalProperty.isPresent()) {
415 
416             SpeciesBatchUIModel speciesBatchUIModel = ui.getModel();
417 
418             Integer index = optionalRowIndex.get();
419 
420             SpeciesBatchRowModel row;
421 
422             if (SpeciesSortMode.NONE != speciesBatchUIModel.getSpeciesSortMode()) {
423 
424                 // must resort rows in natural order (in service we use this order)
425                 List<SpeciesBatchRowModel> rows = new ArrayList<>(speciesBatchUIModel.getRows());
426                 SpeciesBatchNaturalOrderComparator.sort(rows);
427                 // get the row
428                 row = rows.get(index);
429                 // get the correct rowIndex in the sorted list
430                 index = speciesBatchUIModel.getRows().indexOf(row);
431 
432             } else {
433 
434                 // correct order can directly get row from list
435                 List<SpeciesBatchRowModel> rows = speciesBatchUIModel.getRows();
436                 row = rows.get(index);
437 
438             }
439 
440             JXTable table = ui.getTable();
441             SpeciesBatchTableModel tableModel = (SpeciesBatchTableModel) table.getModel();
442             Set<SampleCategoryColumnIdentifier> sampleCols = tableModel.getSampleCols();
443             selectBatchCell(table, index, row, optionalProperty.get(), sampleCols, SpeciesBatchTableModel.WEIGHT);
444 
445         }
446 
447     }
448 
449     protected void selectBatchCell(JXTable table,
450                                    int index,
451                                    SpeciesBatchRowModel row,
452                                    String property,
453                                    Set<SampleCategoryColumnIdentifier> sampleCols,
454                                    ColumnIdentifier<SpeciesBatchRowModel> weightColumn) {
455 
456         ColumnIdentifier columnIdentifier = weightColumn;
457 
458         if (SpeciesBatch.PROPERTY_SAMPLE_CATEGORY_WEIGHT.equals(property)) {
459 
460             // get category column for category
461             Integer categoryId = row.getFinestCategory().getCategoryId();
462             for (SampleCategoryColumnIdentifier sampleCol : sampleCols) {
463                 if (categoryId.equals(sampleCol.getSampleCategoryId())) {
464                     columnIdentifier = sampleCol;
465                     break;
466                 }
467             }
468 
469         }
470 
471         int column = 0;
472         TableColumnExt columnExt = table.getColumnExt(columnIdentifier);
473         int modelIndex = columnExt.getModelIndex();
474         for (TableColumn tableColumn : table.getColumns(false)) {
475 
476             if (columnExt.equals(tableColumn) || tableColumn.getModelIndex() > modelIndex) {
477                 break;
478             }
479             column++;
480         }
481 
482         JTables.doSelectCell(table, index, column);
483 
484     }
485 
486     private SpeciesBatchUI getBenthosBatchUI() {
487         return getUI().getBenthosTabPanel().getEditBatchesUI();
488     }
489 
490     private SpeciesBatchUI getSpeciesBatchUI() {
491         return getUI().getSpeciesTabPanel().getEditBatchesUI();
492     }
493 
494 }