1 package fr.ifremer.dali.ui.swing.content.manage.program.locations;
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.Lists;
27 import com.google.common.collect.Sets;
28 import fr.ifremer.dali.dto.DaliBeans;
29 import fr.ifremer.dali.dto.configuration.programStrategy.AppliedStrategyDTO;
30 import fr.ifremer.dali.dto.configuration.programStrategy.ProgStratDTO;
31 import fr.ifremer.dali.dto.enums.FilterTypeValues;
32 import fr.ifremer.dali.dto.referential.LocationDTO;
33 import fr.ifremer.dali.service.StatusFilter;
34 import fr.ifremer.dali.ui.swing.content.manage.filter.select.SelectFilterUI;
35 import fr.ifremer.dali.ui.swing.content.manage.program.locations.updatePeriod.UpdatePeriodUI;
36 import fr.ifremer.dali.ui.swing.content.manage.program.programs.ProgramsTableRowModel;
37 import fr.ifremer.dali.ui.swing.content.manage.program.strategies.StrategiesTableRowModel;
38 import fr.ifremer.dali.ui.swing.util.AbstractDaliBeanUIModel;
39 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableModel;
40 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIHandler;
41 import fr.ifremer.quadrige3.core.dao.technical.Assert;
42 import fr.ifremer.quadrige3.ui.swing.ApplicationUIUtil;
43 import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
44 import fr.ifremer.quadrige3.ui.swing.table.SwingTableColumnModel;
45 import jaxx.runtime.SwingUtil;
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48 import org.jdesktop.swingx.table.TableColumnExt;
49
50 import javax.swing.JOptionPane;
51 import javax.swing.SortOrder;
52 import java.awt.Dimension;
53 import java.util.List;
54 import java.util.Set;
55 import java.util.stream.Collectors;
56
57 import static org.nuiton.i18n.I18n.t;
58
59
60
61
62 public class LocationsTableUIHandler extends AbstractDaliTableUIHandler<LocationsTableRowModel, LocationsTableUIModel, LocationsTableUI> {
63
64
65
66
67 private static final Log LOG = LogFactory.getLog(LocationsTableUIHandler.class);
68
69
70
71
72 @Override
73 public AbstractDaliTableModel<LocationsTableRowModel> getTableModel() {
74 return (LocationsTableModel) getTable().getModel();
75 }
76
77
78
79
80 @Override
81 public SwingTable getTable() {
82 return getUI().getLocationsTable();
83 }
84
85
86
87
88 @Override
89 public void beforeInit(final LocationsTableUI ui) {
90 super.beforeInit(ui);
91
92
93 final LocationsTableUIModel model = new LocationsTableUIModel();
94 ui.setContextValue(model);
95 }
96
97
98
99
100 @Override
101 public void afterInit(LocationsTableUI ui) {
102
103 initUI(ui);
104
105
106 getModel().setPeriodsEnabled(false);
107 initTable();
108 SwingUtil.setLayerUI(ui.getTableScrollPane(), ui.getTableBlockLayer());
109
110 initListeners();
111
112 initActionComboBox(getUI().getEditCombobox());
113
114 }
115
116
117
118
119
120
121 public void loadMonitoringLocationsFromProgram(ProgramsTableRowModel selectedProgram) {
122
123
124 if (getModel().isPeriodsEnabled()) {
125 getModel().setPeriodsEnabled(false);
126 initTable();
127 }
128
129 getModel().setSelectedProgram(selectedProgram);
130 getModel().setSelectedStrategy(null);
131
132
133 load();
134 }
135
136
137
138
139
140
141
142 public void loadAppliedStrategiesFromStrategy(ProgramsTableRowModel selectedProgram, StrategiesTableRowModel selectedStrategy) {
143
144
145 if (!getModel().isPeriodsEnabled()) {
146 getModel().setPeriodsEnabled(true);
147 initTable();
148 }
149
150 getModel().setSelectedProgram(selectedProgram);
151 getModel().setSelectedStrategy(selectedStrategy);
152
153
154 load();
155 }
156
157 private void load() {
158 try {
159 if (getModel().getSelectedProgram() == null) {
160 return;
161 }
162
163 getModel().setEditable(getModel().getSelectedProgram().isEditable());
164
165 if (getModel().getSelectedStrategy() == null) {
166
167
168 getModel().setBeans(DaliBeans.locationsToAppliedStrategyDTOs(getModel().getSelectedProgram().getLocations()));
169
170 } else {
171
172 if (getUI().getStrategyFilterCheckbox().isSelected()) {
173
174
175 getModel().setBeans(DaliBeans.filterNotEmptyAppliedPeriod(getModel().getSelectedStrategy().getAppliedStrategies()));
176
177 } else {
178
179
180 getModel().setBeans(getModel().getSelectedStrategy().getAppliedStrategies());
181 }
182 }
183
184 if (getContext().getSelectedLocationId() != null) {
185 selectRowById(getContext().getSelectedLocationId());
186 }
187
188 recomputeRowsValidState();
189 getModel().setLoaded(true);
190
191 } finally {
192 getModel().setLoading(false);
193 }
194 }
195
196
197
198
199 void addLocations() {
200
201 ProgramsTableRowModel program = getModel().getSelectedProgram();
202 StrategiesTableRowModel strategy = getModel().getSelectedStrategy();
203
204 Assert.notNull(program);
205
206 SelectFilterUI dialog = new SelectFilterUI(getContext(), FilterTypeValues.LOCATION.getFilterTypeId());
207 dialog.setTitle(t("dali.program.location.new.dialog.title"));
208 List<LocationDTO> locations = program.getLocations().stream()
209 .sorted(getDecorator(LocationDTO.class, null).getCurrentComparator())
210
211 .peek(location -> location.setReadOnly(true))
212 .collect(Collectors.toList());
213 dialog.getModel().setSelectedElements(locations);
214
215
216
217
218
219
220
221
222 openDialog(dialog, new Dimension(1024, 720));
223
224 if (dialog.getModel().isValid()) {
225
226
227 List<LocationDTO> newLocations = dialog.getModel().getSelectedElements().stream()
228 .map(newLocation -> ((LocationDTO) newLocation))
229 .filter(newLocation -> program.getLocations().stream().noneMatch(location -> location.equals(newLocation)))
230 .collect(Collectors.toList());
231
232 if (!newLocations.isEmpty()) {
233
234
235 newLocations.forEach(program::addLocations);
236
237
238 if (strategy != null) {
239 newLocations.stream()
240
241 .filter(newLocation -> strategy.getAppliedStrategies().stream().noneMatch(appliedStrategy -> appliedStrategy.getId().equals(newLocation.getId())))
242 .forEach(newLocation -> strategy.addAppliedStrategies(DaliBeans.locationToAppliedStrategyDTO(newLocation)));
243 }
244
245
246 List<AppliedStrategyDTO> beans = strategy != null ? strategy.getAppliedStrategies() : DaliBeans.locationsToAppliedStrategyDTOs(program.getLocations());
247 getModel().setBeans(beans);
248
249 saveToStrategy();
250
251
252 unselectAllRows();
253 List<Integer> newLocIds = DaliBeans.collectIds(newLocations);
254 selectRows(getModel().getRows().stream().filter(row -> newLocIds.contains(row.getId())).collect(Collectors.toList()));
255
256 }
257 }
258 }
259
260
261
262
263 private void initListeners() {
264
265
266 getModel().addPropertyChangeListener(LocationsTableUIModel.PROPERTY_SINGLE_ROW_SELECTED, evt -> {
267
268
269 getContext().setSelectedLocationId(getModel().getSingleSelectedRow() == null ? null : getModel().getSingleSelectedRow().getId());
270
271 });
272
273
274 getUI().getStrategyFilterCheckbox().addItemListener(e -> {
275
276
277 load();
278 });
279
280 getModel().addPropertyChangeListener(LocationsTableUIModel.EVENT_VALIDATE_ROWS, evt -> recomputeRowsValidState());
281
282 }
283
284
285
286
287 private void initTable() {
288
289
290 getModel().setBeans(null);
291
292
293 getTable().setColumnModel(new SwingTableColumnModel());
294
295
296 final TableColumnExt colCode = addColumn(LocationsTableModel.CODE);
297 colCode.setSortable(true);
298 colCode.setCellRenderer(newNumberCellRenderer(0));
299
300
301 final TableColumnExt colName = addColumn(
302 LocationsTableModel.LABEL);
303 colName.setSortable(true);
304
305
306 final TableColumnExt colComment = addColumn(
307 LocationsTableModel.NAME);
308 colComment.setSortable(true);
309
310
311 if (getModel().isPeriodsEnabled()) {
312
313
314 final TableColumnExt colStartDate = addLocalDatePickerColumnToModel(
315 LocationsTableModel.START_DATE, getConfig().getDateFormat());
316 colStartDate.setSortable(true);
317 colStartDate.setHideable(false);
318
319
320 final TableColumnExt colEndDate = addLocalDatePickerColumnToModel(
321 LocationsTableModel.END_DATE, getConfig().getDateFormat());
322 colEndDate.setSortable(true);
323 colEndDate.setHideable(false);
324
325
326 final TableColumnExt colSamplingDepartment = addFilterableComboDataColumnToModel(
327 LocationsTableModel.SAMPLING_DEPARTMENT,
328 getContext().getReferentialService().getDepartments(StatusFilter.ACTIVE),
329 false);
330 colSamplingDepartment.setSortable(true);
331 colSamplingDepartment.setHideable(false);
332
333
334 final TableColumnExt colAnalysisDepartment = addFilterableComboDataColumnToModel(
335 LocationsTableModel.ANALYSIS_DEPARTMENT,
336 getContext().getReferentialService().getDepartments(StatusFilter.ACTIVE),
337 false);
338 colAnalysisDepartment.setSortable(true);
339 colAnalysisDepartment.setHideable(false);
340 }
341
342 final LocationsTableModel tableModel = new LocationsTableModel(getTable().getColumnModel());
343 getTable().setModel(tableModel);
344
345 tableModel.setNoneEditableCols();
346
347 colCode.setHideable(false);
348 colName.setHideable(false);
349 colComment.setHideable(false);
350
351 colCode.setEditable(false);
352 colName.setEditable(false);
353 colComment.setEditable(false);
354
355 initTable(getTable());
356
357 getTable().setVisibleRowCount(4);
358
359 getTable().setSortOrder(LocationsTableModel.CODE, SortOrder.ASCENDING);
360
361 if (getModel().isPeriodsEnabled()) {
362 overrideTabKeyActions(getTable(), true);
363 }
364 }
365
366
367
368
369 @Override
370 protected String[] getRowPropertiesToIgnore() {
371 return new String[]{LocationsTableRowModel.PROPERTY_ERRORS};
372 }
373
374
375
376
377 @Override
378 protected boolean isRowValid(LocationsTableRowModel row) {
379 row.getErrors().clear();
380 return super.isRowValid(row) && isDatesValid(row) && isAnalystValid(row);
381 }
382
383 private boolean isAnalystValid(LocationsTableRowModel row) {
384
385
386 if (getModel().getSelectedStrategy() != null && getModel().getSelectedStrategy().isPmfmStrategiesEmpty() && row.getAnalysisDepartment() != null) {
387 DaliBeans.addError(row, t("dali.program.location.analysisDepartment.noPmfmStrategy"), LocationsTableRowModel.PROPERTY_ANALYSIS_DEPARTMENT);
388 return false;
389 }
390
391 return true;
392 }
393
394 private boolean isDatesValid(LocationsTableRowModel row) {
395
396
397 if (row.getStartDate() == null && row.getPreviousStartDate() != null
398 && row.getEndDate() == null && row.getPreviousEndDate() != null) {
399 checkExistingSurveysInsideStrategy(row);
400 }
401
402
403 if (row.getStartDate() == null && row.getEndDate() != null) {
404 DaliBeans.addError(row, t("dali.program.location.startDate.null"), LocationsTableRowModel.PROPERTY_START_DATE);
405
406 } else if (row.getStartDate() != null && row.getEndDate() == null) {
407 DaliBeans.addError(row, t("dali.program.location.endDate.null"), LocationsTableRowModel.PROPERTY_END_DATE);
408
409 } else if (row.getStartDate() != null && row.getEndDate() != null) {
410
411 if (row.getStartDate().isAfter(row.getEndDate())) {
412 DaliBeans.addError(row, t("dali.program.location.endDate.before"), LocationsTableRowModel.PROPERTY_END_DATE);
413 } else {
414
415
416 checkExistingSurveysOutsideStrategy(row);
417 }
418 }
419
420 return row.getErrors().isEmpty();
421 }
422
423 private void checkExistingSurveysInsideStrategy(LocationsTableRowModel row) {
424 if (row.getAppliedStrategyId() != null && row.getId() != null) {
425 long surveysCount = getContext().getObservationService().countSurveysWithProgramLocationAndInsideDates(
426 getModel().getSelectedProgram().getCode(),
427 row.getAppliedStrategyId(),
428 row.getId(),
429 row.getPreviousStartDate(),
430 row.getPreviousEndDate()
431 );
432 if (surveysCount > 0) {
433 DaliBeans.addError(row, t("dali.program.location.period.surveyInsidePeriod"),
434 LocationsTableRowModel.PROPERTY_START_DATE, LocationsTableRowModel.PROPERTY_END_DATE);
435 }
436 }
437 }
438
439 private void checkExistingSurveysOutsideStrategy(LocationsTableRowModel row) {
440 if (row.getAppliedStrategyId() != null && row.getId() != null) {
441 long surveysCount = getContext().getObservationService().countSurveysWithProgramLocationAndOutsideDates(
442 getModel().getSelectedProgram().getCode(),
443 row.getAppliedStrategyId(),
444 row.getId(),
445 row.getStartDate(),
446 row.getEndDate()
447 );
448 if (surveysCount > 0) {
449 DaliBeans.addError(row, t("dali.program.location.period.surveyOutsidePeriod"),
450 LocationsTableRowModel.PROPERTY_START_DATE, LocationsTableRowModel.PROPERTY_END_DATE);
451 }
452 }
453 }
454
455
456
457
458 @Override
459 protected void onRowModified(int rowIndex, LocationsTableRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
460
461
462 if (getModel().isPeriodsEnabled()) {
463 if (LocationsTableRowModel.PROPERTY_START_DATE.equals(propertyName) || LocationsTableRowModel.PROPERTY_END_DATE.equals(propertyName)) {
464 if (row.getStartDate() == null && row.getEndDate() == null) {
465 if (row.getSamplingDepartment() != null) row.setSamplingDepartment(null);
466 if (row.getAnalysisDepartment() != null) row.setAnalysisDepartment(null);
467 }
468 }
469 }
470
471 saveToStrategy();
472 super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
473 }
474
475
476
477
478 private void saveToStrategy() {
479
480 if (getModel().isLoading()) return;
481
482
483 getModel().getParentModel().getStrategiesUIModel().fireSaveAppliedStrategies();
484 getModel().getParentModel().getProgramsUIModel().fireSaveStrategies();
485
486
487 recomputeRowsValidState();
488 getModel().firePropertyChanged(AbstractDaliBeanUIModel.PROPERTY_MODIFY, null, true);
489 getModel().firePropertyChanged(AbstractDaliBeanUIModel.PROPERTY_VALID, null, getModel().getRowCount() > 0);
490
491 }
492
493
494
495
496 @Override
497 public void recomputeRowsValidState() {
498 super.recomputeRowsValidState();
499
500
501 getModel().getParentModel().getStrategiesUIModel().fireValidateRows();
502 }
503
504
505
506
507 void removeLocations() {
508
509 if (getModel().getSelectedRows().isEmpty()) {
510 LOG.warn("No location selected");
511 return;
512 }
513
514
515 ProgramsTableRowModel program = getModel().getSelectedProgram();
516 List<Integer> locationIds = Lists.newArrayList();
517 for (final AppliedStrategyDTO row : getModel().getSelectedRows()) {
518
519 locationIds.add(row.getId());
520 }
521
522
523 if (getModel().isPeriodsEnabled()) {
524
525
526 if (!askBeforeDelete(t("dali.program.location.delete.titre"), t("dali.program.location.delete.appliedStrategy.message"))) {
527 return;
528 }
529
530 } else {
531
532
533 long surveysCount = getContext().getObservationService().countSurveysWithProgramAndLocations(program.getCode(), locationIds);
534 if (surveysCount > 0) {
535 getContext().getDialogHelper().showErrorDialog(
536 surveysCount == 1
537 ? t("dali.program.location.delete.usedInData")
538 : t("dali.program.location.delete.usedInData.many", surveysCount),
539 t("dali.program.location.delete.titre"));
540 return;
541 }
542
543
544 if (!askBeforeDelete(t("dali.program.location.delete.titre"), t("dali.program.location.delete.location.message"))) {
545 return;
546 }
547
548
549 Set<ProgStratDTO> usedStrategies = Sets.newHashSet();
550 for (Integer locationId : locationIds) {
551 List<ProgStratDTO> appliedStrategies = getContext().getProgramStrategyService().getStrategyUsageByProgramAndLocationId(program.getCode(), locationId);
552 usedStrategies.addAll(appliedStrategies);
553 }
554 if (!usedStrategies.isEmpty()) {
555 List<String> locationNames = Lists.newArrayList();
556 for (AppliedStrategyDTO row : getModel().getSelectedRows()) {
557 locationNames.add(decorate(row));
558 }
559 List<String> strategyNames = DaliBeans.collectProperties(usedStrategies, ProgStratDTO.PROPERTY_NAME);
560
561 String topPart = t("dali.program.location.delete.location.formStrategy");
562 String bottomMessage = t("dali.program.location.delete.location.fromStrategy.list", ApplicationUIUtil.formatHtmlList(strategyNames));
563
564 if (locationNames.size() > 8) {
565
566 if (getContext().getDialogHelper().showConfirmDialog(topPart, ApplicationUIUtil.getHtmlString(locationNames), bottomMessage, JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
567 return;
568 }
569
570 } else {
571
572 String message = String.format("%s\n%s\n%s", topPart, ApplicationUIUtil.formatHtmlList(locationNames), bottomMessage);
573 if (getContext().getDialogHelper().showConfirmDialog(message, JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION) {
574 return;
575 }
576 }
577
578 }
579 }
580
581
582 getModel().deleteSelectedRows();
583
584 if (!getModel().isPeriodsEnabled()) {
585
586 removeFromModels(locationIds);
587 }
588
589 saveToStrategy();
590
591 }
592
593
594
595
596
597
598 private void removeFromModels(List<Integer> locationIds) {
599
600
601 getModel().getParentModel().getProgramsUIModel().fireRemoveLocations(locationIds);
602
603
604 getModel().getParentModel().getStrategiesUIModel().fireRemoveLocations(locationIds);
605 }
606
607
608
609
610 void updatePeriod() {
611
612 final UpdatePeriodUI dialogue = new UpdatePeriodUI(getContext());
613 dialogue.getModel().setTableModel(getModel());
614
615 openDialog(dialogue, new Dimension(400, 220));
616
617 getModel().setModify(true);
618 saveToStrategy();
619 getTable().repaint();
620 }
621
622 }