View Javadoc
1   package fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped;
2   
3   /*
4    * #%L
5    * Dali :: 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 fr.ifremer.dali.dto.DaliBeanFactory;
27  import fr.ifremer.dali.dto.DaliBeans;
28  import fr.ifremer.dali.dto.data.measurement.MeasurementDTO;
29  import fr.ifremer.dali.dto.data.sampling.SamplingOperationDTO;
30  import fr.ifremer.dali.dto.referential.pmfm.PmfmDTO;
31  import fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped.initGrid.InitGridUI;
32  import fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped.initGrid.InitGridUIModel;
33  import fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped.initGrid.PresetFileLoader;
34  import fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped.multiedit.OperationMeasurementsMultiEditUI;
35  import fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped.multiedit.OperationMeasurementsMultiEditUIModel;
36  import fr.ifremer.dali.ui.swing.content.observation.operation.measurement.grouped.shared.AbstractOperationMeasurementsGroupedTableUIHandler;
37  import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIModel;
38  import fr.ifremer.dali.ui.swing.util.table.DaliColumnIdentifier;
39  import fr.ifremer.dali.vo.PresetVO;
40  import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
41  import fr.ifremer.quadrige3.ui.swing.table.action.AdditionalTableActions;
42  import jaxx.runtime.SwingUtil;
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  import org.jdesktop.swingx.table.TableColumnExt;
46  
47  import javax.swing.JComponent;
48  import javax.swing.JPanel;
49  import javax.swing.JScrollPane;
50  import javax.swing.RowFilter;
51  import java.awt.Dimension;
52  import java.awt.Insets;
53  import java.util.ArrayList;
54  import java.util.List;
55  import java.util.Map;
56  import java.util.Objects;
57  
58  /**
59   * Controleur pour les mesures des prelevements (ecran prelevements/mesure).
60   */
61  public class OperationMeasurementsGroupedTableUIHandler
62          extends AbstractOperationMeasurementsGroupedTableUIHandler<OperationMeasurementsGroupedRowModel, OperationMeasurementsGroupedTableUIModel, OperationMeasurementsGroupedTableUI> {
63  
64      private static final Log LOG = LogFactory.getLog(OperationMeasurementsGroupedTableUIHandler.class);
65  
66      /**
67       * <p>Constructor for OperationMeasurementsGroupedTableUIHandler.</p>
68       */
69      public OperationMeasurementsGroupedTableUIHandler() {
70          super(OperationMeasurementsGroupedRowModel.PROPERTY_SAMPLING_OPERATION,
71                  OperationMeasurementsGroupedRowModel.PROPERTY_TAXON_GROUP,
72                  OperationMeasurementsGroupedRowModel.PROPERTY_TAXON,
73                  OperationMeasurementsGroupedRowModel.PROPERTY_INDIVIDUAL_PMFMS,
74                  OperationMeasurementsGroupedRowModel.PROPERTY_COMMENT);
75      }
76  
77      /**
78       * {@inheritDoc}
79       */
80      @Override
81      public OperationMeasurementsGroupedTableModel getTableModel() {
82          return (OperationMeasurementsGroupedTableModel) getTable().getModel();
83      }
84  
85      /**
86       * {@inheritDoc}
87       */
88      @Override
89      public SwingTable getTable() {
90          return getUI().getOperationGroupedMeasurementTable();
91      }
92  
93      @Override
94      protected OperationMeasurementsGroupedTableUIModel createNewModel() {
95          return new OperationMeasurementsGroupedTableUIModel();
96      }
97  
98      @Override
99      protected OperationMeasurementsGroupedRowModel createNewRow(boolean readOnly, SamplingOperationDTO parentBean) {
100         OperationMeasurementsGroupedRowModel row = new OperationMeasurementsGroupedRowModel(readOnly);
101         row.setSamplingOperation(parentBean);
102         return row;
103     }
104 
105     /**
106      * {@inheritDoc}
107      */
108     @Override
109     public void afterInit(final OperationMeasurementsGroupedTableUI ui) {
110 
111         super.afterInit(ui);
112 
113         SwingUtil.setLayerUI(ui.getTableauBasScrollPane(), ui.getTableBlockLayer());
114 
115         initActionComboBox(ui.getInitDataGridComboBox());
116 
117         // Les boutons sont desactives
118         getUI().getDeleteButton().setEnabled(false);
119         getUI().getDuplicateButton().setEnabled(false);
120 
121     }
122 
123     /**
124      * Initialiser les listeners
125      */
126     protected void initListeners() {
127         super.initListeners();
128 
129         getModel().addPropertyChangeListener(evt -> {
130 
131             if (AbstractDaliTableUIModel.PROPERTY_ROWS.equals(evt.getPropertyName())) {// update some controls
132                 getUI().processDataBinding(OperationMeasurementsGroupedTableUI.BINDING_INIT_DATA_GRID_COMBO_BOX_ENABLED);
133             }
134         });
135 
136     }
137 
138     protected void filterMeasurements() {
139 
140         // sampling operation column should not be editable if only one sampling operation
141         getTable().getColumnExt(OperationMeasurementsGroupedTableModel.SAMPLING).setEditable(getModel().getSamplingFilter() == null);
142 //        getTable().getColumnExt(OperationMeasurementsGroupedTableModel.TAXON_GROUP).setEditable(getModel().getTaxonGroupFilter() == null);
143 //        getTable().getColumnExt(OperationMeasurementsGroupedTableModel.TAXON).setEditable(getModel().getTaxonFilter() == null);
144 
145         if (getModel().getSamplingFilter() == null /*&& getModel().getTaxonGroupFilter() == null && getModel().getTaxonFilter() == null*/) {
146             // remove filter
147             getTable().setRowFilter(null);
148         } else {
149             // add filter on sampling operation (for the moment)
150             getTable().setRowFilter(new OperationRowFilter(getTable().getColumnExt(OperationMeasurementsGroupedTableModel.SAMPLING).getModelIndex()));
151         }
152 
153         getUI().applyDataBinding(OperationMeasurementsGroupedTableUI.BINDING_INIT_DATA_GRID_COMBO_BOX_ENABLED);
154     }
155 
156     class OperationRowFilter extends RowFilter<OperationMeasurementsGroupedTableModel, Integer> {
157 
158         private final int samplingModelIndex;
159 
160         OperationRowFilter(int samplingModelIndex) {
161             this.samplingModelIndex = samplingModelIndex;
162         }
163 
164         @Override
165         public boolean include(Entry<? extends OperationMeasurementsGroupedTableModel, ? extends Integer> entry) {
166             return (getModel().getSamplingFilter() == null
167                 || getModel().getSamplingFilter().equals(entry.getValue(samplingModelIndex)))
168                             /*&& (getModel().getTaxonGroupFilter() == null
169                             || getModel().getTaxonGroupFilter().equals(taxonGroupModelIndex)))
170                             && (getModel().getTaxonFilter() == null
171                             || getModel().getTaxonFilter().equals(entry.getValue(taxonModelIndex)))*/;
172         }
173     }
174 
175     /**
176      * Initialisation du tableau.
177      */
178     protected void initTable() {
179 
180         // La table des prelevements
181         final SwingTable table = getTable();
182 
183         // Colonne mnemonique
184         samplingOperationCellEditor = newExtendedComboBoxCellEditor(new ArrayList<>(), SamplingOperationDTO.class, false);
185         final TableColumnExt colName = addFixedColumn(
186                 samplingOperationCellEditor,
187                 newTableCellRender(OperationMeasurementsGroupedTableModel.SAMPLING),
188                 OperationMeasurementsGroupedTableModel.SAMPLING);
189         colName.setCellEditor(samplingOperationCellEditor);
190         colName.setSortable(true);
191         colName.setMinWidth(100);
192 
193         if (getConfig().isDebugMode()) {
194             TableColumnExt indivIdCol = addColumn(OperationMeasurementsGroupedTableModel.INDIVIDUAL_ID);
195             indivIdCol.setSortable(true);
196             setDefaultColumnMinWidth(indivIdCol);
197         }
198 
199         // Colonne groupe taxon
200         final TableColumnExt colTaxonGroup = addColumn(
201                 taxonGroupCellEditor,
202                 newTableCellRender(OperationMeasurementsGroupedTableModel.TAXON_GROUP),
203                 OperationMeasurementsGroupedTableModel.TAXON_GROUP);
204         colTaxonGroup.setSortable(true);
205         setDefaultColumnMinWidth(colTaxonGroup);
206 
207         // Colonne taxon
208         final TableColumnExt colTaxon = addColumn(
209                 taxonCellEditor,
210                 newTableCellRender(OperationMeasurementsGroupedTableModel.TAXON),
211                 OperationMeasurementsGroupedTableModel.TAXON);
212         colTaxon.setSortable(true);
213         setDefaultColumnMinWidth(colTaxon);
214 
215         // Colonne taxon saisi
216         final TableColumnExt colInputTaxon = addColumn(OperationMeasurementsGroupedTableModel.INPUT_TAXON_NAME);
217         colInputTaxon.setSortable(true);
218         colInputTaxon.setEditable(false);
219         setDefaultColumnMinWidth(colInputTaxon);
220 
221         // Colonne analyste
222         final TableColumnExt colAnalyst = addColumn(
223                 departmentCellEditor,
224                 newTableCellRender(OperationMeasurementsGroupedTableModel.ANALYST),
225                 OperationMeasurementsGroupedTableModel.ANALYST);
226         colAnalyst.setSortable(true);
227         setDefaultColumnMinWidth(colAnalyst);
228 
229         // Colonne commentaire
230         TableColumnExt colComment = addCommentColumn(OperationMeasurementsGroupedTableModel.COMMENT);
231         setDefaultColumnMinWidth(colComment);
232 
233         // Modele de la table
234         final OperationMeasurementsGroupedTableModel tableModel = new OperationMeasurementsGroupedTableModel(getTable().getColumnModel(), true);
235         table.setModel(tableModel);
236 
237         // Add numeric total
238         addColumnTotalAction();
239 
240         // Initialisation de la table
241         initTable(table);
242 
243         colTaxonGroup.setVisible(false);
244         colTaxon.setVisible(false);
245         colInputTaxon.setVisible(false);
246         colComment.setVisible(false);
247         colAnalyst.setVisible(false);
248 
249         // border
250         addEditionPanelBorder(JPanel.class);
251     }
252 
253     private void addColumnTotalAction() {
254 
255         OperationMeasurementsTotalFooterAction action = new OperationMeasurementsTotalFooterAction(this);
256         action.putValue(AdditionalTableActions.ACTION_TARGET_GROUP, 0);
257         getAdditionalTableActions().addAction(action);
258 
259     }
260 
261     /**
262      * Initialize the data grid
263      */
264     void initializeDataGrid(boolean configure) {
265 
266         boolean initOK = true;
267         String programCode = getModel().getSurvey().getProgram().getCode();
268         PresetVO preset = PresetFileLoader.load(programCode);
269 
270         List<PmfmDTO> availablePmfms = DaliBeans.filterCollection(getModel().getPmfms(), input -> input.getParameter().isQualitative());
271 
272         if (preset != null) {
273 
274             // validate integrity
275             Map<Integer, PmfmDTO> pmfmByIds = DaliBeans.mapById(availablePmfms);
276 
277             for (Integer pmfmPresetId : preset.getPmfmIds()) {
278                 PmfmDTO pmfm = pmfmByIds.get(pmfmPresetId);
279                 if (pmfm == null) {
280                     initOK = false;
281                     break;
282                 } else {
283                     List<Integer> qualitativeValueIds = DaliBeans.collectIds(pmfm.getQualitativeValues());
284                     if (!qualitativeValueIds.containsAll(preset.getQualitativeValueIds(pmfmPresetId))) {
285                         initOK = false;
286                         break;
287                     }
288                 }
289             }
290 
291         } else {
292 
293             // create new preset
294             preset = new PresetVO(programCode);
295             initOK = false;
296         }
297 
298         if (configure || !initOK) {
299 
300             InitGridUI initGridUI = new InitGridUI(getContext());
301             InitGridUIModel initModel = initGridUI.getModel();
302 
303             // Set available pmfms
304             initModel.setAvailablePmfms(availablePmfms);
305             // Set presets if exists, AFTER available pmfms
306             initModel.setPreset(preset);
307 
308             openDialog(initGridUI, new Dimension(1000, (int) (getContext().getMainUI().getHeight() * 0.95)));
309 
310             preset = initModel.getPreset();
311             initOK = initModel.isValid();
312 
313         }
314 
315         if (initOK) {
316 
317             getModel().setLoading(true);
318             GridInitializer gridInitializer = new GridInitializer(this, preset);
319             gridInitializer.execute();
320 
321         }
322     }
323 
324     public void editSelectedMeasurements() {
325 
326         OperationMeasurementsMultiEditUI multiEditUI = new OperationMeasurementsMultiEditUI(getUI());
327 
328         // add the calculated transition pmfm as read-only
329 //        editUI.getModel().setReadOnlyPmfmIds(
330 //            Stream.of(
331 //                getModel().getPitTransitionLengthPmfmId(),
332 //                getModel().getPitTransectLengthPmfmId(),
333 //                getModel().getPitTransectOriginPmfmId(),
334 //                getModel().getCalculatedLengthEndPositionPmfmId(),
335 //                getModel().getCalculatedLengthTransitionPmfmId()
336 //            ).filter(Objects::nonNull).collect(Collectors.toList())
337 //        );
338 
339         // save current table state to be able to restore it in dialog's table
340         saveTableState();
341 
342 //        Assert.isInstanceOf(DaliUI.class, dialog);
343 //        DaliUI<?, ?> multiEditUI = (DaliUI<?, ?>) dialog;
344 //        Assert.isInstanceOf(OperationMeasurementsMultiEditUIModel.class, multiEditUI.getModel());
345         OperationMeasurementsMultiEditUIModel multiEditModel = multiEditUI.getModel();
346         multiEditModel.setObservationHandler(getModel().getObservationUIHandler());
347         multiEditModel.setRowsToEdit(getModel().getSelectedRows());
348         multiEditModel.setPmfms(getModel().getPmfms());
349         multiEditModel.setSurvey(getModel().getSurvey());
350 
351         // get parent component for dialog centering
352         JComponent parent = getUI().getParentContainer(getTable(), JScrollPane.class);
353         Insets borderInsets = parent.getBorder() != null ? parent.getBorder().getBorderInsets(parent) : new Insets(0,5,0,5);
354         openDialog(multiEditUI, new Dimension(parent.getWidth() + borderInsets.left + borderInsets.right, 160), true, parent);
355 
356         // if dialog is valid
357         if (multiEditModel.isValid()) {
358 
359             // affect all non multiple column values to selected rows
360             OperationMeasurementsGroupedRowModel multiEditRow = multiEditModel.getRows().get(0);
361 
362             for (OperationMeasurementsGroupedRowModel row : getModel().getSelectedRows()) {
363 
364                 // affect column values
365                 for (DaliColumnIdentifier<OperationMeasurementsGroupedRowModel> identifier : multiEditModel.getIdentifiersToCheck()) {
366                     // be sure that sampling operation value can not be changed
367                     if (identifier.getPropertyName().equals(OperationMeasurementsGroupedRowModel.PROPERTY_SAMPLING_OPERATION))
368                         continue;
369 
370                     // get values
371                     Object multiValue = identifier.getValue(multiEditRow);
372                     Object currentValue = identifier.getValue(row);
373                     boolean isMultiple = multiEditRow.getMultipleValuesOnIdentifier().contains(identifier);
374                     // affect value if a multiple value has been replaced, or modification has been made
375                     if ((!isMultiple || multiValue != null) && !Objects.equals(multiValue, currentValue)) {
376                         identifier.setValue(row, multiValue);
377                         // special case for INPUT_TAXON_NAME
378                         if (identifier.getPropertyName().equals(OperationMeasurementsGroupedRowModel.PROPERTY_INPUT_TAXON_NAME)) {
379                             // affect also INPUT_TAXON_ID
380                             row.setInputTaxonId(multiEditRow.getInputTaxonId());
381                         }
382                     }
383                 }
384 
385                 // for measurement columns
386                 for (PmfmDTO pmfm : getModel().getPmfms()) {
387                     MeasurementDTO multiMeasurement = DaliBeans.getIndividualMeasurementByPmfmId(multiEditRow, pmfm.getId());
388                     if (multiMeasurement == null) {
389                         // can happened if user pass on on a cel without setting a value
390                         multiMeasurement = DaliBeanFactory.newMeasurementDTO();
391                     }
392                     boolean isMultiple = multiEditRow.getMultipleValuesOnPmfmIds().contains(pmfm.getId());
393                     // affect value if a multiple value has been replaced, or modification has been made
394                     if (!isMultiple || !DaliBeans.isMeasurementEmpty(multiMeasurement)) {
395                         MeasurementDTO measurement = DaliBeans.getIndividualMeasurementByPmfmId(row, pmfm.getId());
396                         if (measurement == null) {
397                             // create and add the measurement if not exists
398                             measurement = DaliBeanFactory.newMeasurementDTO();
399                             measurement.setPmfm(pmfm);
400                             measurement.setIndividualId(row.getIndividualId());
401                             row.getIndividualMeasurements().add(measurement);
402                         }
403                         // affect value (either numeric or qualitative)
404                         if (!DaliBeans.measurementValuesEquals(multiMeasurement, measurement)) {
405                             measurement.setNumericalValue(multiMeasurement.getNumericalValue());
406                             measurement.setQualitativeValue(multiMeasurement.getQualitativeValue());
407                         }
408                     }
409                 }
410 
411             }
412 
413             // done
414             getModel().setModify(true);
415             getTable().repaint();
416         }
417 
418     }
419 
420 }