View Javadoc
1   package fr.ifremer.reefdb.ui.swing.content.observation.operation.measurement.grouped.initGrid;
2   
3   /*
4    * #%L
5    * Reef DB :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   *
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   *
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import com.google.common.collect.ImmutableList;
27  import fr.ifremer.reefdb.dto.ReefDbBeans;
28  import fr.ifremer.reefdb.dto.data.measurement.MeasurementDTO;
29  import fr.ifremer.reefdb.dto.data.sampling.SamplingOperationDTO;
30  import fr.ifremer.reefdb.ui.swing.util.AbstractReefDbUIHandler;
31  import jaxx.runtime.validator.swing.SwingValidator;
32  import org.apache.commons.collections4.CollectionUtils;
33  import org.nuiton.jaxx.application.swing.util.Cancelable;
34  
35  import javax.annotation.Nonnull;
36  import javax.swing.JComponent;
37  import java.math.BigDecimal;
38  import java.util.*;
39  import java.util.stream.Collectors;
40  
41  import static org.nuiton.i18n.I18n.t;
42  
43  /**
44   * <p>InitGridUIHandler class.</p>
45   */
46  public class InitGridUIHandler extends AbstractReefDbUIHandler<InitGridUIModel, InitGridUI> implements Cancelable {
47  
48      /**
49       * {@inheritDoc}
50       */
51      @Override
52      public void beforeInit(InitGridUI ui) {
53          super.beforeInit(ui);
54  
55          InitGridUIModel model = new InitGridUIModel();
56          ui.setContextValue(model);
57      }
58  
59      /**
60       * {@inheritDoc}
61       */
62      @Override
63      public void afterInit(InitGridUI ui) {
64          initUI(ui);
65  
66          initBeanFilterableComboBox(ui.getSamplingOperationComboBox(), new ArrayList<>(), null);
67  
68          initListeners();
69  
70          // Register validator
71          registerValidators(getValidator());
72          listenValidatorValid(getValidator(), getModel());
73  
74      }
75  
76      private void initListeners() {
77  
78          getModel().addPropertyChangeListener(evt -> {
79  
80              if (InitGridUIModel.PROPERTY_SAMPLING_OPERATIONS.equals(evt.getPropertyName())) {
81                  // load sampling operations
82                  getUI().getSamplingOperationComboBox().setData(getModel().getSamplingOperations());
83  
84              } else if (InitGridUIModel.PROPERTY_SAMPLING_OPERATION.equals(evt.getPropertyName())) {
85  
86                  if (getModel().getSamplingOperation() != null) {
87  
88                      // build existing transitions values map
89                      buildCurrentMap(ImmutableList.of(getModel().getSamplingOperation()));
90  
91                      // Try to find the last transition gap and set it
92                      getModel().setTransition(findLastTransition());
93  
94                      // find origin and length value
95                      MeasurementDTO originMeasurement = ReefDbBeans.getMeasurementByPmfmId(getModel().getSamplingOperation(), getModel().getOriginPmfmId());
96                      if (!ReefDbBeans.isMeasurementEmpty(originMeasurement) && getModel().getOriginUnit() != null && getModel().getTransitionUnit() != null) {
97                          getModel().setOrigin(ReefDbBeans.convertLengthValue(
98                              originMeasurement.getNumericalValue(),
99                              getModel().getOriginUnit().getId(),
100                             getModel().getTransitionUnit().getId()
101                         ).intValue());
102                     } else {
103                         getModel().setOrigin(getConfig().getPitOriginDefaultValue());
104                     }
105 
106                     MeasurementDTO lengthMeasurement = ReefDbBeans.getMeasurementByPmfmId(getModel().getSamplingOperation(), getModel().getLengthPmfmId());
107                     if (!ReefDbBeans.isMeasurementEmpty(lengthMeasurement) && getModel().getLengthUnit() != null && getModel().getTransitionUnit() != null) {
108                         getModel().setLength(ReefDbBeans.convertLengthValue(
109                             lengthMeasurement.getNumericalValue(),
110                             getModel().getLengthUnit().getId(),
111                             getModel().getTransitionUnit().getId()
112                         ).intValue());
113                     } else {
114                         getModel().setLength(getConfig().getPitTransectLengthDefaultValue());
115                     }
116 
117                 } else {
118 
119                     // reset
120                     getModel().setOrigin(null);
121                     getModel().setTransition(null);
122                     getModel().setLength(null);
123                 }
124 
125             } else if (InitGridUIModel.PROPERTY_ALL_SAMPLING_OPERATIONS.equals(evt.getPropertyName())) {
126 
127                 if (getModel().isAllSamplingOperations()) {
128 
129                     // try to get a unique value
130                     if (CollectionUtils.isNotEmpty(getModel().getSamplingOperations())) {
131 
132                         // build existing transitions values map
133                         buildCurrentMap(getModel().getSamplingOperations());
134 
135                         // Try to find the last transition gap and set it
136                         getModel().setTransition(findLastTransition());
137 
138                         // find origin and length value
139                         Integer origin = null;
140                         boolean sameOrigin = true;
141                         Integer length = null;
142                         boolean sameLength = true;
143 
144                         for (SamplingOperationDTO samplingOperation : getModel().getSamplingOperations()) {
145                             MeasurementDTO originMeasurement = ReefDbBeans.getMeasurementByPmfmId(samplingOperation, getModel().getOriginPmfmId());
146                             if (!ReefDbBeans.isMeasurementEmpty(originMeasurement)) {
147                                 if (origin == null) {
148                                     origin = originMeasurement.getNumericalValue().intValue();
149                                 } else if (origin != originMeasurement.getNumericalValue().intValue()) {
150                                     sameOrigin = false;
151                                 }
152                             }
153                             MeasurementDTO lengthMeasurement = ReefDbBeans.getMeasurementByPmfmId(samplingOperation, getModel().getLengthPmfmId());
154                             if (!ReefDbBeans.isMeasurementEmpty(lengthMeasurement)) {
155                                 if (length == null) {
156                                     length = lengthMeasurement.getNumericalValue().intValue();
157                                 } else if (length != lengthMeasurement.getNumericalValue().intValue()) {
158                                     sameLength = false;
159                                 }
160                             }
161                         }
162 
163                         if (sameOrigin && origin != null && getModel().getOriginUnit() != null && getModel().getTransitionUnit() != null) {
164                             getModel().setOrigin(ReefDbBeans.convertLengthValue(
165                                 BigDecimal.valueOf(origin),
166                                 getModel().getOriginUnit().getId(),
167                                 getModel().getTransitionUnit().getId()
168                             ).intValue());
169                         } else {
170                             getModel().setOrigin(getConfig().getPitOriginDefaultValue());
171                         }
172                         if (sameLength && length != null && getModel().getLengthUnit() != null && getModel().getTransitionUnit() != null) {
173                             getModel().setLength(ReefDbBeans.convertLengthValue(
174                                 BigDecimal.valueOf(length),
175                                 getModel().getLengthUnit().getId(),
176                                 getModel().getTransitionUnit().getId()
177                             ).intValue());
178                         } else {
179                             getModel().setLength(getConfig().getPitTransectLengthDefaultValue());
180                         }
181 
182                     } else {
183 
184                         // reset
185                         getModel().setOrigin(null);
186                         getModel().setTransition(null);
187                         getModel().setLength(null);
188                     }
189 
190                 } else {
191 
192                     // fire again on selected sampling operation
193                     getModel().firePropertyChanged(InitGridUIModel.PROPERTY_SAMPLING_OPERATION, null, getModel().getSamplingOperation());
194                 }
195 
196             } else if (InitGridUIModel.PROPERTY_TRANSITION_UNIT.equals(evt.getPropertyName())) {
197                 // set unit text from transition unit
198                 getUI().getOriginUnit().setText(getModel().getTransitionUnit().getSymbol());
199                 getUI().getTransitionUnit().setText(getModel().getTransitionUnit().getSymbol());
200                 getUI().getLengthUnit().setText(getModel().getTransitionUnit().getSymbol());
201 
202             }
203         });
204 
205     }
206 
207     /**
208      * {@inheritDoc}
209      */
210     @Override
211     protected JComponent getComponentToFocus() {
212         return getUI().getSamplingOperationComboBox();
213     }
214 
215     /**
216      * <p>valid.</p>
217      */
218     public void valid() {
219 
220         // Valid the values
221         if (!getModel().areValuesValid()) {
222             if (getModel().isContiguousSamplingOperations()) {
223                 getContext().getDialogHelper().showErrorDialog(
224                     t("reefdb.validator.error.samplingOperation.measurement.grouped.init.contiguous",
225                         getModel().getSamplingOperations().size(),
226                         getModel().getOrigin(), getModel().getTransition(), getModel().getLength())
227                 );
228             } else {
229                 getContext().getDialogHelper().showErrorDialog(
230                     t("reefdb.validator.error.samplingOperation.measurement.grouped.init",
231                         getModel().getOrigin(), getModel().getTransition(), getModel().getLength())
232                 );
233             }
234             return;
235         }
236 
237         buildResultMap();
238 
239         if (getModel().isValid()) {
240             closeDialog();
241         }
242     }
243 
244     /**
245      * {@inheritDoc}
246      */
247     @Override
248     public void cancel() {
249         stopListenValidatorValid(getValidator());
250         getModel().setValid(false);
251         closeDialog();
252     }
253 
254     /**
255      * {@inheritDoc}
256      */
257     @Override
258     public SwingValidator<InitGridUIModel> getValidator() {
259         return getUI().getValidator();
260     }
261 
262     /**
263      * Build current transition values
264      *
265      * @param samplingOperations selected sampling operations
266      */
267     private void buildCurrentMap(@Nonnull List<SamplingOperationDTO> samplingOperations) {
268         getModel().getCurrentMap().clear();
269         samplingOperations.forEach(samplingOperation -> getModel().getCurrentMap().putAll(samplingOperation, getExistingTransitionValues(samplingOperation)));
270 
271         // Try to find contiguous sampling operations
272         if (getModel().getCurrentMap().keySet().size() > 1) {
273             // if all values are unique, these can be contiguous
274             getModel().setContiguousSamplingOperations(
275                 getModel().getCurrentMap().values().stream().allMatch(new HashSet<>()::add)
276             );
277         }
278     }
279 
280     // find the gap of the last sampling operation input
281     private Integer findLastTransition() {
282         return getLastTransition((List<Integer>) getModel().getCurrentMap().get(
283             getModel().isAllSamplingOperations() ? getModel().getLastSamplingOperation() : getModel().getSamplingOperation()
284         ));
285     }
286 
287     // Calculate the gap between the 2 last transition values
288     private Integer getLastTransition(List<Integer> transitions) {
289         if (CollectionUtils.size(transitions) < 2)
290             return null;
291         return transitions.get(transitions.size() - 1) - transitions.get(transitions.size() - 2);
292     }
293 
294     private List<Integer> getExistingTransitionValues(SamplingOperationDTO samplingOperation) {
295         return ReefDbBeans.getIndividualMeasurementsByPmfmId(samplingOperation, getModel().getTransitionPmfmId()).stream()
296             .filter(measurement -> measurement.getNumericalValue() != null)
297             .map(measurement -> measurement.getNumericalValue().intValue())
298             .sorted()
299             .collect(Collectors.toList());
300     }
301 
302     /**
303      * Build result map of all transition values for each sampling operation, except those already in current map
304      */
305     private void buildResultMap() {
306         getModel().getResultMap().clear();
307 
308         List<SamplingOperationDTO> samplingOperations = getModel().isAllSamplingOperations()
309             ? getModel().getSamplingOperations()
310             : Collections.singletonList(getModel().getSamplingOperation());
311 
312         int origin = getModel().getOrigin();
313         int lengthBySamplingOperation = getModel().isContiguousSamplingOperations()
314             ? getModel().getLength() / getModel().getSamplingOperations().size()
315             : getModel().getLength();
316         int length = lengthBySamplingOperation;
317 
318         for (SamplingOperationDTO samplingOperation : samplingOperations) {
319             for (int value = origin; value <= length; value += getModel().getTransition()) {
320                 if (!getModel().getCurrentMap().containsEntry(samplingOperation, value)) {
321                     getModel().getResultMap().put(samplingOperation, value);
322                 }
323             }
324             if (getModel().isContiguousSamplingOperations()) {
325                 origin += lengthBySamplingOperation;
326                 length += lengthBySamplingOperation;
327             }
328         }
329 
330     }
331 }