1 package fr.ifremer.reefdb.ui.swing.content.manage.program.programs;
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 fr.ifremer.quadrige3.core.dao.referential.StatusCode;
27 import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
28 import fr.ifremer.reefdb.dao.technical.Daos;
29 import fr.ifremer.reefdb.dto.ReefDbBeans;
30 import fr.ifremer.reefdb.dto.configuration.programStrategy.ProgramDTO;
31 import fr.ifremer.reefdb.service.ReefDbTechnicalException;
32 import fr.ifremer.reefdb.ui.swing.content.manage.program.ProgramsUI;
33 import fr.ifremer.reefdb.ui.swing.content.manage.program.programs.departments.DepartmentsDialogUI;
34 import fr.ifremer.reefdb.ui.swing.content.manage.program.programs.users.UsersDialogUI;
35 import fr.ifremer.reefdb.ui.swing.util.ReefDbUIs;
36 import fr.ifremer.reefdb.ui.swing.util.table.AbstractReefDbTableModel;
37 import fr.ifremer.reefdb.ui.swing.util.table.AbstractReefDbTableUIHandler;
38 import fr.ifremer.reefdb.ui.swing.util.table.renderer.StatusRenderer;
39 import jaxx.runtime.validator.swing.SwingValidator;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.jdesktop.swingx.table.TableColumnExt;
44
45 import javax.swing.SortOrder;
46 import javax.swing.SwingUtilities;
47 import javax.swing.SwingWorker;
48 import java.awt.event.MouseAdapter;
49 import java.awt.event.MouseEvent;
50 import java.util.Collection;
51 import java.util.List;
52 import java.util.concurrent.ExecutionException;
53
54 import static org.nuiton.i18n.I18n.t;
55
56
57
58
59 public class ProgramsTableUIHandler extends AbstractReefDbTableUIHandler<ProgramsTableRowModel, ProgramsTableUIModel, ProgramsTableUI> {
60
61
62
63
64 private static final Log LOG = LogFactory.getLog(ProgramsTableUIHandler.class);
65
66 private StrategyAndLocationLoader strategyAndLocationLoader;
67 private boolean newRowSelected;
68
69
70
71
72 public ProgramsTableUIHandler() {
73 super(ProgramsTableRowModel.PROPERTY_NAME,
74 ProgramsTableRowModel.PROPERTY_COMMENT,
75 ProgramsTableRowModel.PROPERTY_CODE);
76 }
77
78
79
80
81 @Override
82 protected String[] getRowPropertiesToIgnore() {
83 return new String[]{ProgramsTableRowModel.PROPERTY_STRATEGIES, ProgramsTableRowModel.PROPERTY_STRATEGIES_LOADED,
84 ProgramsTableRowModel.PROPERTY_LOCATIONS, ProgramsTableRowModel.PROPERTY_LOCATIONS_LOADED,
85 ProgramsTableRowModel.PROPERTY_ERRORS};
86 }
87
88
89
90
91 @Override
92 public AbstractReefDbTableModel<ProgramsTableRowModel> getTableModel() {
93 return (ProgramsTableModel) getTable().getModel();
94 }
95
96
97
98
99 @Override
100 public SwingTable getTable() {
101 return getUI().getProgramsTable();
102 }
103
104
105
106
107 @Override
108 public void beforeInit(final ProgramsTableUI ui) {
109 super.beforeInit(ui);
110
111
112 final ProgramsTableUIModel model = new ProgramsTableUIModel();
113 ui.setContextValue(model);
114 }
115
116
117
118
119 @Override
120 public void afterInit(ProgramsTableUI ui) {
121
122
123 initUI(ui);
124
125
126 initTable();
127
128
129 initListeners();
130
131
132 initActionComboBox(getUI().getEditCombobox());
133
134
135 registerValidators(getValidator());
136 listenValidatorValid(getValidator(), getModel());
137
138 }
139
140
141
142
143 @Override
144 public boolean isRowValid(final ProgramsTableRowModel row) {
145 row.getErrors().clear();
146
147 return !row.isEditable() || (super.isRowValid(row) && isProgramValid(row));
148 }
149
150 private boolean isProgramValid(ProgramsTableRowModel row) {
151
152
153 if (!row.isLocal() && row.sizeManagerPersons() == 0) {
154 ReefDbBeans.addError(row, t("reefdb.programs.validation.error.noManager"), ProgramsTableRowModel.PROPERTY_CODE);
155 }
156
157
158 if (row.isLocationsLoaded() && row.isLocationsEmpty()) {
159 ReefDbBeans.addError(row, t("reefdb.programs.validation.error.noLocationOnProg"), ProgramsTableRowModel.PROPERTY_CODE);
160 }
161
162
163 if (!row.isStrategiesValid() || !row.isLocationsValid()) {
164 ReefDbBeans.addError(row, t("reefdb.program.tables.error"), ProgramsTableRowModel.PROPERTY_CODE);
165 }
166
167 return row.isErrorsEmpty();
168 }
169
170
171
172
173
174
175 public void loadPrograms(Collection<ProgramDTO> programs) {
176
177 getModel().setSingleSelectedRow(null);
178 getModel().setBeans(programs);
179
180 boolean isAdmin = getContext().isAuthenticatedAsAdmin();
181 getModel().getRows().forEach(program -> {
182
183 program.setEditable(getModel().isSaveEnabled());
184
185
186 program.setCurrentUserIsManager(
187 isAdmin && (
188 program.isLocal() ||
189 program.getManagerPersons().stream().anyMatch(personDTO -> personDTO.getId().equals(getContext().getDataContext().getRecorderPersonId()))
190 )
191 );
192
193 });
194
195 autoSelectRow();
196 }
197
198
199
200
201 public void clearTable() {
202
203 getModel().setBeans(null);
204
205 }
206
207
208
209
210 @Override
211 protected void onRowsAdded(List<ProgramsTableRowModel> addedRows) {
212 super.onRowsAdded(addedRows);
213
214
215 if (addedRows.size() == 1) {
216 final ProgramsTableRowModel row = addedRows.get(0);
217
218 if (checkCodeOnNewProgramRow(row)) {
219
220 row.setStatus(Daos.getStatus(StatusCode.LOCAL_ENABLE));
221 row.setCurrentUserIsManager(true);
222 row.setNewCode(true);
223 setFocusOnCell(row);
224
225 } else {
226
227
228 SwingUtilities.invokeLater(() -> {
229 getModel().deleteRow(row);
230 getModel().setSingleSelectedRow(null);
231 });
232 }
233 }
234
235 }
236
237
238
239
240 @Override
241 protected void onRowModified(int rowIndex, ProgramsTableRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
242 super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
243
244 row.setDirty(true);
245 }
246
247
248
249
250
251
252
253 private boolean checkCodeOnNewProgramRow(final ProgramsTableRowModel selectedRow) {
254
255
256 if (!getContext().isAuthenticatedAsAdmin()) {
257 getContext().getDialogHelper().showErrorDialog(t("reefdb.error.authenticate.accessDenied"));
258 return false;
259 }
260
261
262 boolean edit = StringUtils.isNotBlank(selectedRow.getCode());
263 String newCode = (String) getContext().getDialogHelper().showInputDialog(
264 getUI(),
265 t("reefdb.property.program.code"),
266 edit ? t("reefdb.program.editCode.title") : t("reefdb.program.setCode.title"),
267 null,
268 selectedRow.getCode());
269
270 if (StringUtils.isBlank(newCode)) {
271 return false;
272 }
273
274 newCode = newCode.trim();
275
276 for (ProgramsTableRowModel programCheck : getModel().getRows()) {
277 if (selectedRow == programCheck) continue;
278 if (newCode.equalsIgnoreCase(programCheck.getCode())) {
279
280 getContext().getDialogHelper().showErrorDialog(
281 t("reefdb.error.alreadyExists.referential", t("reefdb.property.program"), newCode,
282 ReefDbBeans.isLocalStatus(programCheck.getStatus()) ? t("reefdb.property.referential.local") : t("reefdb.property.referential.national")),
283 edit ? t("reefdb.program.editCode.title") : t("reefdb.program.setCode.title"));
284 return false;
285 }
286 }
287
288 ProgramDTO existingProgram = getContext().getProgramStrategyService().isProgramExists(newCode);
289 if (existingProgram != null) {
290
291 getContext().getDialogHelper().showErrorDialog(
292 t("reefdb.error.alreadyExists.referential", t("reefdb.property.program"), newCode,
293 ReefDbBeans.isLocalStatus(existingProgram.getStatus()) ? t("reefdb.property.referential.local") : t("reefdb.property.referential.national")),
294 edit ? t("reefdb.program.editCode.title") : t("reefdb.program.setCode.title"));
295 return false;
296 }
297
298 selectedRow.setCode(newCode);
299 return true;
300 }
301
302
303
304
305 public void editProgramCode() {
306 ProgramsTableRowModel row = getModel().getSingleSelectedRow();
307 if (row != null && row.isLocal() && row.isNewCode()) {
308 if (checkCodeOnNewProgramRow(row)) {
309 row.setDirty(true);
310 }
311 }
312 }
313
314
315
316
317 private void initListeners() {
318
319
320 getModel().addPropertyChangeListener(ProgramsTableUIModel.PROPERTY_SINGLE_ROW_SELECTED, evt -> {
321
322 final ProgramsUI adminProgrammeUI = getProgramsUI();
323 final ProgramsTableRowModel selectedProgram = getModel().getSingleSelectedRow();
324
325
326 if (selectedProgram != null && StringUtils.isNotBlank(selectedProgram.getCode())) {
327
328 newRowSelected = true;
329
330
331 getContext().setSelectedProgramCode(selectedProgram.getCode());
332
333 if (strategyAndLocationLoader != null && !strategyAndLocationLoader.isDone()) {
334 strategyAndLocationLoader.cancel(true);
335 }
336 adminProgrammeUI.getStrategiesTableUI().getModel().setLoading(true);
337 adminProgrammeUI.getLocationsTableUI().getModel().setLoading(true);
338 strategyAndLocationLoader = new StrategyAndLocationLoader(selectedProgram);
339 strategyAndLocationLoader.execute();
340
341 }
342 });
343
344 getModel().addPropertyChangeListener(ProgramsTableUIModel.PROPERTY_SELECTED_ROWS, evt -> {
345
346 if (getModel().getSelectedRows().size() == 1) {
347 ProgramsTableRowModel selected = getModel().getSelectedRows().iterator().next();
348 getUI().getEditCombobox().setEnabled(selected.getStatus() != null && !selected.isLocal());
349 } else {
350 getUI().getEditCombobox().setEnabled(false);
351 }
352 });
353
354
355 getTable().addMouseListener(new MouseAdapter() {
356 @Override
357 public void mouseClicked(MouseEvent e) {
358 if (!newRowSelected) {
359 getModel().firePropertyChanged(ProgramsTableUIModel.PROPERTY_SINGLE_ROW_SELECTED, null, null);
360 }
361 newRowSelected = false;
362 }
363
364 });
365
366
367 getModel().addPropertyChangeListener(ProgramsTableUIModel.PROPERTY_SAVE_ENABLED, evt -> {
368 getModel().getRows().forEach(programsTableRowModel -> programsTableRowModel.setEditable(getModel().isSaveEnabled()));
369 getUI().getProgramsTable().invalidate();
370 getUI().getProgramsTable().repaint();
371 autoSelectRow();
372 });
373
374 }
375
376
377
378
379
380
381 public void removeLocations(List<Integer> locationIds) {
382 ProgramsTableRowModel programModel = getModel().getSingleSelectedRow();
383 if (programModel != null) {
384 programModel.getLocations().removeIf(location -> locationIds.contains(location.getId()));
385 recomputeRowValidState(programModel);
386 }
387 }
388
389
390
391
392 public void showManagers() {
393
394 if (getModel().getSingleSelectedRow() == null) {
395 return;
396 }
397
398 UsersDialogUI usersDialogUI = new UsersDialogUI(getUI());
399 usersDialogUI.getModel().setManagerList(true);
400 usersDialogUI.getModel().setProgram(getModel().getSingleSelectedRow());
401
402 openDialog(usersDialogUI);
403
404 }
405
406
407
408
409 public void showRecorderPersons() {
410
411 if (getModel().getSingleSelectedRow() == null) {
412 return;
413 }
414
415 UsersDialogUI usersDialogUI = new UsersDialogUI(getUI());
416 usersDialogUI.getModel().setManagerList(false);
417 usersDialogUI.getModel().setProgram(getModel().getSingleSelectedRow());
418
419 openDialog(usersDialogUI);
420
421 }
422
423
424
425
426 public void showRecorderDepartments() {
427
428 if (getModel().getSingleSelectedRow() == null) {
429 return;
430 }
431
432 DepartmentsDialogUI usersDialogUI = new DepartmentsDialogUI(getUI());
433 usersDialogUI.getModel().setProgram(getModel().getSingleSelectedRow());
434
435 openDialog(usersDialogUI);
436
437 }
438
439
440
441
442 private void initTable() {
443
444
445 final TableColumnExt columnCode = addColumn(
446 ProgramsTableModel.CODE);
447 columnCode.setSortable(true);
448
449
450 final TableColumnExt columnLibelle = addColumn(
451 ProgramsTableModel.NAME);
452 columnLibelle.setSortable(true);
453
454
455 final TableColumnExt columnDescription = addCommentColumn(ProgramsTableModel.DESCRIPTION, ProgramsTableRowModel.PROPERTY_DESCRIPTION, true);
456 columnDescription.setSortable(false);
457
458
459 addCommentColumn(ProgramsTableModel.COMMENT);
460 TableColumnExt creationDateCol = addDatePickerColumnToModel(ProgramsTableModel.CREATION_DATE, getConfig().getDateTimeFormat(), false);
461 fixColumnWidth(creationDateCol, 120);
462 TableColumnExt updateDateCol = addDatePickerColumnToModel(ProgramsTableModel.UPDATE_DATE, getConfig().getDateTimeFormat(), false);
463 fixColumnWidth(updateDateCol, 120);
464
465
466 final TableColumnExt departmentHermeticCol = addBooleanColumnToModel(ProgramsTableModel.DEPARTMENT_HERMETIC, getTable());
467 fixColumnWidth(departmentHermeticCol, ReefDbUIs.REEFDB_CHECKBOX_WIDTH);
468 departmentHermeticCol.setSortable(true);
469
470
471 final TableColumnExt columnStatus = addColumn(null, new StatusRenderer(), ProgramsTableModel.STATUS);
472 fixColumnWidth(columnStatus, ReefDbUIs.REEFDB_CHECKBOX_WIDTH);
473 columnStatus.setSortable(true);
474
475
476 final ProgramsTableModel tableModel = new ProgramsTableModel(getTable().getColumnModel());
477 getTable().setModel(tableModel);
478
479
480 tableModel.setNoneEditableCols(ProgramsTableModel.CODE, ProgramsTableModel.STATUS);
481
482
483 columnStatus.setHideable(false);
484 columnCode.setHideable(false);
485 columnLibelle.setHideable(false);
486 columnDescription.setHideable(false);
487
488
489 initTable(getTable());
490
491 creationDateCol.setVisible(false);
492 updateDateCol.setVisible(false);
493
494
495 getTable().setVisibleRowCount(4);
496
497
498 getTable().setSortOrder(ProgramsTableModel.CODE, SortOrder.ASCENDING);
499 }
500
501
502
503
504 public void autoSelectRow() {
505
506 String previousSelectedProgramCode = getContext().getSelectedProgramCode();
507
508 if (StringUtils.isBlank(previousSelectedProgramCode) && getModel().getRowCount() > 1) {
509 return;
510 }
511
512
513 getModel().setSingleSelectedRow(null);
514
515 ProgramsTableRowModel rowToSelect = null;
516 if (getModel().getRowCount() == 1) {
517
518
519 rowToSelect = getModel().getRows().get(0);
520
521 } else {
522
523
524 for (final ProgramsTableRowModel row : getModel().getRows()) {
525 if (row.getCode().equals(previousSelectedProgramCode)) {
526 rowToSelect = row;
527 break;
528 }
529 }
530 }
531
532
533 if (rowToSelect != null) {
534 ProgramsTableRowModel finalRowToSelect = rowToSelect;
535 SwingUtilities.invokeLater(() -> {
536 selectRow(finalRowToSelect);
537 getModel().setSingleSelectedRow(finalRowToSelect);
538 });
539 }
540 }
541
542
543
544
545 public void keepModificationOnStrategiesTable() {
546
547 if (getModel().getSingleSelectedRow() != null) {
548 getModel().getSingleSelectedRow().setStrategies(getProgramsUI().getStrategiesTableUI().getHandler().getModel().getBeans());
549 getModel().getSingleSelectedRow().setStrategiesLoaded(true);
550 }
551
552 }
553
554
555
556
557
558
559 public ProgramsUI getProgramsUI() {
560 return getUI().getParentContainer(ProgramsUI.class);
561 }
562
563
564
565
566 @Override
567 public SwingValidator<ProgramsTableUIModel> getValidator() {
568 return getUI().getValidator();
569 }
570
571 private class StrategyAndLocationLoader extends SwingWorker<Object, Object> {
572
573 private final ProgramsUI adminProgrammeUI = getProgramsUI();
574 private final ProgramsTableRowModel selectedProgram;
575
576 public StrategyAndLocationLoader(ProgramsTableRowModel selectedProgram) {
577 this.selectedProgram = selectedProgram;
578 }
579
580 @Override
581 protected Object doInBackground() {
582
583 getContext().getProgramStrategyService().loadStrategiesAndLocations(selectedProgram);
584
585 return null;
586 }
587
588 @Override
589 protected void done() {
590 if (isCancelled()) {
591 return;
592 }
593 try {
594 get();
595 } catch (InterruptedException | ExecutionException e) {
596 throw new ReefDbTechnicalException(e.getMessage(), e);
597 }
598
599
600 adminProgrammeUI.getStrategiesTableUI().getHandler().load(selectedProgram);
601
602
603 adminProgrammeUI.getLocationsTableUI().getHandler().loadMonitoringLocationsFromProgram(selectedProgram);
604
605
606 adminProgrammeUI.getPmfmsTableUI().getHandler().clearTable();
607
608
609 recomputeRowValidState(selectedProgram);
610 adminProgrammeUI.getHandler().getValidator().doValidate();
611
612 }
613 }
614 }