View Javadoc
1   package fr.ifremer.dali.ui.swing.content.observation.operation.measurement.ungrouped;
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.decorator.DecoratorService;
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.enums.FilterTypeValues;
31  import fr.ifremer.dali.dto.referential.DepartmentDTO;
32  import fr.ifremer.dali.service.DaliTechnicalException;
33  import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIHandler;
34  import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
35  import fr.ifremer.quadrige3.ui.swing.table.editor.ExtendedComboBoxCellEditor;
36  import jaxx.runtime.SwingUtil;
37  import org.apache.commons.collections4.CollectionUtils;
38  import org.jdesktop.swingx.table.TableColumnExt;
39  
40  import javax.swing.RowFilter;
41  import javax.swing.SwingUtilities;
42  import java.util.HashMap;
43  import java.util.Map;
44  import java.util.Optional;
45  
46  import static org.nuiton.i18n.I18n.t;
47  
48  /**
49   * Controleur pour le tableau du haut (Psfm) pour l onglet des mesures des prelevements.
50   */
51  public class OperationMeasurementsUngroupedTableUIHandler extends AbstractDaliTableUIHandler<OperationMeasurementsUngroupedRowModel, OperationMeasurementsUngroupedTableUIModel, OperationMeasurementsUngroupedTableUI> {
52  
53      private static final int ROW_COUNT = 5;
54  
55      // editor for analyst column
56      private ExtendedComboBoxCellEditor<DepartmentDTO> departmentCellEditor;
57  
58      /**
59       * <p>Constructor for OperationMeasurementsUngroupedTableUIHandler.</p>
60       */
61      public OperationMeasurementsUngroupedTableUIHandler() {
62          super(OperationMeasurementsUngroupedRowModel.PROPERTY_PMFMS);
63      }
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      public OperationMeasurementsUngroupedTableModel getTableModel() {
70          return (OperationMeasurementsUngroupedTableModel) getTable().getModel();
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      @Override
77      public void beforeInit(final OperationMeasurementsUngroupedTableUI ui) {
78          super.beforeInit(ui);
79          // create model and register to the JAXX context
80          final OperationMeasurementsUngroupedTableUIModel model = new OperationMeasurementsUngroupedTableUIModel();
81          ui.setContextValue(model);
82      }
83  
84      /**
85       * {@inheritDoc}
86       */
87      @Override
88      public void afterInit(final OperationMeasurementsUngroupedTableUI ui) {
89  
90          // Initialiser l UI
91          initUI(ui);
92          createDepartmentCellEditor();
93          updateDepartmentCellEditor(false);
94  
95          initTable();
96          SwingUtil.setLayerUI(ui.getTableauHautScrollPane(), ui.getTableBlockLayer());
97  
98          // Initialiser listeners
99          initListeners();
100 
101         getTable().setVisibleRowCount(ROW_COUNT);
102     }
103 
104     private void createDepartmentCellEditor() {
105 
106         departmentCellEditor = newExtendedComboBoxCellEditor(null, DepartmentDTO.class, false);
107 
108         departmentCellEditor.setAction("unfilter", "dali.common.unfilter", e -> {
109             if (!askBefore(t("dali.common.unfilter"), t("dali.common.unfilter.confirmation"))) {
110                 return;
111             }
112             // unfilter location
113             updateDepartmentCellEditor(true);
114         });
115 
116     }
117 
118     private void updateDepartmentCellEditor(boolean forceNoFilter) {
119 
120         departmentCellEditor.getCombo().setActionEnabled(!forceNoFilter
121             && getContext().getDataContext().isContextFiltered(FilterTypeValues.DEPARTMENT));
122 
123         departmentCellEditor.getCombo().setData(getContext().getObservationService().getAvailableDepartments(forceNoFilter));
124     }
125 
126     /**
127      * Initialiser les listeners
128      */
129     private void initListeners() {
130 
131         getModel().addPropertyChangeListener(OperationMeasurementsUngroupedTableUIModel.PROPERTY_SURVEY, evt -> loadSamplingOperations());
132         getModel().addPropertyChangeListener(OperationMeasurementsUngroupedTableUIModel.PROPERTY_SAMPLING_FILTER, evt -> filterSamplingOperations());
133 
134     }
135 
136     /**
137      * Load prelevements.
138      */
139     private void loadSamplingOperations() {
140 
141         SwingUtilities.invokeLater(() -> {
142 
143             // Uninstall save state listener
144             uninstallSaveTableStateListener();
145 
146             addPmfmColumns(
147                 getModel().getPmfms(),
148                 SamplingOperationDTO.PROPERTY_PMFMS,
149                 DecoratorService.NAME_WITH_UNIT); // insert at the end
150 
151             boolean notEmpty = CollectionUtils.isNotEmpty(getModel().getPmfms());
152 
153             // tell the table model is editable or not
154             getTableModel().setReadOnly(!getModel().getSurvey().isEditable());
155 
156             getModel().setBeans(getModel().getSamplingOperations());
157             if (notEmpty) {
158                 for (OperationMeasurementsUngroupedRowModel row : getModel().getRows()) {
159                     // set analyst from first non null measurement
160                     Optional<MeasurementDTO> measurementFound = row.getMeasurements().stream().filter(measurement -> measurement.getAnalyst() != null).findFirst();
161                     if (measurementFound.isPresent()) {
162                         row.setAnalyst(measurementFound.get().getAnalyst());
163                     } else {
164                         row.setAnalyst(getContext().getProgramStrategyService().getAnalysisDepartmentOfAppliedStrategyBySurvey(getModel().getSurvey()));
165                     }
166                 }
167             }
168             recomputeRowsValidState();
169 
170             filterSamplingOperations();
171 
172             // restore table from swing session
173             restoreTableState();
174 
175             // hide analyst if no pmfm
176 //            forceColumnVisibleAtLastPosition(OperationMeasurementsUngroupedTableModel.ANALYST, notEmpty);
177             // Don't force position (Mantis #49939)
178             forceColumnVisible(OperationMeasurementsUngroupedTableModel.ANALYST, notEmpty);
179 
180             // set columns with errors visible (Mantis #40752)
181             ensureColumnsWithErrorAreVisible(getModel().getRows());
182 
183             // Install save state listener
184             SwingUtilities.invokeLater(this::installSaveTableStateListener);
185 //            installSaveTableStateListener();
186         });
187     }
188 
189     private void filterSamplingOperations() {
190 
191         if (getModel().getSamplingFilter() == null) {
192             getTable().setRowFilter(null);
193         } else {
194             // add filter
195             getTable().setRowFilter(new RowFilter<OperationMeasurementsUngroupedTableModel, Integer>() {
196                 @Override
197                 public boolean include(Entry<? extends OperationMeasurementsUngroupedTableModel, ? extends Integer> entry) {
198                     return getModel().getSamplingFilter() == null
199                         || getModel().getSamplingFilter().getName().equals(entry.getValue(getTable().getColumnExt(OperationMeasurementsUngroupedTableModel.NAME).getModelIndex()));
200                 }
201             });
202         }
203     }
204 
205     /**
206      * {@inheritDoc}
207      */
208     @Override
209     protected void onRowModified(int rowIndex, OperationMeasurementsUngroupedRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
210 
211         // no need to tell the table is modified if no pmfms (measurement) changes
212         if (OperationMeasurementsUngroupedRowModel.PROPERTY_PMFMS.equals(propertyName) && oldValue == newValue) {
213             return;
214         }
215 
216         super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
217 
218         row.setDirty(true);
219     }
220 
221     public void save() {
222 
223         Map<Integer, OperationMeasurementsUngroupedRowModel> rowById = new HashMap<>();
224         getModel().getRows().forEach(row -> rowById.put(row.getId(), row));
225 
226         getModel().getSamplingOperations().forEach(samplingOperation -> {
227             OperationMeasurementsUngroupedRowModel row = rowById.get(samplingOperation.getId());
228             if (row == null)
229                 throw new DaliTechnicalException("Unable to find the row for sampling operation id=" + samplingOperation.getId());
230 
231             // update all measurements
232             row.getMeasurements().forEach(measurement -> measurement.setAnalyst(row.getAnalyst()));
233 
234             // affect measurements
235             samplingOperation.setMeasurements(row.getMeasurements());
236         });
237 
238     }
239 
240     /**
241      * {@inheritDoc}
242      */
243     @Override
244     protected boolean isRowValid(OperationMeasurementsUngroupedRowModel row) {
245         return super.isRowValid(row) && isMeasurementRowValid(row);
246     }
247 
248     private boolean isMeasurementRowValid(OperationMeasurementsUngroupedRowModel row) {
249 
250         if (row.getAnalyst() == null && row.getMeasurements().stream().anyMatch(measurement -> !DaliBeans.isMeasurementEmpty(measurement))) {
251             DaliBeans.addError(row,
252                 t("dali.validator.error.analyst.required"),
253                 OperationMeasurementsUngroupedRowModel.PROPERTY_ANALYST);
254             return false;
255         }
256         return true;
257     }
258 
259     /**
260      * Initialisation du tableau.
261      */
262     private void initTable() {
263 
264         // La table des prelevements
265         final SwingTable table = getTable();
266 
267         // Colonne mnemonique
268         final TableColumnExt colName = addFixedColumn(OperationMeasurementsUngroupedTableModel.NAME);
269         colName.setSortable(true);
270         colName.setEditable(false);
271         colName.setMinWidth(100);
272 
273         // Add analyst column (Mantis #42617)
274         TableColumnExt analystColumn = addColumn(
275             departmentCellEditor,
276             newTableCellRender(OperationMeasurementsUngroupedTableModel.ANALYST),
277             OperationMeasurementsUngroupedTableModel.ANALYST
278         );
279         analystColumn.setMinWidth(100);
280 
281         // Modele de la table
282         final OperationMeasurementsUngroupedTableModel tableModel = new OperationMeasurementsUngroupedTableModel(getTable().getColumnModel());
283         tableModel.setNoneEditableCols();
284         table.setModel(tableModel);
285 
286         // Initialisation de la table
287         initTable(table, true);
288 
289         // border
290         addEditionPanelBorder();
291     }
292 
293     /**
294      * {@inheritDoc}
295      */
296     @Override
297     public SwingTable getTable() {
298         return ui.getOperationUngroupedMeasurementTable();
299     }
300 }