View Javadoc
1   package fr.ifremer.tutti.ui.swing.content.operation.catches.species.frequency;
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 fr.ifremer.tutti.persistence.entities.CaracteristicMap;
26  import fr.ifremer.tutti.persistence.entities.data.CopyIndividualObservationMode;
27  import fr.ifremer.tutti.persistence.entities.referential.Caracteristic;
28  import fr.ifremer.tutti.persistence.entities.referential.CaracteristicQualitativeValue;
29  import fr.ifremer.tutti.persistence.entities.referential.Species;
30  import fr.ifremer.tutti.type.WeightUnit;
31  import fr.ifremer.tutti.ui.swing.util.table.CaracteristicColumnIdentifier;
32  import org.apache.commons.collections4.CollectionUtils;
33  import org.jdesktop.swingx.table.TableColumnModelExt;
34  import org.nuiton.jaxx.application.swing.table.AbstractApplicationTableModel;
35  import org.nuiton.jaxx.application.swing.table.ColumnIdentifier;
36  
37  import java.io.Serializable;
38  import java.util.ArrayList;
39  import java.util.List;
40  import java.util.Objects;
41  import java.util.Set;
42  import java.util.function.Function;
43  import java.util.stream.Collectors;
44  
45  import static org.nuiton.i18n.I18n.n;
46  
47  /**
48   * @author Kevin Morin - kmorin@codelutin.com
49   * @since 1.4
50   */
51  public class IndividualObservationBatchTableModel extends AbstractApplicationTableModel<IndividualObservationBatchRowModel> {
52  
53      private static final long serialVersionUID = 1L;
54  
55      public static final ColumnIdentifier<IndividualObservationBatchRowModel> RANK = ColumnIdentifier.newId(
56              IndividualObservationBatchRowModel.PROPERTY_RANK_ORDER,
57              n("tutti.editIndividualObservationBatch.table.header.rank"),
58              n("tutti.editIndividualObservationBatch.table.header.rank.tip"));
59  
60      public static final ColumnIdentifier<IndividualObservationBatchRowModel> WEIGHT = ColumnIdentifier.newId(
61              IndividualObservationBatchRowModel.PROPERTY_WEIGHT,
62              n("tutti.editIndividualObservationBatch.table.header.weight"),
63              n("tutti.editIndividualObservationBatch.table.header.weight.tip"));
64  
65      public static final ColumnIdentifier<IndividualObservationBatchRowModel> SIZE = ColumnIdentifier.newId(
66              IndividualObservationBatchRowModel.PROPERTY_SIZE,
67              n("tutti.editIndividualObservationBatch.table.header.size"),
68              n("tutti.editIndividualObservationBatch.table.header.size.tip"));
69  
70      public static final MaturityColumnIdentifier MATURITY = new MaturityColumnIdentifier();
71  
72      public static final ColumnIdentifier<IndividualObservationBatchRowModel> OTHER_CARACTERISTICS = ColumnIdentifier.newId(
73              IndividualObservationBatchRowModel.PROPERTY_CARACTERISTICS,
74              n("tutti.editIndividualObservationBatch.table.header.otherCaracteristics"),
75              n("tutti.editIndividualObservationBatch.table.header.otherCaracteristics.tip"));
76  
77      public static final ColumnIdentifier<IndividualObservationBatchRowModel> SAMPLING_CODE = ColumnIdentifier.newId(
78              IndividualObservationBatchRowModel.PROPERTY_SAMPLING_CODE,
79              n("tutti.editIndividualObservationBatch.table.header.samplingCode"),
80              n("tutti.editIndividualObservationBatch.table.header.samplingCode.tip"));
81  
82      public static final ColumnIdentifier<IndividualObservationBatchRowModel> COMMENT = ColumnIdentifier.newId(
83              IndividualObservationBatchRowModel.PROPERTY_COMMENT,
84              n("tutti.editIndividualObservationBatch.table.header.comment"),
85              n("tutti.editIndividualObservationBatch.table.header.comment.tip"));
86  
87      public static final ColumnIdentifier<IndividualObservationBatchRowModel> ATTACHMENT = ColumnIdentifier.newReadOnlyId(
88              IndividualObservationBatchRowModel.PROPERTY_ATTACHMENT,
89              n("tutti.editIndividualObservationBatch.table.header.file"),
90              n("tutti.editIndividualObservationBatch.table.header.file.tip"));
91  
92      /**
93       * Weight unit.
94       *
95       * @since 2.5
96       */
97      protected final WeightUnit weightUnit;
98  
99      protected final CaracteristicMap defaultCaracteristicsMap;
100 
101     protected Species species;
102 
103     protected Caracteristic lengthstepCaracteristic;
104 
105     private final SpeciesFrequencyUIModel uiModel;
106     private final Function<IndividualObservationBatchRowModel, Void> installListenersOnRow;
107     private final Function<IndividualObservationBatchRowModel, Void> uninstallListenersOnRow;
108     private final IndividualObservationBatchUIModel model;
109 
110     public IndividualObservationBatchTableModel(WeightUnit weightUnit,
111                                                 SpeciesFrequencyUIModel uiModel,
112                                                 TableColumnModelExt columnModel,
113                                                 Function<IndividualObservationBatchRowModel, Void> installListenersOnRow,
114                                                 Function<IndividualObservationBatchRowModel, Void> uninstallListenersOnRow) {
115         super(columnModel, true, true);
116         this.uiModel = uiModel;
117         this.installListenersOnRow = installListenersOnRow;
118         this.uninstallListenersOnRow = uninstallListenersOnRow;
119         this.model = uiModel.getIndividualObservationModel();
120         this.weightUnit = weightUnit;
121         this.defaultCaracteristicsMap = new CaracteristicMap();
122         setNoneEditableCols(RANK);
123     }
124 
125     public void setSpecies(Species species) {
126         this.species = species;
127         if (rows != null) {
128             rows.forEach(row -> row.setSpecies(species));
129         }
130     }
131 
132     public void setLengthstepCaracteristic(Caracteristic lengthstepCaracteristic) {
133         this.lengthstepCaracteristic = lengthstepCaracteristic;
134         if (rows != null) {
135             rows.forEach(row -> row.setLengthStepCaracteristic(lengthstepCaracteristic));
136         }
137     }
138 
139     public void setDefaultCaracteristics(CaracteristicMap defaultCaracteristics) {
140         defaultCaracteristicsMap.clear();
141         defaultCaracteristicsMap.putAll(defaultCaracteristics);
142     }
143 
144     @Override
145     public IndividualObservationBatchRowModel createNewRow() {
146         IndividualObservationBatchRowModel result = new IndividualObservationBatchRowModel(weightUnit, defaultCaracteristicsMap);
147         result.setCopyIndividualObservationMode(uiModel.getCopyIndividualObservationMode());
148 
149         // by default empty row is not valid
150         result.setValid(false);
151         result.setRankOrder(getRowCount() + 1);
152         result.setSpecies(species);
153         result.setLengthStepCaracteristic(lengthstepCaracteristic);
154 
155         if (getRowCount() > 0) {
156             IndividualObservationBatchRowModel lastRow = getRows().get(getRowCount() - 1);
157 
158             CaracteristicQualitativeValue gender = model.getGender(lastRow);
159             model.setGenderValueToDefaultCaracterictis(result, gender);
160 
161             if (model.withMaturityCaracteristic()) {
162                 CaracteristicQualitativeValue maturityState = model.getMaturityValue(lastRow);
163                 model.setMaturityValueToDefaultCaracterictis(result, maturityState);
164             }
165         }
166 
167         return result;
168     }
169 
170     @Override
171     protected boolean isCellEditable(int rowIndex, int columnIndex,
172                                      ColumnIdentifier<IndividualObservationBatchRowModel> columnIdentifier) {
173 
174         boolean editable;
175         if (columnIdentifier instanceof MaturityColumnIdentifier) {
176 
177             MaturityColumnIdentifier maturityColumnIdentifier = (MaturityColumnIdentifier) columnIdentifier;
178 
179             editable = maturityColumnIdentifier.withCaracteristic();
180 
181             if (editable) {
182                 Serializable defaultValue = defaultCaracteristicsMap.get(maturityColumnIdentifier.getCaracteristic());
183                 editable = defaultValue == null;
184             }
185 
186         } else if (columnIdentifier instanceof CaracteristicColumnIdentifier) {
187 
188             CaracteristicColumnIdentifier<IndividualObservationBatchRowModel> caracteristicColumnIdentifier =
189                     (CaracteristicColumnIdentifier<IndividualObservationBatchRowModel>) columnIdentifier;
190 
191             Caracteristic caracteristic = caracteristicColumnIdentifier.getCaracteristic();
192             Serializable defaultValue = defaultCaracteristicsMap.get(caracteristic);
193 
194             editable = defaultValue == null;
195 
196         } else if (SAMPLING_CODE.equals(columnIdentifier)) {
197 
198             editable = getValueAt(rowIndex, columnIndex) == null && getValueAt(rowIndex, identifiers.indexOf(SIZE)) != null;
199 
200         } else {
201             editable = super.isCellEditable(rowIndex, columnIndex, columnIdentifier);
202         }
203         return editable;
204     }
205 
206     public List<IndividualObservationBatchRowModel> loadRows(List<IndividualObservationBatchRowModel> individualObservations) {
207 
208         List<IndividualObservationBatchRowModel> obsRows = new ArrayList<>();
209 
210         //FIXME Faire un check sur la méthode de mensuration qui doit être la même
211         if (CollectionUtils.isNotEmpty(individualObservations)) {
212 
213             CopyIndividualObservationMode copyIndividualObservationMode = null;
214 
215             int rankOrder = 1;
216             for (IndividualObservationBatchRowModel rowModel : individualObservations) {
217 
218                 CopyIndividualObservationMode incomingCopyIndividualObservationMode = rowModel.getCopyIndividualObservationMode();
219                 Objects.requireNonNull(incomingCopyIndividualObservationMode, "Mode de recopie non trouvé sur l'observation individuelle: " + rowModel.getId());
220                 if (copyIndividualObservationMode == null) {
221                     copyIndividualObservationMode = incomingCopyIndividualObservationMode;
222                 } else {
223                     if (copyIndividualObservationMode != incomingCopyIndividualObservationMode) {
224                         throw new IllegalStateException("Plusieurs modes de recopie trouvés sur les observations individuelles du lot, ce qui est impossible");
225                     }
226                 }
227                 IndividualObservationBatchRowModel newRow = createNewRow();
228                 newRow.copy(rowModel);
229                 newRow.setRankOrder(rankOrder++);
230                 newRow.setValid(true);
231 
232                 model.moveGenderValueFromCaracteristicsToDefaultCaracteristics(newRow);
233                 model.moveMaturityValueFromCaracteristicsToDefaultCaracteristics(newRow);
234 
235                 obsRows.add(newRow);
236 
237             }
238 
239         }
240 
241         return obsRows;
242 
243     }
244 
245     @Override
246     protected void onRowAdded(int rowIndex, IndividualObservationBatchRowModel row) {
247 
248         attachListeners(row);
249 
250         uiModel.recomputeCanEditLengthStep();
251         uiModel.setModify(true);
252 
253     }
254 
255     @Override
256     protected void onRowUpdated(int rowIndex, IndividualObservationBatchRowModel row) {
257 
258         uiModel.recomputeCanEditLengthStep();
259         uiModel.setModify(true);
260         model.recomputeRowValidState(row);
261 
262     }
263 
264     @Override
265     protected void onRowRemoved(int rowIndex, IndividualObservationBatchRowModel row) {
266 
267         dettachListeners(row);
268 
269         uiModel.recomputeCanEditLengthStep();
270         uiModel.recomputeRowsValidateState();
271 
272     }
273 
274     @Override
275     protected void onBeforeRowsChanged(List<IndividualObservationBatchRowModel> oldRows) {
276 
277         if (oldRows != null) {
278             oldRows.forEach(this::dettachListeners);
279         }
280 
281     }
282 
283     @Override
284     protected void onRowsChanged(List<IndividualObservationBatchRowModel> newRows) {
285 
286         int rankOrder = 1;
287         for (IndividualObservationBatchRowModel row : newRows) {
288             attachListeners(row);
289             row.setRankOrder(rankOrder++);
290         }
291         newRows.forEach(this::attachListeners);
292 
293         uiModel.recomputeCanEditLengthStep();
294         uiModel.recomputeRowsValidateState();
295 
296     }
297 
298     public IndividualObservationBatchRowModel addRafaleRow(Float step) {
299 
300         IndividualObservationBatchRowModel row = getEmptyRow();
301         if (row == null) {
302             row = createNewRow();
303             addNewRow(row);
304         }
305         row.setSize(step);
306         updateRow(row);
307 
308         return row;
309 
310     }
311 
312     private IndividualObservationBatchRowModel getEmptyRow() {
313 
314         IndividualObservationBatchRowModel result = null;
315 
316         for (int i = rows.size() - 1; i >= 0; i--) {
317             IndividualObservationBatchRowModel row = rows.get(i);
318             // if the row has no data set, then it could be the empty row we are looking for
319             Set<Caracteristic> notNullCaracteristics = defaultCaracteristicsMap.keySet().stream()
320                                                                                .filter(key -> defaultCaracteristicsMap.get(key) != null)
321                                                                                .collect(Collectors.toSet());
322             if (row.isEmpty(notNullCaracteristics)) {
323 
324                 result = row;
325 
326             } else { // if the row has data set, then the empty row we are looking for was the previous row
327                 break;
328             }
329 
330         }
331 
332         return result;
333 
334     }
335 
336     private void dettachListeners(IndividualObservationBatchRowModel result) {
337         uninstallListenersOnRow.apply(result);
338     }
339 
340     private void attachListeners(IndividualObservationBatchRowModel result) {
341         dettachListeners(result); // prevent leaks!
342         installListenersOnRow.apply(result);
343     }
344 
345 }