1 package fr.ifremer.dali.ui.swing.content.manage.program.strategies;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import com.google.common.collect.ArrayListMultimap;
27 import com.google.common.collect.Maps;
28 import com.google.common.collect.Multimap;
29 import fr.ifremer.dali.dto.DaliBeans;
30 import fr.ifremer.dali.dto.configuration.programStrategy.AppliedStrategyDTO;
31 import fr.ifremer.dali.dto.configuration.programStrategy.PmfmStrategyDTO;
32 import fr.ifremer.dali.service.DaliTechnicalException;
33 import fr.ifremer.dali.ui.swing.content.manage.program.ProgramsUI;
34 import fr.ifremer.dali.ui.swing.content.manage.program.programs.ProgramsTableRowModel;
35 import fr.ifremer.dali.ui.swing.util.AbstractDaliBeanUIModel;
36 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableModel;
37 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIHandler;
38 import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
39 import jaxx.runtime.SwingUtil;
40 import org.jdesktop.swingx.table.TableColumnExt;
41
42 import javax.swing.SortOrder;
43 import javax.swing.SwingWorker;
44 import java.util.Collection;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.concurrent.ExecutionException;
48 import java.util.stream.Collectors;
49
50 import static org.nuiton.i18n.I18n.t;
51
52
53
54
55 public class StrategiesTableUIHandler extends AbstractDaliTableUIHandler<StrategiesTableRowModel, StrategiesTableUIModel, StrategiesTableUI> {
56
57 private PmfmAndAppliedStrategyLoader pmfmAndAppliedStrategyLoader;
58
59
60
61
62 public StrategiesTableUIHandler() {
63 super(StrategiesTableRowModel.PROPERTY_NAME,
64 StrategiesTableRowModel.PROPERTY_COMMENT);
65 }
66
67
68
69
70 @Override
71 public AbstractDaliTableModel<StrategiesTableRowModel> getTableModel() {
72 return (StrategiesTableModel) getTable().getModel();
73 }
74
75
76
77
78 @Override
79 public SwingTable getTable() {
80 return getUI().getStrategiesTable();
81 }
82
83
84
85
86 @Override
87 public void beforeInit(final StrategiesTableUI ui) {
88 super.beforeInit(ui);
89
90
91 final StrategiesTableUIModel model = new StrategiesTableUIModel();
92 ui.setContextValue(model);
93 }
94
95
96
97
98 @Override
99 public void afterInit(StrategiesTableUI ui) {
100
101
102 initUI(ui);
103
104
105 initTable();
106 SwingUtil.setLayerUI(ui.getTableScrollPane(), ui.getTableBlockLayer());
107
108
109 initListeners();
110
111 }
112
113
114
115
116 @Override
117 protected boolean isRowValid(final StrategiesTableRowModel row) {
118 row.getErrors().clear();
119 return (!row.isEditable() || super.isRowValid(row)) && isStrategyValid(row);
120 }
121
122 private boolean isStrategyValid(StrategiesTableRowModel row) {
123
124
125 if (getModel().getRowCount() >= 2) {
126
127 for (StrategiesTableRowModel otherRow : getModel().getRows()) {
128 if (row == otherRow) continue;
129 if (row.getName().equals(otherRow.getName())) {
130
131 DaliBeans.addError(row, t("dali.program.strategy.name.duplicates"), StrategiesTableRowModel.PROPERTY_NAME);
132 }
133 }
134 }
135
136 if (row.isAppliedStrategiesLoaded()) {
137
138 Map<Integer, AppliedStrategyDTO> validAppliedStrategies = Maps.newHashMap();
139
140
141 boolean isStrategyApplied = false;
142 if (!row.isAppliedStrategiesEmpty()) {
143 for (AppliedStrategyDTO appliedStrategy : row.getAppliedStrategies()) {
144 if (appliedStrategy.getStartDate() != null && appliedStrategy.getEndDate() != null) {
145 isStrategyApplied = true;
146 validAppliedStrategies.put(appliedStrategy.getId(), appliedStrategy);
147 }
148 }
149 }
150 if (!isStrategyApplied) {
151 DaliBeans.addError(row, t("dali.programs.validation.error.noAppliedPeriod"), StrategiesTableRowModel.PROPERTY_NAME);
152 } else {
153
154
155 Multimap<Integer, AppliedStrategyDTO> otherAppliedStrategiesByLocationId = ArrayListMultimap.create();
156 for (StrategiesTableRowModel otherRow : getModel().getRows()) {
157
158 if (otherRow == row) continue;
159
160
161 for (AppliedStrategyDTO appliedStrategy : otherRow.getAppliedStrategies()) {
162 if (validAppliedStrategies.containsKey(appliedStrategy.getId()) && appliedStrategy.getStartDate() != null && appliedStrategy.getEndDate() != null) {
163 otherAppliedStrategiesByLocationId.put(appliedStrategy.getId(), appliedStrategy);
164 }
165 }
166 }
167
168
169 for (Integer appliedStrategyId : validAppliedStrategies.keySet()) {
170 boolean overlappingFound = false;
171 AppliedStrategyDTO appliedStrategy = validAppliedStrategies.get(appliedStrategyId);
172 Collection<AppliedStrategyDTO> otherAppliedStrategies = otherAppliedStrategiesByLocationId.get(appliedStrategyId);
173 for (AppliedStrategyDTO otherAppliedStrategy : otherAppliedStrategies) {
174
175 if (appliedStrategy.getStartDate().compareTo(otherAppliedStrategy.getEndDate()) <= 0
176 && otherAppliedStrategy.getStartDate().compareTo(appliedStrategy.getEndDate()) <= 0) {
177
178
179 overlappingFound = true;
180 break;
181 }
182
183 }
184
185 if (overlappingFound) {
186 DaliBeans.addError(row, t("dali.programs.validation.error.overlappingPeriods"), StrategiesTableRowModel.PROPERTY_NAME);
187 break;
188 }
189 }
190
191
192 for (AppliedStrategyDTO appliedStrategy : row.getAppliedStrategies()) {
193 if (!appliedStrategy.isErrorsEmpty()) {
194 DaliBeans.addError(row, t("dali.programs.validation.error.appliedStrategies"), StrategiesTableRowModel.PROPERTY_NAME);
195 }
196 }
197 }
198 }
199
200
201 if (row.isPmfmStrategiesLoaded()) {
202
203 for (PmfmStrategyDTO pmfmStrategy : row.getPmfmStrategies()) {
204 if (!pmfmStrategy.isSurvey() && !pmfmStrategy.isSampling()) {
205 DaliBeans.addError(row, t("dali.program.tables.error"), StrategiesTableRowModel.PROPERTY_NAME);
206 }
207
208 }
209 }
210
211 return row.isErrorsEmpty();
212 }
213
214
215
216
217 @Override
218 protected void onRowModified(int rowIndex, StrategiesTableRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
219 saveToProgram();
220 super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
221 }
222
223
224
225
226 @Override
227 protected String[] getRowPropertiesToIgnore() {
228 return new String[]{StrategiesTableRowModel.PROPERTY_APPLIED_STRATEGIES,
229 StrategiesTableRowModel.PROPERTY_APPLIED_STRATEGIES_LOADED,
230 StrategiesTableRowModel.PROPERTY_PMFM_STRATEGIES,
231 StrategiesTableRowModel.PROPERTY_PMFM_STRATEGIES_LOADED,
232 StrategiesTableRowModel.PROPERTY_ERRORS};
233 }
234
235
236
237
238
239
240 public void load(ProgramsTableRowModel selectedProgram) {
241
242 getModel().setProgramStatus(selectedProgram.getStatus());
243 getModel().setBeans(selectedProgram.getStrategies());
244 getModel().setEditable(selectedProgram.isEditable());
245 getModel().setLoading(false);
246 getModel().setLoaded(true);
247 recomputeRowsValidState();
248 }
249
250 private ProgramsUI getProgramsUI() {
251 return getUI().getParentContainer(ProgramsUI.class);
252 }
253
254
255
256
257 private void initListeners() {
258
259
260 getModel().addPropertyChangeListener(StrategiesTableUIModel.PROPERTY_SINGLE_ROW_SELECTED, evt -> {
261
262
263 final ProgramsTableRowModel program = getModel().getParentModel().getProgramsUIModel().getSingleSelectedRow();
264 final StrategiesTableRowModel strategy = getModel().getSingleSelectedRow();
265
266
267 if (program != null && strategy != null) {
268
269
270 if (pmfmAndAppliedStrategyLoader != null && !pmfmAndAppliedStrategyLoader.isDone()) {
271 pmfmAndAppliedStrategyLoader.cancel(true);
272 }
273 getModel().getParentModel().getLocationsUIModel().setLoading(true);
274 getModel().getParentModel().getPmfmsUIModel().setLoading(true);
275 pmfmAndAppliedStrategyLoader = new PmfmAndAppliedStrategyLoader(program, strategy);
276 pmfmAndAppliedStrategyLoader.execute();
277
278 } else {
279
280
281 getModel().getParentModel().getPmfmsUIModel().clear();
282 }
283 });
284
285 getModel().addPropertyChangeListener(StrategiesTableUIModel.EVENT_SAVE_APPLIED_STRATEGIES, evt -> {
286 if (getModel().getSingleSelectedRow() != null) {
287 getModel().getSingleSelectedRow().setAppliedStrategies(getModel().getParentModel().getLocationsUIModel().getBeans());
288 getModel().getSingleSelectedRow().setAppliedStrategiesLoaded(true);
289 }
290 });
291 getModel().addPropertyChangeListener(StrategiesTableUIModel.EVENT_SAVE_PMFM_STRATEGIES, evt -> {
292 if (getModel().getSingleSelectedRow() != null) {
293 getModel().getSingleSelectedRow().setPmfmStrategies(getModel().getParentModel().getPmfmsUIModel().getBeans());
294 getModel().getSingleSelectedRow().setPmfmStrategiesLoaded(true);
295
296
297 getModel().getParentModel().getLocationsUIModel().fireValidateRows();
298 }
299 });
300
301 getModel().addPropertyChangeListener(StrategiesTableUIModel.EVENT_VALIDATE_ROWS, evt -> recomputeRowsValidState());
302
303 getModel().addPropertyChangeListener(StrategiesTableUIModel.EVENT_REMOVE_LOCATIONS, evt -> removeLocations((List<Integer>) evt.getNewValue()));
304
305 }
306
307
308
309
310 private void initTable() {
311
312 final SwingTable table = getTable();
313
314
315 final TableColumnExt colonneLibelle = addColumn(
316 StrategiesTableModel.NAME);
317 colonneLibelle.setSortable(true);
318
319
320 TableColumnExt colonneDescription = addCommentColumn(StrategiesTableModel.COMMENT);
321
322 final StrategiesTableModel tableModel = new StrategiesTableModel(getTable().getColumnModel());
323 table.setModel(tableModel);
324
325
326 colonneLibelle.setHideable(false);
327 colonneDescription.setHideable(false);
328
329
330 initTable(table);
331
332
333 table.setVisibleRowCount(4);
334
335
336 table.setSortOrder(StrategiesTableModel.NAME, SortOrder.ASCENDING);
337 }
338
339
340
341
342 private void saveToProgram() {
343
344 if (getModel().isLoading()) return;
345
346
347
348 getModel().getParentModel().getProgramsUIModel().fireSaveStrategies();
349
350
351 recomputeRowsValidState();
352 getModel().firePropertyChanged(AbstractDaliBeanUIModel.PROPERTY_MODIFY, null, true);
353
354 }
355
356
357
358
359 @Override
360 protected void onRowsAdded(List<StrategiesTableRowModel> addedRows) {
361 super.onRowsAdded(addedRows);
362
363 if (addedRows.size() == 1) {
364 StrategiesTableRowModel row = addedRows.get(0);
365
366 getModel().setModify(true);
367
368 setFocusOnCell(row);
369
370 saveToProgram();
371 }
372 }
373
374
375
376
377 void removeStrategies() {
378
379 if (getModel().getSelectedRows().isEmpty())
380 return;
381
382 if (!checkExistingSurveysInsideRemovedStrategy()) {
383
384 getContext().getDialogHelper().showErrorDialog(
385 t("dali.program.location.period.surveyInsidePeriod"),
386 t("dali.program.strategy.delete.titre")
387 );
388
389 return;
390 }
391
392
393 if (askBeforeDelete(t("dali.program.strategy.delete.titre"), t("dali.program.strategy.delete.message"))) {
394
395
396 getModel().deleteSelectedRows();
397
398
399 getModel().getParentModel().getPmfmsUIModel().clear();
400
401 saveToProgram();
402
403
404 getModel().getParentModel().getProgramsUIModel().fireReselect();
405
406 }
407
408 }
409
410 void removeLocations(List<Integer> locationIds) {
411 getModel().getRows().stream().filter(strategy -> !strategy.isAppliedStrategiesEmpty())
412 .forEach(strategy -> strategy.getAppliedStrategies().removeIf(appliedStrategy -> locationIds.contains(appliedStrategy.getId())));
413 }
414
415
416
417
418
419
420
421 private boolean checkExistingSurveysInsideRemovedStrategy() {
422
423 getModel().setLoading(true);
424 try {
425
426 List<AppliedStrategyDTO> appliedStrategies = getModel().getSelectedBeans().stream()
427 .filter(strategyDTO -> strategyDTO.getId() != null)
428 .flatMap(strategyDTO -> strategyDTO.getAppliedStrategies().stream())
429 .filter(appliedStrategyDTO -> appliedStrategyDTO.getStartDate() != null && appliedStrategyDTO.getEndDate() != null)
430 .collect(Collectors.toList());
431
432 if (appliedStrategies.isEmpty()) return true;
433
434 String programCode = getModel().getParentModel().getProgramsUIModel().getSingleSelectedRow().getCode();
435
436 return appliedStrategies.stream().noneMatch(appliedStrategy ->
437 getContext().getObservationService().countSurveysWithProgramLocationAndInsideDates(
438 programCode,
439 appliedStrategy.getAppliedStrategyId(),
440 appliedStrategy.getId(),
441 appliedStrategy.getStartDate(),
442 appliedStrategy.getEndDate()
443 ) > 0
444 );
445
446 } finally {
447 getModel().setLoading(false);
448 }
449 }
450
451 private class PmfmAndAppliedStrategyLoader extends SwingWorker<Object, Object> {
452
453 private final ProgramsUI adminProgrammeUI = getProgramsUI();
454 private final ProgramsTableRowModel selectedProgram;
455 private final StrategiesTableRowModel selectedStrategy;
456
457 PmfmAndAppliedStrategyLoader(ProgramsTableRowModel selectedProgram, StrategiesTableRowModel selectedStrategy) {
458 this.selectedProgram = selectedProgram;
459 this.selectedStrategy = selectedStrategy;
460 }
461
462 @Override
463 protected Object doInBackground() {
464
465
466 getContext().getProgramStrategyService().loadAppliedPeriodsAndPmfmStrategies(selectedProgram, selectedStrategy);
467
468 return null;
469 }
470
471 @Override
472 protected void done() {
473 if (isCancelled()) {
474 return;
475 }
476 try {
477 get();
478 } catch (InterruptedException | ExecutionException e) {
479 throw new DaliTechnicalException(e.getMessage(), e);
480 }
481
482
483 adminProgrammeUI.getLocationsTableUI().getHandler().loadAppliedStrategiesFromStrategy(selectedProgram, selectedStrategy);
484
485
486 adminProgrammeUI.getPmfmsTableUI().getHandler().load(selectedProgram, selectedStrategy);
487
488 }
489 }
490
491 }