From 2ce4e7f6a0194c8428882216ad30821eb9e8eb8b Mon Sep 17 00:00:00 2001 From: Viktoria Pundy Date: Thu, 31 May 2018 09:24:48 +0200 Subject: Added fxml and controller for archived operations [#27299] Created fxml-file for archived operations. Additionally, a controller was created to fill the pane with information about an archived Operation. Furthermore, the already existing controller archiveOperationController was adjusted to created these panes according to the existing archived operations. --- src/main/resources/fxml/OperationInArchive.fxml | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/resources/fxml/OperationInArchive.fxml (limited to 'src/main/resources/fxml/OperationInArchive.fxml') diff --git a/src/main/resources/fxml/OperationInArchive.fxml b/src/main/resources/fxml/OperationInArchive.fxml new file mode 100644 index 0000000..43ac14b --- /dev/null +++ b/src/main/resources/fxml/OperationInArchive.fxml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3-70-g09d2 From 31478202a4a4c371f861d9d8613429e124b72e9a Mon Sep 17 00:00:00 2001 From: Viktoria Pundy Date: Thu, 31 May 2018 16:43:22 +0200 Subject: Added padding for panes [#27299] --- src/main/resources/fxml/ArchiveOperation.fxml | 2 +- src/main/resources/fxml/OperationInArchive.fxml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/main/resources/fxml/OperationInArchive.fxml') diff --git a/src/main/resources/fxml/ArchiveOperation.fxml b/src/main/resources/fxml/ArchiveOperation.fxml index 21662fd..f185545 100644 --- a/src/main/resources/fxml/ArchiveOperation.fxml +++ b/src/main/resources/fxml/ArchiveOperation.fxml @@ -11,7 +11,7 @@ - + diff --git a/src/main/resources/fxml/OperationInArchive.fxml b/src/main/resources/fxml/OperationInArchive.fxml index 43ac14b..1f04fc0 100644 --- a/src/main/resources/fxml/OperationInArchive.fxml +++ b/src/main/resources/fxml/OperationInArchive.fxml @@ -10,7 +10,7 @@ - + @@ -32,7 +32,7 @@ - + -- cgit v1.2.3-70-g09d2 From cd1d4f95b1f7b7aeefd20d0b545d6856ff0b9b70 Mon Sep 17 00:00:00 2001 From: Viktoria Pundy Date: Thu, 31 May 2018 17:24:07 +0200 Subject: Added elements to Archive-Window, adjusted already existing elements [#27299] --- .../controller/ArchiveOperationController.java | 5 ++++ src/main/resources/fxml/ArchiveOperation.fxml | 27 +++++++++++++--------- .../resources/fxml/CreateOperationController.fxml | 2 +- src/main/resources/fxml/OperationInArchive.fxml | 20 ++++++++-------- 4 files changed, 32 insertions(+), 22 deletions(-) (limited to 'src/main/resources/fxml/OperationInArchive.fxml') diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java index 9c372fe..4377dcb 100644 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java @@ -27,6 +27,7 @@ import org.springframework.stereotype.Controller; @Controller public class ArchiveOperationController { + public AnchorPane apMainDetails; @FXML private AnchorPane backApMain; @FXML private AnchorPane backApDetails; @FXML private AnchorPane archiveOperationAP; @@ -87,6 +88,7 @@ public class ArchiveOperationController { event -> { detailOperation = operation; backApMain.setVisible(false); + apMainDetails.setVisible(false); backApDetails.setVisible(true); setOperation(); setDetailsVisible(true); @@ -157,6 +159,7 @@ public class ArchiveOperationController { } public void setListVisible(boolean b) { + apMainDetails.setVisible(b); archiveOperationFlowPane.setVisible(b); } @@ -169,6 +172,7 @@ public class ArchiveOperationController { setDetailsVisible(false); // apHeader.setVisible(true); backApDetails.setVisible(false); + apMainDetails.setVisible(true); backApMain.setVisible(true); } @@ -180,5 +184,6 @@ public class ArchiveOperationController { public void setVisible(boolean b) { archiveOperationAP.setVisible(b); backApMain.setVisible(b); + apMainDetails.setVisible(b); } } diff --git a/src/main/resources/fxml/ArchiveOperation.fxml b/src/main/resources/fxml/ArchiveOperation.fxml index f185545..b5daa5b 100644 --- a/src/main/resources/fxml/ArchiveOperation.fxml +++ b/src/main/resources/fxml/ArchiveOperation.fxml @@ -1,5 +1,6 @@ + @@ -7,16 +8,19 @@ - + - + - + + + + - + - + - + - + - - + - + - + @@ -74,5 +78,6 @@ + diff --git a/src/main/resources/fxml/CreateOperationController.fxml b/src/main/resources/fxml/CreateOperationController.fxml index ba27f53..79c0a51 100644 --- a/src/main/resources/fxml/CreateOperationController.fxml +++ b/src/main/resources/fxml/CreateOperationController.fxml @@ -87,5 +87,5 @@ - + diff --git a/src/main/resources/fxml/OperationInArchive.fxml b/src/main/resources/fxml/OperationInArchive.fxml index 1f04fc0..f079f42 100644 --- a/src/main/resources/fxml/OperationInArchive.fxml +++ b/src/main/resources/fxml/OperationInArchive.fxml @@ -10,10 +10,10 @@ - + - - + + @@ -24,15 +24,15 @@ - + - + - + @@ -41,19 +41,19 @@ - + - + - + - + -- cgit v1.2.3-70-g09d2 From 99df0868cbe3e215c1e494f89accae0deb0434d8 Mon Sep 17 00:00:00 2001 From: Viktoria Pundy Date: Thu, 31 May 2018 20:45:25 +0200 Subject: Adjusted design for main archive operation [#27299] Removed scrollbars, added padding for better look, etc. --- .../controller/ArchiveOperationController.java | 27 ---------------------- src/main/resources/fxml/ArchiveOperation.fxml | 17 +++++++++----- src/main/resources/fxml/OperationInArchive.fxml | 2 +- 3 files changed, 12 insertions(+), 34 deletions(-) (limited to 'src/main/resources/fxml/OperationInArchive.fxml') diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java index d6b6de8..107ed2f 100644 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java @@ -66,15 +66,6 @@ public class ArchiveOperationController { alert.showAndWait(); } setFlowPane(); - - /*for (Operation operation : list) { - Button b = new Button(); - b.setPrefHeight(200); - b.setPrefWidth(750 / 2); - b.setText(operation.opCode()); - b.setOnAction(event -> buttonClicked(b)); - archiveOperationFlowPane.getChildren().add(b); - }*/ } private void setFlowPane() { @@ -109,23 +100,6 @@ public class ArchiveOperationController { private Operation detailOperation; - /*private void buttonClicked(Button button) { - int size = archiveOperationFlowPane.getChildren().size(); - int index = 0; - for (int i = 0; i < size; i++) { - if (archiveOperationFlowPane.getChildren().get(i) == button) { - index = i; - break; - } - } - detailOperation = list.get(index); - backApMain.setVisible(false); - backApDetails.setVisible(true); - //apHeader.setVisible(false); - setOperation(); - setDetailsVisible(true); - }*/ - private void setOperation() { lblCodeHeader.setText(detailOperation.opCode()); String date = "am "; @@ -173,7 +147,6 @@ public class ArchiveOperationController { public void backClicked() { fpVehicles.getChildren().clear(); setDetailsVisible(false); - // apHeader.setVisible(true); backApDetails.setVisible(false); apMainDetails.setVisible(true); backApMain.setVisible(true); diff --git a/src/main/resources/fxml/ArchiveOperation.fxml b/src/main/resources/fxml/ArchiveOperation.fxml index 41c6a03..90cbe74 100644 --- a/src/main/resources/fxml/ArchiveOperation.fxml +++ b/src/main/resources/fxml/ArchiveOperation.fxml @@ -13,11 +13,11 @@ - + - + - + @@ -74,14 +74,19 @@ - + - + + - + diff --git a/src/main/resources/fxml/OperationInArchive.fxml b/src/main/resources/fxml/OperationInArchive.fxml index f079f42..9da1d9b 100644 --- a/src/main/resources/fxml/OperationInArchive.fxml +++ b/src/main/resources/fxml/OperationInArchive.fxml @@ -32,7 +32,7 @@ - + -- cgit v1.2.3-70-g09d2 From 17556e5701442e9c2a7e219c5d93734812344ebe Mon Sep 17 00:00:00 2001 From: Dominic Rogetzer Date: Mon, 18 Jun 2018 20:13:05 +0200 Subject: Rename 'einsatzverwaltung' to 'missioncontrol' + remove TODO [#25963] --- .../groupphase/application/MainApplication.java | 4 +- .../controller/ArchiveOperationController.java | 213 ------------ .../controller/CreateCarController.java | 231 ------------- .../controller/CreateNewEmployeeController.java | 174 ---------- .../controller/CreateOperationController.java | 371 --------------------- .../controller/CustomListItemController.java | 24 -- .../DetailArchiveOperationController.java | 77 ----- .../controller/EmployeeListController.java | 133 -------- .../controller/EmployeeListItemController.java | 87 ----- .../controller/FilterEmployeesController.java | 65 ---- .../einsatzverwaltung/controller/Helper.java | 34 -- .../controller/ManageEmployeesController.java | 120 ------- .../controller/OperationDetailsController.java | 169 ---------- .../controller/OperationInArchiveController.java | 65 ---- .../controller/RegistrationWindowController.java | 279 ---------------- .../controller/VehiclePaneController.java | 118 ------- .../einsatzverwaltung/dao/EmployeeDAO.java | 44 --- .../einsatzverwaltung/dao/EmployeeDatabaseDAO.java | 144 -------- .../einsatzverwaltung/dao/OperationDAO.java | 48 --- .../dao/OperationDatabaseDAO.java | 221 ------------ .../einsatzverwaltung/dao/RegistrationDAO.java | 28 -- .../dao/RegistrationDatabaseDAO.java | 130 -------- .../einsatzverwaltung/dao/VehicleDAO.java | 54 --- .../einsatzverwaltung/dao/VehicleDatabaseDAO.java | 211 ------------ .../groupphase/einsatzverwaltung/dto/Employee.java | 51 --- .../einsatzverwaltung/dto/EmployeeValidator.java | 23 -- .../einsatzverwaltung/dto/Operation.java | 70 ---- .../einsatzverwaltung/dto/Registration.java | 34 -- .../dto/RegistrationValidator.java | 174 ---------- .../groupphase/einsatzverwaltung/dto/Vehicle.java | 73 ---- .../einsatzverwaltung/service/EmployeeService.java | 46 --- .../service/EmployeeServiceImpl.java | 59 ---- .../service/OperationService.java | 70 ---- .../service/OperationServiceImpl.java | 286 ---------------- .../service/RegistrationService.java | 32 -- .../service/RegistrationServiceImpl.java | 52 --- .../einsatzverwaltung/service/VehicleService.java | 49 --- .../service/VehicleServiceImpl.java | 116 ------- .../controller/ArchiveOperationController.java | 213 ++++++++++++ .../controller/CreateCarController.java | 231 +++++++++++++ .../controller/CreateNewEmployeeController.java | 174 ++++++++++ .../controller/CreateOperationController.java | 371 +++++++++++++++++++++ .../controller/CustomListItemController.java | 24 ++ .../DetailArchiveOperationController.java | 77 +++++ .../controller/EmployeeListController.java | 133 ++++++++ .../controller/EmployeeListItemController.java | 87 +++++ .../controller/FilterEmployeesController.java | 65 ++++ .../missioncontrol/controller/Helper.java | 34 ++ .../controller/ManageEmployeesController.java | 120 +++++++ .../controller/OperationDetailsController.java | 169 ++++++++++ .../controller/OperationInArchiveController.java | 65 ++++ .../controller/RegistrationWindowController.java | 279 ++++++++++++++++ .../controller/VehiclePaneController.java | 118 +++++++ .../groupphase/missioncontrol/dao/EmployeeDAO.java | 44 +++ .../missioncontrol/dao/EmployeeDatabaseDAO.java | 144 ++++++++ .../missioncontrol/dao/OperationDAO.java | 48 +++ .../missioncontrol/dao/OperationDatabaseDAO.java | 221 ++++++++++++ .../missioncontrol/dao/RegistrationDAO.java | 28 ++ .../dao/RegistrationDatabaseDAO.java | 130 ++++++++ .../groupphase/missioncontrol/dao/VehicleDAO.java | 54 +++ .../missioncontrol/dao/VehicleDatabaseDAO.java | 211 ++++++++++++ .../groupphase/missioncontrol/dto/Employee.java | 51 +++ .../missioncontrol/dto/EmployeeValidator.java | 23 ++ .../groupphase/missioncontrol/dto/Operation.java | 70 ++++ .../missioncontrol/dto/Registration.java | 34 ++ .../missioncontrol/dto/RegistrationValidator.java | 174 ++++++++++ .../groupphase/missioncontrol/dto/Vehicle.java | 73 ++++ .../missioncontrol/service/EmployeeService.java | 46 +++ .../service/EmployeeServiceImpl.java | 59 ++++ .../missioncontrol/service/OperationService.java | 70 ++++ .../service/OperationServiceImpl.java | 286 ++++++++++++++++ .../service/RegistrationService.java | 32 ++ .../service/RegistrationServiceImpl.java | 52 +++ .../missioncontrol/service/VehicleService.java | 49 +++ .../missioncontrol/service/VehicleServiceImpl.java | 116 +++++++ src/main/resources/fxml/ArchiveOperation.fxml | 2 +- .../resources/fxml/CreateOperationController.fxml | 2 +- .../resources/fxml/DetailArchiveOperation.fxml | 2 +- src/main/resources/fxml/OperationDetails.fxml | 2 +- src/main/resources/fxml/OperationInArchive.fxml | 2 +- src/main/resources/fxml/RegistrationWindow.fxml | 2 +- src/main/resources/fxml/createCar.fxml | 2 +- src/main/resources/fxml/createNewEmployee.fxml | 2 +- src/main/resources/fxml/employeeList.fxml | 2 +- src/main/resources/fxml/employeeListItem.fxml | 2 +- .../resources/fxml/filterEmployeesControl.fxml | 2 +- src/main/resources/fxml/manageEmployees.fxml | 2 +- src/main/resources/fxml/vehiclePane.fxml | 2 +- .../CreateNewEmployeeControllerTest.java | 87 ----- .../controller/CreateNewVehicleControllerTest.java | 81 ----- .../controller/GuiTestApplication.java | 101 ------ .../controller/RegistrationControllerTest.java | 22 -- .../einsatzverwaltung/dao/EmployeeDAOTest.java | 253 -------------- .../einsatzverwaltung/dao/OperationDAOTest.java | 197 ----------- .../einsatzverwaltung/dao/RegistrationDAOTest.java | 115 ------- .../einsatzverwaltung/dao/VehicleDAOTest.java | 161 --------- .../service/EmployeeServiceTest.java | 67 ---- .../service/OperationServiceIntegrationTest.java | 97 ------ .../service/OperationServiceTest.java | 205 ------------ .../RegistrationServiceIntegrationTest.java | 55 --- .../service/RegistrationServiceTest.java | 159 --------- .../CreateNewEmployeeControllerTest.java | 87 +++++ .../controller/CreateNewVehicleControllerTest.java | 81 +++++ .../controller/GuiTestApplication.java | 101 ++++++ .../controller/RegistrationControllerTest.java | 22 ++ .../missioncontrol/dao/EmployeeDAOTest.java | 253 ++++++++++++++ .../missioncontrol/dao/OperationDAOTest.java | 197 +++++++++++ .../missioncontrol/dao/RegistrationDAOTest.java | 115 +++++++ .../missioncontrol/dao/VehicleDAOTest.java | 161 +++++++++ .../service/EmployeeServiceTest.java | 67 ++++ .../service/OperationServiceIntegrationTest.java | 97 ++++++ .../service/OperationServiceTest.java | 205 ++++++++++++ .../RegistrationServiceIntegrationTest.java | 55 +++ .../service/RegistrationServiceTest.java | 159 +++++++++ 114 files changed, 5789 insertions(+), 5791 deletions(-) delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateCarController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateOperationController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CustomListItemController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/DetailArchiveOperationController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListItemController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/FilterEmployeesController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/Helper.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ManageEmployeesController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationDetailsController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationInArchiveController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/VehiclePaneController.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDatabaseDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDAO.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Employee.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Operation.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Registration.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Vehicle.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeService.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationService.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationServiceImpl.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationService.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImpl.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleService.java delete mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ArchiveOperationController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateCarController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateNewEmployeeController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateOperationController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CustomListItemController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/DetailArchiveOperationController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListItemController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/FilterEmployeesController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/Helper.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ManageEmployeesController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationDetailsController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationInArchiveController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/RegistrationWindowController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/VehiclePaneController.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDatabaseDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDatabaseDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDatabaseDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDatabaseDAO.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Employee.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/EmployeeValidator.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Operation.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Registration.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/RegistrationValidator.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Vehicle.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java create mode 100644 src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeControllerTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewVehicleControllerTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/GuiTestApplication.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationControllerTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDAOTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDAOTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDAOTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDAOTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationServiceIntegrationTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationServiceTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceIntegrationTest.java delete mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateNewEmployeeControllerTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateNewVehicleControllerTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/GuiTestApplication.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/RegistrationControllerTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDAOTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDAOTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDAOTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDAOTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceIntegrationTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceIntegrationTest.java create mode 100644 src/test/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceTest.java (limited to 'src/main/resources/fxml/OperationInArchive.fxml') diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/application/MainApplication.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/application/MainApplication.java index 87daea4..a6c0566 100644 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/application/MainApplication.java +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/application/MainApplication.java @@ -1,6 +1,6 @@ package at.ac.tuwien.sepm.assignment.groupphase.application; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.CreateOperationController; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.CreateOperationController; import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; import javafx.application.Application; @@ -34,8 +34,6 @@ public class MainApplication extends Application { Platform.exit(); }); - // TODO: close connection on program exit (feedback) - configApplicationContext = new AnnotationConfigApplicationContext(MainApplication.class); final var fxmlLoader = configApplicationContext.getBean(SpringFXMLLoader.class); primaryStage.setScene( diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java deleted file mode 100644 index 9ac6a1a..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java +++ /dev/null @@ -1,213 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.OperationService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.Arrays; -import java.util.Collection; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; -import javafx.fxml.FXML; -import javafx.scene.control.Label; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.FlowPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class ArchiveOperationController { - - private static final Logger LOG = LoggerFactory.getLogger(ArchiveOperationController.class); - - @FXML private ImageView imvVehicleDetail; - @FXML private Label lblStatus; - @FXML private AnchorPane apMainDetails; - @FXML private Label lblOperations; - @FXML private Label lblCompleted; - @FXML private Label lblCancelled; - @FXML private AnchorPane backApMain; - @FXML private AnchorPane backApDetails; - @FXML private AnchorPane archiveOperationAP; - @FXML private AnchorPane apDetails; - @FXML private Label lblCodeHeader; - @FXML private Label lblOpCode; - @FXML private Label lblVehicles; - @FXML private Label lblDate; - @FXML private Label lblAddress; - @FXML private FlowPane fpVehicles; - private final OperationService operationService; - @FXML private FlowPane archiveOperationFlowPane; - private final CreateOperationController createOperationController; - private Set list = new HashSet<>(); - private final SpringFXMLLoader fxmlLoader; - - public ArchiveOperationController( - OperationService operationService, - CreateOperationController createOperationController, - SpringFXMLLoader fxmlLoader) { - this.operationService = operationService; - this.createOperationController = createOperationController; - this.fxmlLoader = fxmlLoader; - } - - @FXML - private void initialize() { - update(); - } - - public void update() { - archiveOperationFlowPane.getChildren().clear(); - list.clear(); - try { - list.addAll(operationService.list(EnumSet.of(Status.CANCELLED, Status.COMPLETED))); - long cancelledAmount = 0; - long completedAmount = 0; - for (Operation operation : list) { - if (operation.status() == Status.CANCELLED) cancelledAmount++; - else completedAmount++; - } - lblCancelled.setText("storniert: " + cancelledAmount); - lblCompleted.setText("abgeschlossen: " + completedAmount); - lblOperations.setText("Einsätze: " + list.size()); - } catch (ServiceException e) { - LOG.error("ServiceException in update().", e); - showServiceExceptionAlertAndWait("Die Einsätze konnten nicht geladen werden!"); - ; - } - setFlowPane(); - } - - private void setFlowPane() { - try { - archiveOperationFlowPane.getChildren().clear(); - for (Operation operation : sortSet(list)) { - OperationInArchiveController opInAController = - OperationInArchiveController.create(); - opInAController.set(operation); - opInAController - .getRoot() - .setOnMouseClicked( - event -> { - detailOperation = operation; - backApMain.setVisible(false); - apMainDetails.setVisible(false); - backApDetails.setVisible(true); - setOperation(); - setDetailsVisible(true); - imvVehicleDetail.setImage(new Image("/images/Vehicle.png")); - }); - archiveOperationFlowPane.getChildren().add(opInAController.getRoot()); - } - } catch (IOException e) { - LOG.error("IOException in setFlowPane(). ", e); - showServiceExceptionAlertAndWait("Die Elemente konnten nicht geladen werden!"); - } - } - - private Operation detailOperation; - - private List sortSet(Set operationsSet) { - Operation[] array = operationsSet.toArray(new Operation[operationsSet.size()]); - for (int i = array.length - 1; i > 0; i--) { - for (int j = 0; j < i; j++) { - LocalDateTime first = - LocalDateTime.ofInstant( - Objects.requireNonNull(array[j].created()), ZoneOffset.UTC); - LocalDateTime second = - LocalDateTime.ofInstant( - Objects.requireNonNull(array[j + 1].created()), ZoneOffset.UTC); - if (first.isBefore(second)) { - Operation help = array[j]; - array[j] = array[j + 1]; - array[j + 1] = help; - } - } - } - return Arrays.asList(array); - } - - private void setOperation() { - lblCodeHeader.setText(detailOperation.opCode()); - if (detailOperation.created() != null) { - LocalDateTime dateTime = - LocalDateTime.ofInstant( - Objects.requireNonNull(detailOperation.created()), ZoneOffset.UTC); - lblDate.setText( - "am " - + dateTime.getDayOfMonth() - + "." - + dateTime.getMonth().getValue() - + "." - + dateTime.getYear()); - } else { - lblDate.setText("---"); - } - lblStatus.setText( - "Status: " - + (detailOperation.status() == Status.CANCELLED - ? "storniert" - : "abgeschlossen")); - lblOpCode.setText(detailOperation.opCode()); - Collection elements = - detailOperation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); - String result = String.join(", ", elements); - - lblVehicles.setText(result); - lblAddress.setText(detailOperation.destination()); - - fpVehicles.getChildren().clear(); - try { - for (Vehicle vehicle : detailOperation.vehicles()) { - DetailArchiveOperationController controller = null; - - controller = DetailArchiveOperationController.create(fxmlLoader); - - controller.set(vehicle); - fpVehicles.getChildren().add(controller.getRoot()); - } - } catch (IOException e) { - LOG.error("IOException in setOperation(). ", e); - showServiceExceptionAlertAndWait("Die Element konnte nicht geladen werden!"); - } - } - - private void setDetailsVisible(boolean b) { - apDetails.setVisible(b); - } - - public void backClicked() { - LOG.debug("Hyperlink \"Zurück\" in archive detail view clicked."); - fpVehicles.getChildren().clear(); - setDetailsVisible(false); - backApDetails.setVisible(false); - apMainDetails.setVisible(true); - backApMain.setVisible(true); - } - - public void backToMain() { - LOG.debug("Hyperlink \"Zurück\" in archive main view clicked."); - this.setVisible(false); - createOperationController.setVisible(true); - } - - void setVisible(boolean b) { - archiveOperationAP.setVisible(b); - backApMain.setVisible(b); - apMainDetails.setVisible(b); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateCarController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateCarController.java deleted file mode 100644 index 0734820..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateCarController.java +++ /dev/null @@ -1,231 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showSuccessAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showValidationErrorAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.ConstructionType; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.VehicleType; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.VehicleService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.io.IOException; -import java.util.EnumSet; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javafx.collections.FXCollections; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ChoiceBox; -import javafx.scene.input.MouseButton; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.FlowPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class CreateCarController { - - @FXML private AnchorPane createCarAP; - @FXML private ChoiceBox cmbCtype; - @FXML private ChoiceBox cmbTyp; - - @FXML private Button btnCreate; - @FXML private CheckBox cbxNEF; - @FXML private FlowPane fpVehicleList; - private final CreateOperationController createOperationController; - - private static final Logger LOG = LoggerFactory.getLogger(CreateCarController.class); - private final VehicleService vehicleService; - private boolean update = false; - private long vid = -1; - - private Vehicle chooseVehicle; - - public CreateCarController( - CreateOperationController createOperationController, VehicleService vehicleService) { - this.createOperationController = createOperationController; - this.vehicleService = vehicleService; - } - - @FXML - private void initialize() { - fpVehicleList.setHgap(5); - fpVehicleList.setVgap(5); - - cmbCtype.setItems( - FXCollections.observableArrayList( - Stream.of( - ConstructionType.NORMAL, - ConstructionType.MITTELHOCHDACH, - ConstructionType.HOCHDACH) - .map(Enum::toString) - .collect(Collectors.toList()))); - cmbCtype.setValue(ConstructionType.NORMAL.toString()); - cmbTyp.setItems( - FXCollections.observableArrayList( - Stream.of( - VehicleType.BKTW, - VehicleType.KTW_B, - VehicleType.KTW, - VehicleType.RTW, - VehicleType.NEF, - VehicleType.NAH) - .map(Enum::toString) - .collect(Collectors.toList()))); - cmbTyp.setValue(VehicleType.BKTW.toString()); - - updateVehiclePane(); - } - - @FXML - private void createCar(ActionEvent actionEvent) { - - if (!update) { - LOG.debug("Button \"Erstellen\" clicked."); - Vehicle vehicle = - Vehicle.builder() - .constructionType(parseConstructionType()) - .type(parseType()) - .name("") - .status(Status.ABGEMELDET) - .hasNef(cbxNEF.isSelected()) - .build(); - try { - vehicleService.add(vehicle); - setToStart(); - } catch (InvalidVehicleException e) { - LOG.debug("Validation of Vehicle failed"); - showValidationErrorAlertAndWait(e.getMessage()); - setToStart(); - return; - } catch (ServiceException e) { - LOG.error("ServiceException in createCar(). ", e); - showServiceExceptionAlertAndWait( - "Ein Fehler beim Erstellen des Fahrzeuges ist aufgetreten."); - setToStart(); - return; - } - showSuccessAlertAndWait("Auto wurde erfolgreich angelegt."); - } else { - LOG.debug("Button \"Speichern\" clicked."); - try { - Vehicle vehicle = - Vehicle.builder() - .id(vid) - .constructionType(parseConstructionType()) - .type(parseType()) - .name("") - .status(Status.ABGEMELDET) - .hasNef(cbxNEF.isSelected()) - .build(); - vehicleService.update(vehicle); - setToStart(); - chooseVehicle = null; - } catch (InvalidVehicleException e) { - LOG.debug("Validation of Vehicle failed"); - showValidationErrorAlertAndWait(e.getMessage()); - setToStart(); - return; - } catch (ServiceException e) { - LOG.error("ServiceException in createCar(). ", e); - showServiceExceptionAlertAndWait(e.getMessage()); - setToStart(); - return; - } - showSuccessAlertAndWait("Auto wurde erfolgreich bearbeitet."); - } - - updateVehiclePane(); - } - - private ConstructionType parseConstructionType() { - if (cmbCtype.getSelectionModel().getSelectedItem() == null) { - return ConstructionType.NORMAL; - } - return ConstructionType.valueOf(cmbCtype.getSelectionModel().getSelectedItem()); - } - - private VehicleType parseType() { - if (cmbTyp.getSelectionModel().getSelectedItem() == null) { - return VehicleType.BKTW; - } - return VehicleType.valueOf(cmbTyp.getSelectionModel().getSelectedItem()); - } - - private void setToStart() { - btnCreate.setText("Erstellen"); - cbxNEF.setSelected(false); - cmbTyp.setValue(VehicleType.BKTW.name()); - cmbCtype.setValue(ConstructionType.NORMAL.name()); - update = false; - } - - private void updateVehicle(Vehicle vehicle) { - - cmbCtype.setValue(vehicle.constructionType().name()); - cmbTyp.setValue(vehicle.type().name()); - cbxNEF.setSelected(vehicle.hasNef()); - btnCreate.setText("Speichern"); - vid = vehicle.id(); - update = true; - chooseVehicle = vehicle; - } - - public void setVisible(boolean b) { - createCarAP.setVisible(b); - } - - @FXML - private void backToMain() { - LOG.debug("Hyperlink \"zurück\" clicked."); - this.setVisible(false); - createOperationController.setVisible(true); - } - - private void updateVehiclePane() { - try { - fpVehicleList.getChildren().clear(); - - Set vehicles; - - vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET)); - - for (Vehicle vehicle : vehicles) { - VehiclePaneController controller = VehiclePaneController.createVehiclePane(); - - controller.setData(vehicle, false, false); - controller - .getRootElement() - .setOnMouseClicked( - event -> { - if (event.getButton().equals(MouseButton.PRIMARY)) { - if (chooseVehicle == null || vehicle == chooseVehicle) { - if (update == false) { - chooseVehicle = vehicle; - updateVehicle(vehicle); - controller.setSelected(true); - } else { - setToStart(); - controller.setSelected(false); - - chooseVehicle = null; - } - } - } - }); - - fpVehicleList.getChildren().add(controller.getRootElement()); - } - } catch (ServiceException | IOException e) { - LOG.error("Exception in updateVehiclePane(). ", e); - showServiceExceptionAlertAndWait(e.getMessage()); - } - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java deleted file mode 100644 index 5f0a8b2..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java +++ /dev/null @@ -1,174 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showSuccessAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showValidationErrorAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; -import java.io.IOException; -import java.time.LocalDate; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javafx.collections.FXCollections; -import javafx.fxml.FXML; -import javafx.scene.Node; -import javafx.scene.control.Button; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ChoiceBox; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Controller; - -@Controller -@Scope("prototype") -public class CreateNewEmployeeController { - - private static final Logger LOG = LoggerFactory.getLogger(CreateNewEmployeeController.class); - private final EmployeeService employeeService; - - @FXML private Label lblHeader; - @FXML private CheckBox inputIsDriver; - @FXML private CheckBox inputIsPilot; - @FXML private TextField inputName; - @FXML private ChoiceBox inputQualification; - @FXML private Button btnCreate; - - private Node rootElement; - private Employee employee; - private boolean isEdit; - - private Runnable consumerCancelClicked; - private Runnable consumerCreateClicked; - - public CreateNewEmployeeController(EmployeeService employeeService) { - this.employeeService = employeeService; - } - - @FXML - private void initialize() { - inputQualification.setItems( - FXCollections.observableArrayList( - Stream.of( - EducationLevel.RS, - EducationLevel.NFS, - EducationLevel.NKV, - EducationLevel.NKA, - EducationLevel.NKI, - EducationLevel.NA) - .map(Enum::toString) - .collect(Collectors.toList()))); - - inputQualification.setValue(EducationLevel.RS.toString()); - employee = - Employee.builder() - .name("") - .educationLevel(EducationLevel.RS) - .isDriver(false) - .isPilot(false) - .birthday(LocalDate.MIN) - .build(); - } - - @FXML - private void onCancelClicked() { - LOG.debug("Hyperlink \"abbrechen\" clicked."); - if (consumerCancelClicked != null) { - consumerCancelClicked.run(); - } - } - - @FXML - private void onCreateClicked() { - LOG.debug("Button {} clicked.", btnCreate.getText()); - - employee = - employee.toBuilder() - .name(inputName.getText()) - .educationLevel(parseEducationLevel()) - .birthday(LocalDate.MIN) // TODO: change UI to include birthday field - .isDriver(inputIsDriver.isSelected()) - .isPilot(inputIsPilot.isSelected()) - .build(); - - try { - if (isEdit) { - employeeService.update(employee); - } else { - employeeService.add(employee); - } - } catch (InvalidEmployeeException e) { - LOG.debug("Validation for Employee failed"); - showValidationErrorAlertAndWait(e.getMessage()); - return; - } catch (ServiceException e) { - LOG.error("ServiceException in onCreateClicked(). ", e); - showServiceExceptionAlertAndWait( - "Der Eintrag konnte nicht gespeichert werden. Bitte versuchen Sie es erneut."); - return; - } - - showSuccessAlertAndWait( - "Der/die MitarbeiterIn wurde erfolgreich angelegt und gespeichert!"); - - if (consumerCreateClicked != null) { - consumerCreateClicked.run(); - } - } - - private EducationLevel parseEducationLevel() { - if (inputQualification.getSelectionModel().getSelectedItem() == null) { - return EducationLevel.RS; - } - return EducationLevel.valueOf(inputQualification.getSelectionModel().getSelectedItem()); - } - - private void setData(Employee employee) { - isEdit = true; - this.employee = employee; - inputName.setText(employee.name()); - inputQualification.setValue(employee.educationLevel().name()); - inputIsDriver.setSelected(employee.isDriver()); - inputIsPilot.setSelected(employee.isPilot()); - lblHeader.setText("Person bearbeiten"); - btnCreate.setText("Speichern"); - } - - public static CreateNewEmployeeController createCreateNewEmployeeController( - SpringFXMLLoader fxmlLoader, Employee employee) throws IOException { - CreateNewEmployeeController controller = createCreateNewEmployeeController(fxmlLoader); - controller.setData(employee); - return controller; - } - - public static CreateNewEmployeeController createCreateNewEmployeeController( - SpringFXMLLoader fxmlLoader) throws IOException { - FXMLWrapper wrapper = - fxmlLoader.loadAndWrap( - "/fxml/createNewEmployee.fxml", CreateNewEmployeeController.class); - Node root = (Node) wrapper.getLoadedObject(); - CreateNewEmployeeController controller = wrapper.getController(); - controller.rootElement = root; - return controller; - } - - public Node getRootElement() { - return rootElement; - } - - public void setConsumerCancelClicked(Runnable consumerCancelClicked) { - this.consumerCancelClicked = consumerCancelClicked; - } - - public void setConsumerCreateClicked(Runnable consumerCreateClicked) { - this.consumerCreateClicked = consumerCreateClicked; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateOperationController.java deleted file mode 100644 index 19ed7bf..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateOperationController.java +++ /dev/null @@ -1,371 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showSuccessAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showValidationErrorAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.OperationService; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.VehicleService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.io.IOException; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import javafx.collections.FXCollections; -import javafx.fxml.FXML; -import javafx.scene.control.Button; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; -import javafx.scene.control.MenuItem; -import javafx.scene.control.TextField; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.MouseButton; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.FlowPane; -import javafx.scene.layout.GridPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class CreateOperationController { - - private static final Logger LOG = LoggerFactory.getLogger(CreateOperationController.class); - - public AnchorPane apCreateOperation; - @FXML private GridPane grdWindowContainer; - @FXML private TextField txtCode; - @FXML private TextField txtAddress; - @FXML private TextField txtNote; - @FXML private Button btnCreateOperation; - @FXML private ListView lvVehicles; - @FXML private ListView lvActiveOperations; - @FXML private Label lblChosenVehicles; - @FXML private AnchorPane apInvisible; - @FXML private OperationDetailsController operationDetailsController; - @FXML private ManageEmployeesController manageEmployeesController; - @FXML private CreateCarController createCarController; - @FXML private RegistrationWindowController registrationWindowController; - @FXML private ArchiveOperationController archiveOperationController; - @FXML private FlowPane fpVehicles; - - private LinkedList chosenVehicles = new LinkedList<>(); - - private final OperationService operationService; - private final VehicleService vehicleService; - - public CreateOperationController( - OperationService operationService, VehicleService vehicleService) { - this.operationService = operationService; - this.vehicleService = vehicleService; - } - - @FXML - private void initialize() { - - lblChosenVehicles.setText("keine ausgewählt"); - lvActiveOperations.setCellFactory(param -> generateOpCodeListItem()); - - lvActiveOperations.setOnMouseClicked( - event -> { - if (event.getClickCount() == 2) { - if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { - return; - } - openDetailsWindow(lvActiveOperations.getSelectionModel().getSelectedItem()); - } - }); - - setVisible(true); - createCarController.setVisible(false); - registrationWindowController.setVisible(false); - } - - public void updateList() { - try { - fpVehicles.getChildren().clear(); - - // TODO: this should probably be handled differently - Set vehicles; - if (txtCode.getText().isEmpty()) { - vehicles = - vehicleService.list( - EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET))); - } else { - vehicles = operationService.rankVehicles(txtCode.getText()); - } - - for (Vehicle vehicle : vehicles) { - VehiclePaneController controller = VehiclePaneController.createVehiclePane(); - - controller.setData(vehicle, true, false); - controller - .getRootElement() - .setOnMouseClicked( - event -> { - if (event.getButton().equals(MouseButton.SECONDARY)) { - createContextMenu(vehicle, vehicleService) - .show( - controller.getRootElement(), - event.getScreenX(), - event.getScreenY()); - } else { - if (chosenVehicles.contains(vehicle)) { - chosenVehicles.remove(vehicle); - controller.setSelected(false); - } else { - chosenVehicles.add(vehicle); - controller.setSelected(true); - } - - StringBuilder result = new StringBuilder(); - for (int i = 0; i < chosenVehicles.size(); i++) { - if (i == chosenVehicles.size() - 1) { - result.append(chosenVehicles.get(i).name()); - } else { - result.append(chosenVehicles.get(i).name()) - .append(", "); - } - } - if (result.toString().equals("")) { - lblChosenVehicles.setText("keine ausgewählt"); - } else { - lblChosenVehicles.setText(result.toString()); - } - } - }); - - if (chosenVehicles.stream().anyMatch(v -> v.id() == vehicle.id())) - controller.setSelected(true); - - fpVehicles.getChildren().add(controller.getRootElement()); - } - } catch (ServiceException | IOException e) { - LOG.error("Exception in updateList(). ", e); - showServiceExceptionAlertAndWait( - "Beim Erstellen des Ranking ist ein Fehler aufgetreten."); - } catch (InvalidOperationException e) { - LOG.debug("Validation error in updateList(). ", e); - showValidationErrorAlertAndWait(e.getMessage()); - } - try { - lvActiveOperations.setItems( - FXCollections.observableArrayList( - operationService.list(EnumSet.of(Status.ACTIVE)))); - } catch (ServiceException e) { - LOG.error("ServiceException in updateList(). ", e); - showServiceExceptionAlertAndWait( - "Beim Holen der aktiven Einsätze ist ein Fehler aufgetreten"); - } - } - - private ContextMenu createContextMenu(Vehicle data, VehicleService vehicleService) { - ContextMenu menu = new ContextMenu(); - - for (Vehicle.Status status : Vehicle.Status.values()) { - if (status == Vehicle.Status.ABGEMELDET) { - continue; - } - - MenuItem mi = new MenuItem(status.name()); - - if (status == Vehicle.Status.FREI_FUNK || status == Vehicle.Status.FREI_WACHE) { - mi.getStyleClass().add("mi-free"); - } else { - mi.getStyleClass().add("mi-other"); - } - - mi.setOnAction( - event -> { - try { - vehicleService.update(data.toBuilder().status(status).build()); - this.updateList(); - } catch (InvalidVehicleException e) { - LOG.debug( - "Validation error in createContextMenu(). (mi.setOnAction) ", - e); - showValidationErrorAlertAndWait(e.getMessage()); - } catch (ServiceException e) { - LOG.error("Exception in createContextMenu(). (mi.setOnAction) ", e); - showServiceExceptionAlertAndWait( - "Beim Aktualisieren der Fahrzeuge ist ein Fehler aufgetreten."); - } - }); - - menu.getItems().add(mi); - } - - MenuItem abmelden = new MenuItem("abmelden"); - - abmelden.setOnAction( - event -> { - try { - List registrations = data.registrations(); - assert registrations - != null; // Otherwise the element shouldn't be in the list. - - List newRegistrations = new ArrayList<>(); - Instant now = Instant.now(); - - for (Registration registration : registrations) { - if (registration.start().isBefore(now) - && registration.end().isAfter(now)) { - newRegistrations.add( - registration - .toBuilder() - .end(Instant.now().minus(1, ChronoUnit.SECONDS)) - .build()); - } else newRegistrations.add(registration); - } - - vehicleService.update( - data.toBuilder() - .registrations(newRegistrations) - .status(Vehicle.Status.ABGEMELDET) - .build()); - - this.updateList(); - } catch (InvalidVehicleException e) { - LOG.debug( - "Validation error in createContextMenu(). (abmelden.setOnAction) ", - e); - showValidationErrorAlertAndWait(e.getMessage()); - } catch (ServiceException e) { - LOG.error("Exception in createContextMenu(). (abmelden.setOnAction) ", e); - showServiceExceptionAlertAndWait( - "Beim Aktualisieren der Fahrzeuge ist ein Fehler aufgetreten."); - } - }); - - menu.getItems().add(abmelden); - return menu; - } - - @FXML - protected void createOperationClicked() { - LOG.debug("Button \"Erstellen\" clicked."); - Vehicle[] vehicles = new Vehicle[chosenVehicles.size()]; - for (int i = 0; i < chosenVehicles.size(); i++) { - vehicles[i] = chosenVehicles.get(i); - } - Operation operation = - Operation.builder() - .additionalInfo(txtNote.getText()) - .destination(txtAddress.getText()) - .opCode(txtCode.getText()) - .status(Status.ACTIVE) - .vehicles(Set.of(vehicles)) - .build(); - try { - operationService.add(operation); - } catch (ServiceException e) { - LOG.error("Exception in createOperationClicked(). ", e); - showServiceExceptionAlertAndWait( - "Beim Erstellen des Einsatzes ist ein Fehler aufgetreten."); - return; - } catch (InvalidOperationException e) { - LOG.debug("Validation error in createOperationClicked(). ", e); - showValidationErrorAlertAndWait(e.getMessage()); - return; - } - showSuccessAlertAndWait("Der Einsatz wurde erfolgreich gespeichert."); - updateList(); - lblChosenVehicles.setText("keine ausgewählt"); - txtAddress.setText(""); - txtCode.setText(""); - txtNote.setText(""); - chosenVehicles = new LinkedList<>(); - } - - @FXML - private void onRegistrationLinkClicked() { - LOG.debug("Hyperlink \"Anmeldungen\" clicked."); - openRegistrationWindow(); - } - - @FXML - private void onEmployeeLinkClicked() { - LOG.debug("Hyperlink \"Personen\" clicked."); - openCreateNewEmployeeWindow(); - } - - @FXML - private void onVehicleLinkClicked() { - LOG.debug("Hyperlink \"Fahrzeuge\" clicked."); - openCreateCarWindow(); - } - - @FXML - private void onArchivLinkClicked() { - LOG.debug("Hyperlink \"Archiv\" clicked."); - archiveOperationController.update(); - openArchivWindow(); - } - - private void openArchivWindow() { - archiveOperationController.setVisible(true); - this.setVisible(false); - } - - void setVisible(boolean b) { - apInvisible.setVisible(!b); - grdWindowContainer.setVisible(!b); - - updateList(); - } - - private void openDetailsWindow(Operation operation) { - operationDetailsController.initOperation(operation); - this.setVisible(false); - } - - private void openCreateNewEmployeeWindow() { - this.setVisible(false); - manageEmployeesController.setVisible(true); - } - - private void openCreateCarWindow() { - this.setVisible(false); - createCarController.setVisible(true); - } - - private void openRegistrationWindow() { - this.setVisible(false); - registrationWindowController.setVisible(true); - } - - @FXML - private void onOperationCodeChanged(KeyEvent keyEvent) { - if (keyEvent.getCode() == KeyCode.ENTER) { - updateList(); - } - } - - static ListCell generateOpCodeListItem() { - return new ListCell<>() { - @Override - protected void updateItem(Operation item, boolean empty) { - super.updateItem(item, empty); - - if (empty || item == null || item.opCode() == null) { - setText(null); - } else { - setText(item.opCode()); - } - } - }; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CustomListItemController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CustomListItemController.java deleted file mode 100644 index 79cf243..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CustomListItemController.java +++ /dev/null @@ -1,24 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import javafx.scene.Node; - -public abstract class CustomListItemController { - - protected Node rootElement; - - public Node getRootElement() { - return rootElement; - } - - public void setSelected(boolean selected) { - rootElement.getStyleClass().clear(); - - if (selected) { - rootElement.getStyleClass().add("bg-yellow"); - rootElement.getStyleClass().add("shadowed"); - } else { - rootElement.getStyleClass().add("bg-white"); - rootElement.getStyleClass().add("shadowed"); - } - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/DetailArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/DetailArchiveOperationController.java deleted file mode 100644 index 41bd2a6..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/DetailArchiveOperationController.java +++ /dev/null @@ -1,77 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; -import java.io.IOException; -import java.util.Objects; -import javafx.fxml.FXML; -import javafx.scene.Node; -import javafx.scene.layout.VBox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class DetailArchiveOperationController { - private static final Logger LOG = - LoggerFactory.getLogger(DetailArchiveOperationController.class); - - @FXML private VBox vBoxVehicle; - @FXML private VBox vBoxPeople; - private final SpringFXMLLoader fxmlLoader; - - public DetailArchiveOperationController(SpringFXMLLoader fxmlLoader) { - this.fxmlLoader = fxmlLoader; - } - - static DetailArchiveOperationController create(SpringFXMLLoader fxmlLoader) throws IOException { - FXMLWrapper wrapper = - fxmlLoader.loadAndWrap( - "/fxml/DetailArchiveOperation.fxml", - DetailArchiveOperationController.class); - - Node root = (Node) wrapper.getLoadedObject(); - DetailArchiveOperationController result = wrapper.getController(); - result.rootElement = root; - - return result; - } - - public Node getRoot() { - return rootElement; - } - - private Node rootElement; - - public void set(Vehicle vehicle) { - VehiclePaneController controller; - try { - controller = VehiclePaneController.createVehiclePane(); - controller.setData(vehicle, false, false); - vBoxVehicle.getChildren().add(controller.getRootElement()); - } catch (IOException e) { - LOG.error("IOException in set(Vehicle). (vBoxVehicle) ", e); - showServiceExceptionAlertAndWait( - "Ein interner Fehler ist aufgetreten. Bitte wenden Sie sich an den/die SystemadministratorIn."); - } - try { - for (int i = 0; i < Objects.requireNonNull(vehicle.registrations()).size(); i++) { - Employee employee = - Objects.requireNonNull(vehicle.registrations()).get(i).employee(); - - EmployeeListItemController employeeListItemController = - EmployeeListItemController.createEmployeeListItemController( - fxmlLoader, employee); - vBoxPeople.getChildren().add(employeeListItemController.getRootElement()); - } - } catch (IOException e) { - LOG.error("IOException in set(Vehicle). (vBoxPeople) ", e); - showServiceExceptionAlertAndWait( - "Ein interner Fehler ist aufgetreten. Bitte wenden Sie sich an den/die SystemadministratorIn."); - } - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListController.java deleted file mode 100644 index 6e1159a..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListController.java +++ /dev/null @@ -1,133 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.function.Consumer; -import javafx.fxml.FXML; -import javafx.geometry.Insets; -import javafx.scene.Node; -import javafx.scene.layout.FlowPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Controller; - -@Controller -@Scope("prototype") -public class EmployeeListController { - - private static final Logger LOG = LoggerFactory.getLogger(EmployeeListController.class); - - @FXML private FlowPane flowPaneEmployeeList; - - private Consumer onEmployeeClicked; - - private final SpringFXMLLoader fxmlLoader; - private Node rootElement; - private List employeeListItemControllers; - private Insets listItemMargins = new Insets(10, 5, 0, 5); - - public EmployeeListController(SpringFXMLLoader fxmlLoader) { - this.fxmlLoader = fxmlLoader; - this.employeeListItemControllers = new ArrayList<>(); - } - - public void setListItemMargins(Insets value) { - this.listItemMargins = value; - } - - public void setData(Set employeeList) { - setData(employeeList, null, null); - } - - public void setData(Set employeeList, Consumer onEmployeeClicked) { - setData(employeeList, onEmployeeClicked, null); - } - - public void setData( - Set employeeList, - Consumer onEmployeeClicked, - Consumer onEmployeeListItemClicked) { - - flowPaneEmployeeList.getChildren().clear(); - employeeListItemControllers.clear(); - employeeList.forEach( - employee -> - addEmployeeToFlowPane( - employee, onEmployeeClicked, onEmployeeListItemClicked)); - } - - private void addEmployeeToFlowPane( - Employee employee, - Consumer onEmployeeClicked, - Consumer onEmployeeListItemClicked) { - - try { - EmployeeListItemController controller = - EmployeeListItemController.createEmployeeListItemController( - fxmlLoader, employee); - Node rootElement = controller.getRootElement(); - flowPaneEmployeeList.getChildren().add(rootElement); - employeeListItemControllers.add(controller); - FlowPane.setMargin(rootElement, listItemMargins); - if (onEmployeeClicked != null) { - controller.setConsumerEmployeeClicked(onEmployeeClicked); - } - if (onEmployeeListItemClicked != null) { - controller.setConsumerEmployeeListItemClicked( - employeeListItemController -> { - onEmployeeListItemClicked.accept(employeeListItemController); - if (this.onEmployeeClicked != null) { - this.onEmployeeClicked.accept( - employeeListItemController.getEmployee()); - } - }); - } - } catch (IOException e) { - LOG.error("IOException in addEmployeeToFlowPane. ", e); - } - } - - private void setEmployeeSelected(Employee employee, boolean selected) { - employeeListItemControllers - .stream() - .filter(controller -> controller.getEmployee().equals(employee)) - .forEach(controller -> controller.setSelected(selected)); - } - - public void selectEmployee(Employee employee) { - setEmployeeSelected(employee, true); - } - - public void deselectEmployee(Employee employee) { - setEmployeeSelected(employee, false); - } - - public void deselectAllEmployees() { - employeeListItemControllers.forEach( - employeeListItemController -> employeeListItemController.setSelected(false)); - } - - public static EmployeeListController createEmployeeListController(SpringFXMLLoader loader) - throws IOException { - FXMLWrapper wrapper = - loader.loadAndWrap("/fxml/employeeList.fxml", EmployeeListController.class); - Node root = (Node) wrapper.getLoadedObject(); - EmployeeListController controller = wrapper.getController(); - controller.rootElement = root; - return controller; - } - - public Node getRootElement() { - return rootElement; - } - - public void setOnEmployeeClicked(Consumer onEmployeeClicked) { - this.onEmployeeClicked = onEmployeeClicked; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListItemController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListItemController.java deleted file mode 100644 index 7b5910a..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListItemController.java +++ /dev/null @@ -1,87 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; -import java.io.IOException; -import java.util.function.Consumer; -import javafx.fxml.FXML; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Controller; - -@Controller -@Scope("prototype") -public class EmployeeListItemController extends CustomListItemController { - - @FXML private Label lblName; - @FXML private Label lblQualification; - @FXML private Label lblPilot; - @FXML private Label lblDriver; - @FXML private ImageView imgPilot; - @FXML private ImageView imgDriver; - @FXML private ImageView imgQualification; - - private Employee employee; - - private Consumer consumerEmployeeClicked; - private Consumer consumerEmployeeListItemClicked; - - @FXML - private void onEmployeeClicked() { - if (consumerEmployeeClicked != null) { - consumerEmployeeClicked.accept(employee); - } - if (consumerEmployeeListItemClicked != null) { - consumerEmployeeListItemClicked.accept(this); - } - } - - private void setData(Employee employee) { - this.employee = employee; - lblName.setText(employee.name()); - lblQualification.setText(employee.educationLevel().name()); - lblPilot.setText(String.format("%s Pilot", employee.isPilot() ? "ist" : "nicht")); - lblDriver.setText(String.format("%s Fahrer", employee.isDriver() ? "ist" : "nicht")); - imgQualification.setImage(new Image("/images/Qualification.png")); - String imgSrcPilot = - String.format("/images/%s", employee.isPilot() ? "Pilot.png" : "NotPilot.png"); - imgPilot.setImage(new Image(imgSrcPilot)); - String imgSrcDriver = - String.format("/images/%s", employee.isDriver() ? "Driver.png" : "NotDriver.png"); - imgDriver.setImage(new Image(imgSrcDriver)); - } - - public static EmployeeListItemController createEmployeeListItemController( - SpringFXMLLoader fxmlLoader, Employee employee) throws IOException { - EmployeeListItemController controller = createEmployeeListItemController(fxmlLoader); - controller.setData(employee); - return controller; - } - - public static EmployeeListItemController createEmployeeListItemController( - SpringFXMLLoader loader) throws IOException { - FXMLWrapper wrapper = - loader.loadAndWrap("/fxml/employeeListItem.fxml", EmployeeListItemController.class); - Node root = (Node) wrapper.getLoadedObject(); - EmployeeListItemController controller = wrapper.getController(); - controller.rootElement = root; - return controller; - } - - public Employee getEmployee() { - return employee; - } - - public void setConsumerEmployeeClicked(Consumer consumerEmployeeClicked) { - this.consumerEmployeeClicked = consumerEmployeeClicked; - } - - public void setConsumerEmployeeListItemClicked( - Consumer consumerEmployeeListItemClicked) { - this.consumerEmployeeListItemClicked = consumerEmployeeListItemClicked; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/FilterEmployeesController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/FilterEmployeesController.java deleted file mode 100644 index a1d1f70..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/FilterEmployeesController.java +++ /dev/null @@ -1,65 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; -import java.io.IOException; -import java.util.function.Consumer; -import javafx.fxml.FXML; -import javafx.scene.Node; -import javafx.scene.control.TextField; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Controller; - -@Controller -@Scope("prototype") -public class FilterEmployeesController { - private static final Logger LOG = LoggerFactory.getLogger(FilterEmployeesController.class); - - @FXML private TextField inputFilterString; - - private Consumer consumerFilterTextChanged; - private Runnable consumerAddEmployeeClicked; - - private Node rootElement; - - @FXML - private void onAddEmployeeClicked() { - LOG.debug("Button \"Person hinzufügen\" clicked."); - if (consumerAddEmployeeClicked != null) { - consumerAddEmployeeClicked.run(); - } - } - - @FXML - private void onFilterTextChanged() { - LOG.debug("Filter text changed."); - if (consumerFilterTextChanged != null) { - consumerFilterTextChanged.accept(inputFilterString.getText()); - } - } - - public void setOnFilterTextChangedListener(Consumer callback) { - this.consumerFilterTextChanged = callback; - } - - public void setOnAddEmployeeClickedListener(Runnable callback) { - this.consumerAddEmployeeClicked = callback; - } - - public static FilterEmployeesController createFilterEmployeesController( - SpringFXMLLoader fxmlLoader) throws IOException { - FXMLWrapper wrapper = - fxmlLoader.loadAndWrap( - "/fxml/filterEmployeesControl.fxml", FilterEmployeesController.class); - Node root = (Node) wrapper.getLoadedObject(); - FilterEmployeesController controller = wrapper.getController(); - controller.rootElement = root; - return controller; - } - - public Node getRootElement() { - return rootElement; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/Helper.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/Helper.java deleted file mode 100644 index 694c804..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/Helper.java +++ /dev/null @@ -1,34 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.ButtonType; - -public class Helper { - - static final String ALERT_TITLE_VALIDATION_ERROR = "Validierungsfehler"; - static final String ALERT_TITLE_SERVICE_EXCEPTION = "Fehler"; - static final String ALERT_TITLE_SUCCESS = "Erfolg"; - - private Helper() {} // SonarLint insisted to create a private constructor to hide the public one - - static void showValidationErrorAlertAndWait(String message) { - showAlertWithOkButtonAndWait(AlertType.ERROR, ALERT_TITLE_VALIDATION_ERROR, message); - } - - static void showServiceExceptionAlertAndWait(String message) { - showAlertWithOkButtonAndWait(AlertType.ERROR, ALERT_TITLE_SERVICE_EXCEPTION, message); - } - - static void showSuccessAlertAndWait(String message) { - showAlertWithOkButtonAndWait(AlertType.INFORMATION, ALERT_TITLE_SUCCESS, message); - } - - static void showAlertWithOkButtonAndWait( - AlertType alertType, String headerText, String contentText) { - Alert alert = new Alert(alertType, contentText, ButtonType.OK); - alert.setTitle(headerText); - alert.setHeaderText(headerText); - alert.showAndWait(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ManageEmployeesController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ManageEmployeesController.java deleted file mode 100644 index 3aaf040..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ManageEmployeesController.java +++ /dev/null @@ -1,120 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import java.io.IOException; -import java.util.HashSet; -import java.util.stream.Collectors; -import javafx.fxml.FXML; -import javafx.scene.layout.AnchorPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class ManageEmployeesController { - - private static final Logger LOG = LoggerFactory.getLogger(ManageEmployeesController.class); - @FXML private AnchorPane listEmployeesAP; - @FXML private AnchorPane containerHeader; - @FXML private EmployeeListController employeeListController; - - private final EmployeeService employeeService; - private final SpringFXMLLoader fxmlLoader; - - private final CreateOperationController createOperationController; - - public ManageEmployeesController( - EmployeeService employeeService, - SpringFXMLLoader fxmlLoader, - CreateOperationController createOperationController) { - this.employeeService = employeeService; - this.fxmlLoader = fxmlLoader; - this.createOperationController = createOperationController; - } - - @FXML - private void initialize() { - openFilter(); - } - - private void openFilter() { - try { - FilterEmployeesController filterEmployeesController = - FilterEmployeesController.createFilterEmployeesController(fxmlLoader); - containerHeader.getChildren().clear(); - containerHeader.getChildren().add(filterEmployeesController.getRootElement()); - filterEmployeesController.setOnFilterTextChangedListener(this::updateEmployeeList); - filterEmployeesController.setOnAddEmployeeClickedListener(this::openAddEmployee); - updateEmployeeList(); - - } catch (IOException e) { - LOG.error("IOException in openFilter().", e); - } - } - - private void openAddEmployee() { - employeeListController.deselectAllEmployees(); - openEmployee(null); - } - - private void openEditEmployee(Employee employee) { - employeeListController.deselectAllEmployees(); - employeeListController.selectEmployee(employee); - openEmployee(employee); - } - - private void openEmployee(Employee employee) { - try { - CreateNewEmployeeController createNewEmployeeController = - employee == null - ? CreateNewEmployeeController.createCreateNewEmployeeController( - fxmlLoader) - : CreateNewEmployeeController.createCreateNewEmployeeController( - fxmlLoader, employee); - containerHeader.getChildren().clear(); - containerHeader.getChildren().add(createNewEmployeeController.getRootElement()); - createNewEmployeeController.setConsumerCancelClicked(this::openFilter); - createNewEmployeeController.setConsumerCreateClicked(this::openFilter); - } catch (IOException e) { - LOG.error("IOException in openEmployee(). ", e); - } - } - - private void updateEmployeeList() { - updateEmployeeList(""); - } - - private void updateEmployeeList(String searchString) { - - try { - employeeListController.setData( - employeeService - .list() - .stream() - .filter( - employee -> - searchString.trim().isEmpty() - || employee.name() - .toLowerCase() - .contains(searchString.toLowerCase())) - .collect(Collectors.toCollection(HashSet::new)), - this::openEditEmployee); - - } catch (ServiceException e) { - LOG.error("ServiceException in updateEmployeeList(). ", e); - } - } - - public void setVisible(boolean b) { - listEmployeesAP.setVisible(b); - } - - public void backToMain() { - LOG.debug("Hyperlink \"Zurück\" clicked."); - this.setVisible(false); - createOperationController.setVisible(true); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationDetailsController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationDetailsController.java deleted file mode 100644 index c0c68f3..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationDetailsController.java +++ /dev/null @@ -1,169 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showAlertWithOkButtonAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showSuccessAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showValidationErrorAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.OperationService; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.VehicleService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.io.IOException; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Set; -import java.util.stream.Collectors; -import javafx.collections.FXCollections; -import javafx.fxml.FXML; -import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.ListView; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.FlowPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class OperationDetailsController { - private static final Logger LOG = LoggerFactory.getLogger(OperationDetailsController.class); - - public Operation operation; - private final OperationService operationService; - private final VehicleService vehicleService; - private final CreateOperationController createOperationController; - @FXML private FlowPane fpVehicles; - @FXML private ListView lvActiveOperations; - @FXML private Label lblChosenVehicles; - @FXML private Button btnCloseOperation; - @FXML private Button btnCancelOperation; - @FXML private Label lblCode, lblAdditionalInfo, lblAddress; - @FXML private AnchorPane operationDetailsAP; - - public OperationDetailsController( - OperationService operationService, - VehicleService vehicleService, - CreateOperationController createOperationController) { - this.operationService = operationService; - this.vehicleService = vehicleService; - this.createOperationController = createOperationController; - } - - @FXML - private void initialize() { - lvActiveOperations.setCellFactory( - param -> CreateOperationController.generateOpCodeListItem()); - lvActiveOperations.setOnMouseClicked( - event -> { - if (event.getClickCount() == 2) { - if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { - return; - } - initOperation(lvActiveOperations.getSelectionModel().getSelectedItem()); - } - }); - } - - private void updateFlowPane() { - try { - fpVehicles.getChildren().clear(); - for (Vehicle vehicle : operation.vehicles()) { - VehiclePaneController controller = VehiclePaneController.createVehiclePane(); - controller.setData(vehicle, true, true); - controller.getBtnRequest().setOnAction(e -> requestVehicleClicked(controller)); - fpVehicles.getChildren().add(controller.getRootElement()); - } - } catch (IOException e) { - LOG.error("Error while updating list.", e); - showServiceExceptionAlertAndWait("Error while updating list."); - } - } - - void initOperation(Operation operation) { - fillActiveList(); - this.operation = operation; - lblCode.setText(operation.opCode()); - Collection vehicleNames = - operation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); - String result = String.join(", ", vehicleNames); - lblChosenVehicles.setText(result.toString()); - lblAdditionalInfo.setText(operation.additionalInfo()); - lblAddress.setText(operation.destination()); - updateFlowPane(); - operationDetailsAP.setVisible(true); - } - - private void fillActiveList() { - try { - lvActiveOperations.setItems( - FXCollections.observableArrayList( - operationService.list(EnumSet.of(Status.ACTIVE)))); - } catch (ServiceException e) { - LOG.error("ServiceException in fillActiveList(). ", e); - showServiceExceptionAlertAndWait(e.getMessage()); - } - } - - @FXML - public void closeOperationClicked() { - LOG.debug("Button \"Abschließen\" clicked."); - try { - operationService.complete(operation.id(), Status.COMPLETED); - } catch (InvalidOperationException e) { - LOG.debug("Validation error in closeOperationClicked(). ", e); - showAlertWithOkButtonAndWait(AlertType.ERROR, "Validierungsfehler", e.getMessage()); - return; - } catch (ServiceException e) { - LOG.error("Exception in closeOperationClicked(). ", e); - showServiceExceptionAlertAndWait(e.getMessage()); - return; - } - showSuccessAlertAndWait("Der Einsatz wurde erfolgreich aktualisiert"); - createOperationController.updateList(); - closeWindow(); - } - - public void cancelOperationClicked() { - LOG.debug("Button \"Stornieren\" clicked."); - try { - operationService.complete(operation.id(), Status.CANCELLED); - } catch (InvalidOperationException e) { - LOG.debug("Validation error in cancelOperationClicked(). ", e); - showValidationErrorAlertAndWait(e.getMessage()); - return; - } catch (ServiceException e) { - LOG.error("Exception in cancelOperationClicked(). ", e); - showServiceExceptionAlertAndWait(e.getMessage()); - return; - } - showSuccessAlertAndWait("Der Einsatz wurde erfolgreich aktualisiert"); - createOperationController.updateList(); - closeWindow(); - } - - private void requestVehicleClicked(VehiclePaneController v) { - LOG.debug("Button \"Nachfordern\" clicked."); - - try { - operationService.requestVehicles(operation.id(), Set.of(v.getData().id())); - } catch (ServiceException | InvalidOperationException | InvalidVehicleException e) { - LOG.error("Exception in requestVehicleClicked()", e); - showServiceExceptionAlertAndWait(e.getMessage()); - return; - } - showSuccessAlertAndWait("Das Fahrzeug wurde erfolgreich angefordert"); - createOperationController.updateList(); - } - - public void closeWindow() { - LOG.debug("Hyperlink \"Zurück\" clicked."); - operationDetailsAP.setVisible(false); - this.createOperationController.setVisible(true); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationInArchiveController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationInArchiveController.java deleted file mode 100644 index d1b325c..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationInArchiveController.java +++ /dev/null @@ -1,65 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import java.io.IOException; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.Collection; -import java.util.Objects; -import java.util.stream.Collectors; -import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.scene.Node; -import javafx.scene.text.Text; - -public class OperationInArchiveController { - - @FXML private Text txtAddress; - @FXML private Text txtVehicles; - @FXML private Text txtDate; - @FXML private Text txtOpCode; - - static OperationInArchiveController create() throws IOException { - FXMLLoader fxmlLoader = - new FXMLLoader( - OperationInArchiveController.class.getResource( - "/fxml/OperationInArchive.fxml")); - Node root = fxmlLoader.load(); - OperationInArchiveController result = fxmlLoader.getController(); - result.rootElement = root; - - return result; - } - - public Node getRoot() { - return rootElement; - } - - private Node rootElement; - - public void set(Operation operation) { - txtAddress.setText(operation.destination()); - String date = "am "; - if (operation.created() != null) { - LocalDateTime myDateTime = - LocalDateTime.ofInstant( - Objects.requireNonNull(operation.created()), ZoneOffset.UTC); - date += - myDateTime.getDayOfMonth() - + "." - + myDateTime.getMonth().getValue() - + "." - + myDateTime.getYear(); - txtDate.setText(date); - } else { - txtDate.setText("---"); - } - txtOpCode.setText(operation.opCode()); - Collection elements = - operation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); - String result = String.join(", ", elements); - - txtVehicles.setText(result); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java deleted file mode 100644 index ed5a12d..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java +++ /dev/null @@ -1,279 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showServiceExceptionAlertAndWait; -import static at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.Helper.showValidationErrorAlertAndWait; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.RegistrationService; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.VehicleService; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import java.io.IOException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.fxml.FXML; -import javafx.geometry.Insets; -import javafx.scene.Node; -import javafx.scene.control.ChoiceBox; -import javafx.scene.control.Label; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextField; -import javafx.scene.input.KeyEvent; -import javafx.scene.input.MouseButton; -import javafx.scene.layout.GridPane; -import javafx.scene.layout.VBox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class RegistrationWindowController { - - private static final Logger LOG = LoggerFactory.getLogger(RegistrationWindowController.class); - - private final EmployeeService employeeService; - private final VehicleService vehicleService; - private final RegistrationService registrationService; - private final CreateOperationController createOperationController; - private final SpringFXMLLoader fxmlLoader; - - @FXML private GridPane root; - @FXML private VBox vbVehicles; - @FXML private ScrollPane listEmployee; - @FXML private ChoiceBox cbStart; - @FXML private ChoiceBox cbEnd; - @FXML private Label lVehicles; - @FXML private Label lEmployees; - @FXML private TextField tfVehicleSearch; - @FXML private TextField tfEmployeeSearch; - private EmployeeListController employeeListController; - - private Vehicle chosenVehicle; - private List chosenEmployees = new LinkedList<>(); - - public RegistrationWindowController( - EmployeeService employeeService, - VehicleService vehicleService, - CreateOperationController createOperationController, - RegistrationService registrationService, - SpringFXMLLoader fxmlLoader) { - this.employeeService = employeeService; - this.vehicleService = vehicleService; - this.createOperationController = createOperationController; - this.registrationService = registrationService; - this.fxmlLoader = fxmlLoader; - } - - @FXML - private void initialize() throws IOException { - employeeListController = EmployeeListController.createEmployeeListController(fxmlLoader); - employeeListController.setListItemMargins(new Insets(10, 6, 0, 6)); - // listEmployee. .getChildren().add(employeeListController.getRootElement()); - Node emplList = employeeListController.getRootElement(); - // emplList.(360); - listEmployee.setContent(emplList); - - ObservableList hours = - FXCollections.observableArrayList( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23); - cbStart.setItems(hours); - cbStart.setValue(0); - cbEnd.setItems(hours); - cbEnd.setValue(12); - - reset(); - } - - private void updateEmplList() { - employeeListController.deselectAllEmployees(); - - try { - Set employees = - employeeService - .list() - .stream() - .filter( - e -> - e.name() - .toLowerCase() - .contains( - tfEmployeeSearch - .getText() - .toLowerCase())) - .collect(Collectors.toCollection(HashSet::new)); - employeeListController.setData( - employees, - selection -> { - if (selection == null) { - return; - } else if (chosenEmployees.contains(selection)) { - chosenEmployees.remove(selection); - } else { - chosenEmployees.add(selection); - } - - StringBuilder text = new StringBuilder(); - boolean first = true; - for (Employee employee : chosenEmployees) { - if (!first) { - text.append(", "); - } - text.append(employee.name()); - first = false; - } - lEmployees.setText(text.toString()); - }, - contr -> contr.setSelected(chosenEmployees.contains(contr.getEmployee()))); - - employees.forEach( - e -> { - if (chosenEmployees.contains(e)) employeeListController.selectEmployee(e); - }); - } catch (ServiceException e) { - LOG.error("ServiceException in updateEmplList(). ", e); - showServiceExceptionAlertAndWait( - "Beim Auflisten des Personals ist ein Fehler aufgetreten."); - } - } - - private void updateVehList() { - vbVehicles.getChildren().clear(); - - try { - Set vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET)); - - boolean anyMatch = false; - - for (Vehicle vehicle : vehicles) { - if (!vehicle.name().toLowerCase().contains(tfVehicleSearch.getText().toLowerCase())) - continue; - - anyMatch = true; - - VehiclePaneController vp = VehiclePaneController.createVehiclePane(); - vp.setData(vehicle, false, false); - vbVehicles.getChildren().add(vp.getRootElement()); - - vp.getRootElement() - .setOnMouseClicked( - event -> { - if (event.getButton() == MouseButton.PRIMARY) { - chosenVehicle = vehicle; - lVehicles.setText(chosenVehicle.name()); - updateVehList(); - } - }); - if (chosenVehicle != null && chosenVehicle.id() == vehicle.id()) - vp.setSelected(true); - } - - if (!anyMatch) { - // Kind of ugly, but best way to get the size of a VehiclePane - VehiclePaneController vp = VehiclePaneController.createVehiclePane(); - vp.getRootElement().setVisible(false); - vbVehicles.getChildren().add(vp.getRootElement()); - } - } catch (ServiceException e) { - LOG.error("ServiceException in updateVehList(). ", e); - showServiceExceptionAlertAndWait( - "Beim Auflisten der Fahrzeuge ist ein Fehler aufgetreten"); - } catch (IOException e) { - LOG.error("IOException in updateVehList(). ", e); - showServiceExceptionAlertAndWait("Beim Laden der Fahrzeuge ist ein Fehler aufgetreten"); - } - } - - public void cancel() { - LOG.debug("Hyperlink \"schließen\" clicked"); - reset(); - this.setVisible(false); - createOperationController.setVisible(true); - } - - private void reset() { - chosenEmployees.clear(); - chosenVehicle = null; - tfEmployeeSearch.setText(""); - tfVehicleSearch.setText(""); - lEmployees.setText("-"); - lVehicles.setText("-"); - updateVehList(); - updateEmplList(); - } - - public void create() { - LOG.debug("Button \"ERSTELLEN\" clicked"); - - Set registrations = new HashSet<>(); - try { - if (chosenVehicle == null) { - throw new InvalidVehicleException("no Vehicle"); - } - for (Employee employee : chosenEmployees) { - registrations.add( - Registration.builder() - .id(chosenVehicle.id()) - .employee(employee) - .start( - LocalDateTime.of( - LocalDate.now(), - LocalTime.of(cbStart.getValue(), 0)) - .toInstant(OffsetDateTime.now().getOffset())) - .end( - LocalDateTime.of( - LocalDate.now(), - LocalTime.of(cbEnd.getValue(), 0)) - .toInstant(OffsetDateTime.now().getOffset())) - .build()); - } - - registrationService.add(chosenVehicle.id(), registrations); - chosenEmployees.clear(); - // ((Stage) lVehicles.getScene().getWindow()).close(); - this.setVisible(false); - createOperationController.setVisible(true); - reset(); - } catch (InvalidVehicleException e) { - LOG.debug("Validation of Vehicle in Registration failed."); - showValidationErrorAlertAndWait("Das spezifizierte Fahrzeug ist nicht gültig."); - } catch (ServiceException e) { - LOG.error("ServiceException in create(). ", e); - showServiceExceptionAlertAndWait( - "Beim Erstellen der Anmeldung ist ein Fehler aufgetreten."); - } catch (InvalidRegistrationException e) { - LOG.debug("Validation of Registration failed."); - showValidationErrorAlertAndWait( - "Die gewählte Kombination von Fahrzeug und Personal ist nicht gültig!"); - } - } - - public void setVisible(boolean b) { - root.setVisible(b); - reset(); - } - - public void tfVehicleSearch_TextChanged(KeyEvent keyEvent) { - updateVehList(); - } - - public void tfEmployeeSearch_TextChanged(KeyEvent keyEvent) { - updateEmplList(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/VehiclePaneController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/VehiclePaneController.java deleted file mode 100644 index b31228d..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/VehiclePaneController.java +++ /dev/null @@ -1,118 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status; -import java.io.IOException; -import java.time.Instant; -import java.util.List; -import java.util.Optional; -import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.scene.Node; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.text.Text; - -public class VehiclePaneController extends CustomListItemController { - - public static VehiclePaneController createVehiclePane() throws IOException { - FXMLLoader fxmlLoader = - new FXMLLoader(VehiclePaneController.class.getResource("/fxml/vehiclePane.fxml")); - Node root = fxmlLoader.load(); - VehiclePaneController result = fxmlLoader.getController(); - result.rootElement = root; - - return result; - } - - @FXML private Label txtStatus; - @FXML private Text txtType; - @FXML private Text txtNumber; - @FXML private ImageView ivNEF; - @FXML private Text txtNEF; - @FXML private ImageView ivQualification; - @FXML private Text txtQualification; - @FXML private Text txtRooftype; - @FXML private Button btnRequest; - - private Vehicle data; - - public Vehicle getData() { - return data; - } - - /** - * * Set the displayed data of this VehiclePane. - * - * @param vehicle The data to display. - * @param showStatusInfo If true, the highest qualification of the vehicle's active registration - * and the vehicle's status will be shown. - */ - public void setData(Vehicle vehicle, boolean showStatusInfo, boolean showRequestVehicle) { - txtType.setText(vehicle.type().name()); - String constrType = vehicle.constructionType().name(); - txtRooftype.setText( - constrType.substring(0, 1).toUpperCase() + constrType.substring(1).toLowerCase()); - txtNumber.setText("-" + vehicle.id()); - if (vehicle.hasNef()) { - ivNEF.setImage(new Image("images/NEF.png")); - txtNEF.setText("hat NEF-Halterung"); - } else { - ivNEF.setImage(new Image("images/NotNEF.png")); - txtNEF.setText("keine NEF-Halterung"); - } - - if (showRequestVehicle) { - btnRequest.setVisible(true); - btnRequest.setManaged(true); - } else { - btnRequest.setVisible(false); - btnRequest.setManaged(false); - } - - if (showStatusInfo) { - txtStatus.setText(vehicle.status().name()); - if (vehicle.status() == Status.FREI_FUNK || vehicle.status() == Status.FREI_WACHE) { - txtStatus.getStyleClass().add("bg-status-green"); - } else { - txtStatus.getStyleClass().add("bg-status-orange"); - } - - Instant now = Instant.now(); - List regs = vehicle.registrations(); - - if (regs == null) { - return; - } - - Optional edu = - regs.stream() - .filter(reg -> reg.start().isBefore(now) && reg.end().isAfter(now)) - .map(reg -> reg.employee().educationLevel()) - .max(EducationLevel::compareTo); - - if (!edu.isPresent()) { - return; - } - - txtQualification.setText(edu.get().name()); - } else { - txtQualification.setVisible(false); - txtQualification.setManaged(false); - ivQualification.setVisible(false); - ivQualification.setManaged(false); - - txtStatus.setVisible(false); - } - - this.data = vehicle; - } - - public Button getBtnRequest() { - return btnRequest; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDAO.java deleted file mode 100644 index 539a8e5..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDAO.java +++ /dev/null @@ -1,44 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import java.util.Set; - -public interface EmployeeDAO { - - /** - * Persist the given employee. - * - * @param employee that should be stored - * @return the id that was assigned - * @throws PersistenceException if the employee could not be persisted - */ - long add(Employee employee) throws PersistenceException; - - /** - * Update the given employee. - * - * @param employee that should be updated - * @throws ElementNotFoundException if no employee with the given id exists - * @throws PersistenceException if the employee could not be updated - */ - void update(Employee employee) throws ElementNotFoundException, PersistenceException; - - /** - * Get all stored employees. - * - * @return list containing all stored employees - * @throws PersistenceException if loading the stored employees failed - */ - Set list() throws PersistenceException; - - /** - * Remove employee with the given id from the store. - * - * @param id of the employee that should be removed - * @throws ElementNotFoundException if no employee with the given id exists - * @throws PersistenceException if the employee could not be removed - */ - void remove(long id) throws ElementNotFoundException, PersistenceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDAO.java deleted file mode 100644 index 1d8286b..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDAO.java +++ /dev/null @@ -1,144 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.time.LocalDate; -import java.util.HashSet; -import java.util.Set; -import org.springframework.stereotype.Repository; - -@Repository -public class EmployeeDatabaseDAO implements EmployeeDAO { - - private JDBCConnectionManager jdbcConnectionManager; - - public EmployeeDatabaseDAO(JDBCConnectionManager jdbcConnectionManager) { - this.jdbcConnectionManager = jdbcConnectionManager; - } - - private long createEmployeeVersion(Connection con, Employee e) - throws PersistenceException, SQLException { - String sql = - "INSERT INTO EmployeeVersion(name, birthday, educationLevel, isDriver, isPilot) " - + "VALUES(?, ?, ?, ?, ?)"; - - try (PreparedStatement pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { - pstmt.setString(1, e.name()); - pstmt.setObject(2, e.birthday()); - pstmt.setInt(3, e.educationLevel().ordinal()); - pstmt.setBoolean(4, e.isDriver()); - pstmt.setBoolean(5, e.isPilot()); - pstmt.executeUpdate(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - if (!rs.next()) throw new PersistenceException("Failed to insert EmployeeVersion"); - - return rs.getLong(1); - } - } - } - - @Override - public long add(Employee employee) throws PersistenceException { - String sql = "INSERT INTO Employee(version) VALUES(?)"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - - long versionId = createEmployeeVersion(con, employee); - - try (PreparedStatement pstmt = - con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { - pstmt.setLong(1, versionId); - pstmt.executeUpdate(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - if (!rs.next()) { - con.rollback(); - throw new PersistenceException("Failed to insert Employee"); - } - - con.commit(); - return rs.getLong(1); - } - } - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public void update(Employee employee) throws ElementNotFoundException, PersistenceException { - String sql = "UPDATE Employee SET version = ? WHERE id = ?"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - - long versionId = createEmployeeVersion(con, employee); - - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setLong(1, versionId); - pstmt.setLong(2, employee.id()); - - if (pstmt.executeUpdate() != 1) { - con.rollback(); - throw new ElementNotFoundException("No such employeeId exists"); - } - } - - con.commit(); - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public Set list() throws PersistenceException { - String sql = - "SELECT emp.id, v.name, v.birthday, v.educationLevel, v.isDriver, v.isPilot " - + "FROM employee emp " - + "JOIN EmployeeVersion v ON v.id = emp.version"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - Set employees = new HashSet<>(); - - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - try (ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - employees.add( - Employee.builder() - .id(rs.getLong(1)) - .name(rs.getString(2)) - .birthday(rs.getObject(3, LocalDate.class)) - .educationLevel(EducationLevel.valueOf(rs.getString(4))) - .isDriver(rs.getBoolean(5)) - .isPilot(rs.getBoolean(6)) - .build()); - } - } - } - - return employees; - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - @Override - public void remove(long id) throws ElementNotFoundException, PersistenceException { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDAO.java deleted file mode 100644 index d82f768..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDAO.java +++ /dev/null @@ -1,48 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import java.util.EnumSet; -import java.util.Set; - -public interface OperationDAO { - - /** - * Persist the given operation. - * - * @param operation that should be stored - * @return the id that was assigned - * @throws PersistenceException if the operation could not be persisted - */ - long add(Operation operation) throws PersistenceException; - - /** - * Update the given operation. - * - * @param operation that should be updated - * @throws ElementNotFoundException if no operation with the given id exists - * @throws PersistenceException if the operation could not be updated - */ - void update(Operation operation) throws ElementNotFoundException, PersistenceException; - - /** - * Returns the operation with the given id. - * - * @param operationId id of the operation that should be returned - * @return operation with the given id - * @throws ElementNotFoundException if no operation with the given id exists - * @throws PersistenceException if the operation could not be loaded - */ - Operation get(long operationId) throws ElementNotFoundException, PersistenceException; - - /** - * Get all stored operations with matching status. - * - * @param statuses set containing all statuses that should be matched - * @return list containing all matched operations - * @throws PersistenceException if loading the stored operations failed - */ - Set list(EnumSet statuses) throws PersistenceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDatabaseDAO.java deleted file mode 100644 index 0b6ce08..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDatabaseDAO.java +++ /dev/null @@ -1,221 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Severity; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Collectors; -import org.springframework.lang.NonNull; -import org.springframework.stereotype.Repository; - -@Repository -public class OperationDatabaseDAO implements OperationDAO { - - private JDBCConnectionManager jdbcConnectionManager; - private VehicleDAO vehicleDAO; - - public OperationDatabaseDAO( - JDBCConnectionManager jdbcConnectionManager, VehicleDAO vehicleDAO) { - this.jdbcConnectionManager = jdbcConnectionManager; - this.vehicleDAO = vehicleDAO; - } - - @Override - public long add(@NonNull Operation o) throws PersistenceException { - String sql = - "INSERT INTO Operation(opCode, severity, created, destination, additionalInfo," - + " status) VALUES (?, ?, ?, ?, ?, ?)"; - String sql2 = "INSERT INTO VehicleOperation(vehicleId, operationId) VALUES (?, ?)"; - long operationId; - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setString(1, o.opCode()); - pstmt.setInt(2, o.severity().ordinal()); - pstmt.setObject(3, OffsetDateTime.ofInstant(o.created(), ZoneId.systemDefault())); - pstmt.setString(4, o.destination()); - pstmt.setString(5, o.additionalInfo()); - pstmt.setInt(6, o.status().ordinal()); - pstmt.executeUpdate(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - if (!rs.next()) throw new PersistenceException("Failed to persist operation"); - - operationId = rs.getLong(1); - } - } - - try (PreparedStatement pstmt = con.prepareStatement(sql2)) { - pstmt.setLong(2, operationId); - - for (long id : (Iterable) o.vehicles().stream().map(Vehicle::id)::iterator) { - pstmt.setLong(1, id); - pstmt.addBatch(); - } - - pstmt.executeBatch(); - } - con.commit(); - return operationId; - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public void update(@NonNull Operation o) throws ElementNotFoundException, PersistenceException { - // Note this will, by design, not update created - String sql = - "UPDATE Operation SET opCode = ?, severity = ?, destination = ?," - + " additionalInfo = ?, status = ? WHERE id = ?"; - String sql2 = "DELETE FROM VehicleOperation WHERE operationId = ?"; - String sql3 = "INSERT INTO VehicleOperation(vehicleId, operationId) VALUES (?, ?)"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setString(1, o.opCode()); - pstmt.setInt(2, o.severity().ordinal()); - pstmt.setString(3, o.destination()); - pstmt.setString(4, o.additionalInfo()); - pstmt.setInt(5, o.status().ordinal()); - pstmt.setLong(6, o.id()); - - if (pstmt.executeUpdate() != 1) - throw new ElementNotFoundException("No such operationId exists"); - } - - try (PreparedStatement pstmt = con.prepareStatement(sql2)) { - pstmt.setLong(1, o.id()); - pstmt.executeUpdate(); - } - - try (PreparedStatement pstmt = con.prepareStatement(sql3)) { - pstmt.setLong(2, o.id()); - - for (long id : (Iterable) o.vehicles().stream().map(Vehicle::id)::iterator) { - pstmt.setLong(1, id); - pstmt.addBatch(); - } - - pstmt.executeBatch(); - } - con.commit(); - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public Operation get(long operationId) throws ElementNotFoundException, PersistenceException { - String sql = "Select * from operation where id = ?"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setLong(1, operationId); - pstmt.execute(); - - try (ResultSet rs = pstmt.getResultSet()) { - if (!rs.next()) - throw new ElementNotFoundException("No such element could be found"); - - return operationFromRS(rs); - } - } - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - @Override - public Set list(EnumSet statuses) throws PersistenceException { - // This hack exists because H2 currently has a bug that prevents IN (?) with an array of - // ids, i.e. pstmt.setArray(1, con.createArrayOf("INT", intarray) from working. See - // commented code below. - - // SELECT * FROM Operation WHERE status IN ('COMPLETED', 'CANCELLED') is BUGGED on H2! - // for this reason we use the ordinal values instead - String str = - statuses.stream() - .map(e -> Integer.toString(e.ordinal())) - .collect(Collectors.joining(",")); - - String sql = "SELECT * FROM Operation WHERE status IN (" + str + ")"; - Set operations = new HashSet<>(); - - try { - Connection con = jdbcConnectionManager.getConnection(); - - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - // Object[] arr = statuses.stream().map(Enum::ordinal).toArray(); - // pstmt.setArray(1, con.createArrayOf("INT", arr)); - - try (ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) operations.add(operationFromRS(rs)); - } - } - - return operations; - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - private Operation operationFromRS(ResultSet rs) throws PersistenceException, SQLException { - Long operationId = rs.getLong("id"); - - return Operation.builder() - .id(operationId) - .opCode(rs.getString("opCode")) - .severity(Severity.valueOf(rs.getString("severity"))) - .status(Status.valueOf(rs.getString("status"))) - .vehicles(getVehiclesFromOperationId(operationId)) - .created((rs.getObject("created", OffsetDateTime.class)).toInstant()) - .destination(rs.getString("destination")) - .additionalInfo(rs.getString("additionalInfo")) - .build(); - } - - private Set getVehiclesFromOperationId(long operationId) throws PersistenceException { - String sql = "SELECT vehicleId FROM VehicleOperation WHERE operationId = ?"; - Set vehicles = new HashSet<>(); - - try { - Connection con = jdbcConnectionManager.getConnection(); - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setLong(1, operationId); - pstmt.execute(); - - try (ResultSet rs = pstmt.getResultSet()) { - while (rs.next()) { - vehicles.add(vehicleDAO.get(rs.getLong("vehicleId"))); - } - } - } - } catch (SQLException e) { - throw new PersistenceException(e); - } catch (ElementNotFoundException e) { - throw new PersistenceException("VehicleOperation contained nonexistent vehicle", e); - } - - return vehicles; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDAO.java deleted file mode 100644 index 36b6f1b..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDAO.java +++ /dev/null @@ -1,28 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import java.util.Set; - -public interface RegistrationDAO { - - /** - * Persist the given registration. - * - * @param vehicleId the id of the target vehicle - * @param registrations that should be stored - * @return a list of the ids that were assigned - * @throws PersistenceException if the registration could not be persisted - */ - Set add(long vehicleId, Set registrations) throws PersistenceException; - - /** - * Make registration with the given id inactive. - * - * @param id of the registration that should be made inactive - * @throws ElementNotFoundException if no registration with the given id exists - * @throws PersistenceException if the registration could not be made inactive - */ - void remove(long id) throws ElementNotFoundException, PersistenceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAO.java deleted file mode 100644 index 9f7ac84..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAO.java +++ /dev/null @@ -1,130 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - -@Repository -public class RegistrationDatabaseDAO implements RegistrationDAO { - - private JDBCConnectionManager jdbcConnectionManager; - private EmployeeDAO employeePersistence; - - @Autowired - public RegistrationDatabaseDAO( - JDBCConnectionManager jdbcConnectionManager, EmployeeDAO employeePersistence) { - this.jdbcConnectionManager = jdbcConnectionManager; - this.employeePersistence = employeePersistence; - } - - @Override - public Set add(long vehicleId, Set registrations) - throws PersistenceException { - String sql = - "INSERT INTO Registration (vehicleId, employeeId, start, end, active) VALUES (?,?,?,?,?)"; - String sql2 = "UPDATE Vehicle SET status = 'FREI_WACHE' WHERE id = ?;"; - - Set vehicleIds = new HashSet<>(); - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - - try (PreparedStatement pstmt = - con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { - pstmt.setLong(1, vehicleId); - - for (Registration r : registrations) { - pstmt.setLong(2, r.employee().id()); - pstmt.setObject(3, OffsetDateTime.ofInstant(r.start(), ZoneId.systemDefault())); - pstmt.setObject(4, OffsetDateTime.ofInstant(r.end(), ZoneId.systemDefault())); - pstmt.setBoolean(5, true); - pstmt.addBatch(); - } - - pstmt.executeBatch(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - while (rs.next()) vehicleIds.add(rs.getLong(1)); - } - } - - try (PreparedStatement pstmt = con.prepareStatement(sql2)) { - pstmt.setLong(1, vehicleId); - if (pstmt.executeUpdate() != 1) { - con.rollback(); - throw new PersistenceException("Failed to persist registration"); - } - } - - con.commit(); - return vehicleIds; - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public void remove(long id) throws ElementNotFoundException, PersistenceException { - throw new UnsupportedOperationException(); - } - - protected List list(long vehicleId) throws PersistenceException { - String sql = "SELECT * FROM Registration WHERE vehicleId = ?"; - - List registrationList = new ArrayList<>(); - try { - Connection con = jdbcConnectionManager.getConnection(); - - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setLong(1, vehicleId); - - try (ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - long employeeId = rs.getLong("employeeId"); - // TODO: replace the following with employeePersistence.get once implemented - Employee emp = - employeePersistence - .list() - .stream() - .filter(employee -> employee.id() == employeeId) - .findAny() - .orElse(null); - Registration registration = - Registration.builder() - .id(rs.getLong("id")) - .start( - (rs.getObject("start", OffsetDateTime.class)) - .toInstant()) - .end( - (rs.getObject("end", OffsetDateTime.class)) - .toInstant()) - .employee(emp) - .build(); - registrationList.add(registration); - } - } - } - - return registrationList; - } catch (SQLException e) { - throw new PersistenceException(e); - } - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDAO.java deleted file mode 100644 index 5782fd9..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDAO.java +++ /dev/null @@ -1,54 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import java.util.Set; - -public interface VehicleDAO { - - /** - * Persist the given vehicle. - * - * @param vehicle that should be stored - * @return the id that was assigned - * @throws PersistenceException if the vehicle could not be persisted - */ - long add(Vehicle vehicle) throws PersistenceException; - - /** - * Update the given vehicle. - * - * @param vehicle that should be updated - * @throws ElementNotFoundException if no vehicle with the given id exists - * @throws PersistenceException if the vehicle could not be updated - */ - void update(Vehicle vehicle) throws ElementNotFoundException, PersistenceException; - - /** - * Get all stored vehicles. - * - * @return list containing all stored vehicles - * @throws PersistenceException if loading the stored vehicles failed - */ - Set list() throws PersistenceException; - - /** - * Returns the vehicle with the given id. - * - * @param vehicleId id of the vehicle that should be returned - * @return vehicle with the given id - * @throws ElementNotFoundException if no vehicle with the given id exists - * @throws PersistenceException if the vehicle could not be loaded - */ - Vehicle get(long vehicleId) throws ElementNotFoundException, PersistenceException; - - /** - * Remove vehicle with the given id from the store. - * - * @param id of the vehicle that should be removed - * @throws ElementNotFoundException if no vehicle with the given id exists - * @throws PersistenceException if the vehicle could not be removed - */ - void remove(long id) throws ElementNotFoundException, PersistenceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDAO.java deleted file mode 100644 index fcae6d3..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDAO.java +++ /dev/null @@ -1,211 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.ConstructionType; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.VehicleType; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.HashSet; -import java.util.Set; -import org.springframework.stereotype.Repository; - -@Repository -public class VehicleDatabaseDAO implements VehicleDAO { - - private final JDBCConnectionManager jdbcConnectionManager; - private RegistrationDatabaseDAO registrationDatabaseDao; - - public VehicleDatabaseDAO( - JDBCConnectionManager j, RegistrationDatabaseDAO registrationDatabaseDao) { - jdbcConnectionManager = j; - this.registrationDatabaseDao = registrationDatabaseDao; - } - - @Override - public long add(Vehicle v) throws PersistenceException { - String sql = - "INSERT INTO VehicleVersion (name,hasNef,constructionType,type) VALUES (?,?,?,?)"; - String sql2 = "INSERT INTO Vehicle (version,status) VALUES (?,?)"; - String sql3 = "UPDATE VehicleVersion SET name=? WHERE id=?"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - String name = ""; - long version, id; - - try (PreparedStatement pstmt = - con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { - pstmt.setString(1, name); - pstmt.setBoolean(2, v.hasNef()); - pstmt.setInt(3, v.constructionType().ordinal()); - pstmt.setString(4, v.type().name()); - pstmt.executeUpdate(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - if (!rs.next()) - throw new PersistenceException("Failed to insert into VehicleVersion"); - - version = rs.getLong(1); - } - } - - try (PreparedStatement pstmt = - con.prepareStatement(sql2, Statement.RETURN_GENERATED_KEYS)) { - pstmt.setLong(1, version); - pstmt.setInt(2, Status.ABGEMELDET.ordinal()); - pstmt.executeUpdate(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - if (!rs.next()) { - con.rollback(); - throw new PersistenceException("Failed to insert into Vehicle"); - } - - id = rs.getLong(1); - } - - name = v.type().name() + "-" + id; - } - - try (PreparedStatement pstmt = con.prepareStatement(sql3)) { - pstmt.setString(1, name); - pstmt.setLong(2, version); - - if (pstmt.executeUpdate() != 1) { - con.rollback(); - throw new PersistenceException("Failed to update VehicleVersion"); - } - } - - con.commit(); - return id; - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public void update(Vehicle v) throws ElementNotFoundException, PersistenceException { - String sql = "SELECT version FROM Vehicle WHERE id = ?"; - String sql2 = - "MERGE INTO VehicleVersion(name, constructionType, type, hasNef)" - + " KEY(name, constructionType, type, hasNef) VALUES(?, ?, ?, ?)"; - String sql3 = "UPDATE Vehicle SET version = ?, status = ? WHERE id = ?"; - - long versionId; - - try { - Connection con = jdbcConnectionManager.getConnection(); - con.setAutoCommit(false); - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setLong(1, v.id()); - - try (ResultSet rs = pstmt.executeQuery()) { - if (!rs.next()) throw new ElementNotFoundException("No such vehicleId exists"); - - versionId = rs.getLong(1); - } - } - - try (PreparedStatement pstmt = - con.prepareStatement(sql2, Statement.RETURN_GENERATED_KEYS)) { - pstmt.setString(1, v.type().name() + "-" + v.id()); - pstmt.setString(2, v.constructionType().name()); - pstmt.setString(3, v.type().name()); - pstmt.setBoolean(4, v.hasNef()); - pstmt.executeUpdate(); - - try (ResultSet rs = pstmt.getGeneratedKeys()) { - if (rs.next()) { - // version changed, update it - versionId = rs.getLong(1); - } - } - } - - try (PreparedStatement pstmt = con.prepareStatement(sql3)) { - pstmt.setLong(1, versionId); - pstmt.setString(2, v.status().name()); - pstmt.setLong(3, v.id()); - pstmt.executeUpdate(); - } - - con.commit(); - } catch (SQLException e) { - jdbcConnectionManager.rollbackConnection(); - throw new PersistenceException(e); - } - } - - @Override - public Set list() throws PersistenceException { - Set result = new HashSet<>(); - - String sql = - "Select * from VehicleVersion, Vehicle where VehicleVersion.id=Vehicle.version"; - - try (PreparedStatement pstmt = - jdbcConnectionManager.getConnection().prepareStatement(sql)) { - pstmt.executeQuery(); - try (ResultSet rs = pstmt.getResultSet()) { - while (rs.next()) { - result.add(vehicleFromRS(rs)); - } - } - } catch (SQLException e) { - throw new PersistenceException(e); - } - return result; - } - - @Override - public Vehicle get(long id) throws ElementNotFoundException, PersistenceException { - String sql = - "SELECT a.id, b.name, b.constructionType, b.type, a.status, b.hasNef" - + " FROM Vehicle a" - + " INNER JOIN VehicleVersion b" - + " ON version = b.id" - + " WHERE a.id = ?"; - - try { - Connection con = jdbcConnectionManager.getConnection(); - try (PreparedStatement pstmt = con.prepareStatement(sql)) { - pstmt.setLong(1, id); - - try (ResultSet rs = pstmt.executeQuery()) { - if (!rs.first()) throw new ElementNotFoundException("No such vehicle exists"); - - return vehicleFromRS(rs); - } - } - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - @Override - public void remove(long id) throws ElementNotFoundException, PersistenceException { - throw new UnsupportedOperationException(); - } - - private Vehicle vehicleFromRS(ResultSet rs) throws SQLException, PersistenceException { - return Vehicle.builder() - .id(rs.getLong("Vehicle.id")) - .name(rs.getString("name")) - .constructionType(ConstructionType.values()[rs.getInt("constructionType")]) - .type(VehicleType.valueOf(rs.getString("type"))) - .status(Status.values()[rs.getInt("status")]) - .hasNef(rs.getBoolean("hasNef")) - .registrations(registrationDatabaseDao.list(rs.getLong("id"))) - .build(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Employee.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Employee.java deleted file mode 100644 index 583bf5b..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Employee.java +++ /dev/null @@ -1,51 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; - -import com.google.auto.value.AutoValue; -import java.time.LocalDate; - -@AutoValue -public abstract class Employee { - public enum EducationLevel { - RS, - NFS, - NKV, - NKA, - NKI, - NA - } - - public abstract long id(); - - public abstract String name(); - - public abstract LocalDate birthday(); - - public abstract EducationLevel educationLevel(); - - public abstract boolean isDriver(); - - public abstract boolean isPilot(); - - public static Builder builder() { - return new AutoValue_Employee.Builder().id(0); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder id(long id); - - public abstract Builder name(String name); - - public abstract Builder birthday(LocalDate birthday); - - public abstract Builder educationLevel(EducationLevel educationLevel); - - public abstract Builder isDriver(boolean isDriver); - - public abstract Builder isPilot(boolean isPilot); - - public abstract Employee build(); - } - - public abstract Builder toBuilder(); -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java deleted file mode 100644 index 36d8003..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java +++ /dev/null @@ -1,23 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; - -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; - -public class EmployeeValidator { - - public static boolean validate(Employee employee) throws InvalidEmployeeException { - - if (employee.name() == null || employee.name().trim().length() == 0) { - throw new InvalidEmployeeException("Name darf nicht leer sein!"); - } - - if (employee.birthday() == null) { - throw new InvalidEmployeeException("Geburtsdatum darf nicht leer sein!"); - } - - if (employee.educationLevel() == null) { - throw new InvalidEmployeeException("Ausbildungsgrad darf nicht leer sein!"); - } - - return true; - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Operation.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Operation.java deleted file mode 100644 index 3a97dc7..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Operation.java +++ /dev/null @@ -1,70 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; - -import com.google.auto.value.AutoValue; -import java.time.Instant; -import java.util.Set; -import javax.annotation.Nullable; - -@AutoValue -public abstract class Operation { - public enum Severity { - A, - B, - C, - D, - E, - O, - } - - public enum Status { - ACTIVE, - COMPLETED, - CANCELLED, - } - - public abstract long id(); - - public abstract String opCode(); - - @Nullable - public abstract Severity severity(); - - public abstract Status status(); - - public abstract Set vehicles(); - - @Nullable - public abstract Instant created(); - - public abstract String destination(); - - @Nullable - public abstract String additionalInfo(); - - public static Builder builder() { - return new AutoValue_Operation.Builder().id(0); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder id(long id); - - public abstract Builder opCode(String opCode); - - public abstract Builder severity(Severity severity); - - public abstract Builder status(Status status); - - public abstract Builder vehicles(Set vehicles); - - public abstract Builder created(Instant created); - - public abstract Builder destination(String destination); - - public abstract Builder additionalInfo(String additionalInfo); - - public abstract Operation build(); - } - - public abstract Builder toBuilder(); -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Registration.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Registration.java deleted file mode 100644 index 8551266..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Registration.java +++ /dev/null @@ -1,34 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; - -import com.google.auto.value.AutoValue; -import java.time.Instant; - -@AutoValue -public abstract class Registration { - public abstract long id(); - - public abstract Instant start(); - - public abstract Instant end(); - - public abstract Employee employee(); - - public static Builder builder() { - return new AutoValue_Registration.Builder().id(0); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder id(long id); - - public abstract Builder start(Instant start); - - public abstract Builder end(Instant end); - - public abstract Builder employee(Employee employee); - - public abstract Registration build(); - } - - public abstract Builder toBuilder(); -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java deleted file mode 100644 index 3456534..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java +++ /dev/null @@ -1,174 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.VehicleType; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -public class RegistrationValidator { - - private RegistrationValidator() {} - - public static void validate(Vehicle vehicle, Set registrations) - throws InvalidVehicleException, InvalidRegistrationException { - /* - Vehicles and Employees are assumed to be valid. - They have been checked at creation, and for them to be checked again, access to - VehicleValidator and EmployeeValidator are needed, which are not available at this time. - */ - /* - The method used here goes as follows: All given employees are inspected in regards to their - qualifications, and added to the appropriate lists of the roles they could fill. - For example, an NFS, who is also a driver, would be added to the lists driverIds, nfsIds - and rsIds (because an NFS can always substitute an RS). - Afterwards, the number of people is checked according to the chosen vehicle type, and if - the number is okay, the program tries to find a valid combination of roles for the vehicle. - For example, for an RTW, first a driver is chosen, their ID marked as found in the aptly - titled HashMap, and then for the second RS, the list of RS is checked, excluding the chosen - driver. If no other valid RS is found, the next possible driver is chosen, and so on. If no - valid combination is found, an InvalidRegistrationException is thrown. - */ - List pilotIds = new LinkedList<>(); - List driverIds = new LinkedList<>(); - List naIds = new LinkedList<>(); - List nfsIds = new LinkedList<>(); - List rsIds = new LinkedList<>(); - HashMap found = - new HashMap<>(); // needed later in DFS, checks that no person is chosen twice - int total = 0; - for (Registration registration : registrations) { - total++; - if (found.put(registration.employee().id(), false) != null) { - throw new InvalidRegistrationException( - "Person mit der ID: " - + registration.employee().id() - + " wurde mehrmals hinzugefügt!"); - } - if (registration.employee().isPilot()) { - pilotIds.add(registration.employee().id()); - } - if (registration.employee().isDriver()) { - driverIds.add(registration.employee().id()); - } - if (registration.employee().educationLevel() == EducationLevel.NA) { - naIds.add(registration.employee().id()); - nfsIds.add(registration.employee().id()); - rsIds.add(registration.employee().id()); - } else if (isNFS(registration.employee())) { - nfsIds.add(registration.employee().id()); - rsIds.add(registration.employee().id()); - } else { // only RS left - rsIds.add(registration.employee().id()); - } - } - if (total <= 0) { - throw new InvalidRegistrationException("Kein Personal ausgewählt!"); - } - if (vehicle.type() == VehicleType.NAH) { - /* - NAH - 1 Pilot - 1 NFS - 1 NA - 3-4 Personen - */ - if (total < 3) { - throw new InvalidRegistrationException("Zu wenig Personal für NAH!"); - } else if (total > 4) { - throw new InvalidRegistrationException("Zu viel Personal für NAH!"); - } - for (long pilot_id : pilotIds) { - found.put(pilot_id, true); - for (long na_id : naIds) { - if (found.get(na_id)) continue; - found.put(na_id, true); - for (long nfs_id : nfsIds) { - if (found.get(nfs_id)) continue; - return; - } - found.put(na_id, false); - } - found.put(pilot_id, false); - } - throw new InvalidRegistrationException( - "Keine gültige Kombination von Personen für NAH!"); - } else if (vehicle.type() == VehicleType.NEF) { - /* - NEF - 1 Driver (has to be NFS) - 1 NA - */ - if (total < 2) { - throw new InvalidRegistrationException("Zu wenig Personal für NEF!"); - } else if (total > 3) { - throw new InvalidRegistrationException("Zu viel Personal für NEF!"); - } - for (long driver_id : driverIds) { - if (!nfsIds.contains(driver_id)) - continue; // if possible driver is not NFS, skip him - found.put(driver_id, true); - for (long na_id : naIds) { - if (found.get(na_id)) continue; - return; - } - found.put(driver_id, false); - } - throw new InvalidRegistrationException( - "Keine gültige Kombination von Personen für NEF!"); - } else if (vehicle.type() == VehicleType.BKTW) { - /* - BKTW - 1 Driver - */ - if (total > 3) { - throw new InvalidRegistrationException("Zu viel Personal für BKTW!"); - } - if (!driverIds.isEmpty()) { - return; - } - throw new InvalidRegistrationException("Kein Fahrer gefunden für BKTW!"); - } else { // KTW or RTW, both have the same requirements - /* - RTW/KTW - 1 Driver - 1 RS - */ - if (total < 2) { - throw new InvalidRegistrationException( - "Zu wenig Personal für " + vehicle.type().name() + "!"); - } else if (total > 4) { - throw new InvalidRegistrationException( - "Zu viel Persoanl für " + vehicle.type().name() + "!"); - } - for (long driver_id : driverIds) { // driver includes rs - found.put(driver_id, true); - for (long rs_id : rsIds) { - if (found.get(rs_id)) continue; - return; - } - } - throw new InvalidRegistrationException( - "Keine gültige Kombination von Personen für " + vehicle.type().name() + "!"); - } - } - - private static boolean isNFS(Employee employee) { - EducationLevel educationLevel = employee.educationLevel(); - switch (educationLevel) { - case NFS: - return true; - case NKA: - return true; - case NKI: - return true; - case NKV: - return true; - default: - return false; - } - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Vehicle.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Vehicle.java deleted file mode 100644 index e81db0b..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/Vehicle.java +++ /dev/null @@ -1,73 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; - -import com.google.auto.value.AutoValue; -import java.util.List; -import javax.annotation.Nullable; - -@AutoValue -public abstract class Vehicle { - public enum ConstructionType { - NORMAL, - HOCHDACH, - MITTELHOCHDACH, - } - - public enum VehicleType { - BKTW, - KTW_B, - KTW, - RTW, - NEF, - NAH, - } - - public enum Status { - ABGEMELDET, - FREI_WACHE, - FREI_FUNK, - ZUM_BERUFUNGSORT, - AM_BERUFUNGSORT, - ZUM_ZIELORT, - AM_ZIELORT, - } - - public abstract long id(); - - public abstract String name(); - - public abstract ConstructionType constructionType(); - - public abstract VehicleType type(); - - public abstract Status status(); - - public abstract boolean hasNef(); - - @Nullable - public abstract List registrations(); - - public static Builder builder() { - return new AutoValue_Vehicle.Builder().id(0); - } - - @AutoValue.Builder - public abstract static class Builder { - public abstract Builder id(long id); - - public abstract Builder name(String name); - - public abstract Builder constructionType(ConstructionType constructionType); - - public abstract Builder type(VehicleType type); - - public abstract Builder status(Status status); - - public abstract Builder hasNef(boolean hasNef); - - public abstract Builder registrations(List registrations); - - public abstract Vehicle build(); - } - - public abstract Builder toBuilder(); -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeService.java deleted file mode 100644 index f7f8e71..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeService.java +++ /dev/null @@ -1,46 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.Set; - -public interface EmployeeService { - - /** - * Add given employee to the store. - * - * @param employee that should be added to the store - * @return the id that was assigned - * @throws InvalidEmployeeException if the employee is invalid - * @throws ServiceException if the employee could not be persisted - */ - long add(Employee employee) throws InvalidEmployeeException, ServiceException; - - /** - * Update the given employee. - * - * @param employee that should be updated - * @return the updated employee - * @throws InvalidEmployeeException if the employee is invalid - * @throws ServiceException if the updated employee could not be persisted - */ - Employee update(Employee employee) throws InvalidEmployeeException, ServiceException; - - /** - * Get all stored employees. - * - * @return list containing all stored employees - * @throws ServiceException if loading the stored employees failed - */ - Set list() throws ServiceException; - - /** - * Remove employee with the given id from the store. - * - * @param id of the employee that should be removed - * @throws InvalidEmployeeException if given employee id is invalid or does not exist - * @throws ServiceException if the employee could not be removed from the store - */ - void remove(long id) throws InvalidEmployeeException, ServiceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java deleted file mode 100644 index cf054c3..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java +++ /dev/null @@ -1,59 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.EmployeeDAO; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.EmployeeValidator; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.Set; -import org.springframework.stereotype.Service; - -@Service -public class EmployeeServiceImpl implements EmployeeService { - - private final EmployeeDAO employeePersistence; - - public EmployeeServiceImpl(EmployeeDAO employeePersistence) { - this.employeePersistence = employeePersistence; - } - - @Override - public long add(Employee employee) throws InvalidEmployeeException, ServiceException { - - EmployeeValidator.validate(employee); - try { - return employeePersistence.add(employee); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - } - - @Override - public Employee update(Employee employee) throws InvalidEmployeeException, ServiceException { - - EmployeeValidator.validate(employee); - try { - employeePersistence.update(employee); - return employee; - } catch (ElementNotFoundException | PersistenceException e) { - throw new ServiceException(e); - } - } - - @Override - public Set list() throws ServiceException { - - try { - return employeePersistence.list(); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - } - - @Override - public void remove(long id) throws InvalidEmployeeException, ServiceException { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationService.java deleted file mode 100644 index 4b7e630..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationService.java +++ /dev/null @@ -1,70 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.EnumSet; -import java.util.Set; -import java.util.SortedSet; - -public interface OperationService { - - /** - * Add given operation to the store. - * - * @param operation that should be added to the store - * @return the id that was assigned - * @throws InvalidOperationException if the operation is invalid - * @throws ServiceException if the operation could not be persisted - */ - long add(Operation operation) throws InvalidOperationException, ServiceException; - - /** - * Request new vehicles to the given operation. - * - * @param operationId id of the operation that the vehicles should be send to - * @param vehicleIds the ids of the vehicles that should be send to the given operation - * @throws InvalidOperationException if the operationId is invalid or does not exist - * @throws InvalidVehicleException if one of the vehicle ids is invalid or does not exist - * @throws ServiceException if the vehicles could not be loaded or the operation could not be - * persisted - */ - void requestVehicles(long operationId, Set vehicleIds) - throws InvalidOperationException, InvalidVehicleException, ServiceException; - - /** - * Completes the given operation with the specified status. - * - * @param operationId id of the operation that should be completed - * @param status of the completed operation, either {@link Status#COMPLETED} or {@link - * Status#CANCELLED} - * @throws InvalidOperationException if the operationId is invalid or does not exist - * @throws ServiceException if the operation could not be persisted - */ - void complete(long operationId, Status status) - throws InvalidOperationException, ServiceException; - - /** - * Get all available vehicles, sorted by how well they fit to the given opCode, starting with - * the best fitting. - * - * @param opCode the operation code that is used to determine the ranking - * @return a sorted list containing all available vehicles - * @throws InvalidOperationException if the opCode is invalid - * @throws ServiceException if loading the stored vehicles failed - */ - SortedSet rankVehicles(String opCode) - throws InvalidOperationException, ServiceException; - - /** - * Get all stored operations with matching status. - * - * @param statuses set containing all statuses that should be matched - * @return list containing all matched operations - * @throws ServiceException if loading the stored operations failed - */ - Set list(EnumSet statuses) throws ServiceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationServiceImpl.java deleted file mode 100644 index a83cf64..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/OperationServiceImpl.java +++ /dev/null @@ -1,286 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.OperationDAO; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.VehicleDAO; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Severity; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.Status; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.VehicleType; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.time.Instant; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -@Service -public class OperationServiceImpl implements OperationService { - - private static final Logger LOG = LoggerFactory.getLogger(OperationServiceImpl.class); - - private final OperationDAO operationDAO; - private final VehicleDAO vehicleDAO; - private final VehicleService vehicleService; - - public OperationServiceImpl( - OperationDAO operationDAO, VehicleDAO vehicleDAO, VehicleService vehicleService) { - this.operationDAO = operationDAO; - this.vehicleDAO = vehicleDAO; - this.vehicleService = vehicleService; - } - - @Override - public long add(Operation o) throws InvalidOperationException, ServiceException { - if (o.created() != null) { - throw new InvalidOperationException("Erstellungszeitpunkt darf nicht gesetzt sein"); - } - - if (o.severity() != null) { - throw new InvalidOperationException("Der Schweregrad darf nicht gesetzt sein"); - } - - if (o.id() != 0) { - throw new InvalidOperationException("Einsatz-ID muss 0 sein"); - } - - if (o.status() != Status.ACTIVE) - LOG.info("Status was set but will be overridden"); // TODO: nullable instead?? - - try { - for (long id : (Iterable) o.vehicles().stream().map(Vehicle::id)::iterator) { - Vehicle v = vehicleDAO.get(id); - VehicleServiceImpl.validateVehicle(v); - - if (v.status() != Vehicle.Status.FREI_FUNK - && v.status() != Vehicle.Status.FREI_WACHE) - throw new InvalidOperationException("Fahrzeug nicht verfügbar: " + v.status()); - } - - validateOperation(o); - - return operationDAO.add( - o.toBuilder() - .created(Instant.now()) - .severity(extractSeverityFromOpCode(o.opCode())) - .status(Status.ACTIVE) - .build()); - } catch (PersistenceException e) { - throw new ServiceException(e); - } catch (InvalidVehicleException e) { - // already logged as invalid vehicle - throw new InvalidOperationException("Enthaltenes Fahrzeug ist ungültig", e); - } catch (ElementNotFoundException e) { - throw new InvalidOperationException("Enthaltenes Fahrzeug existiert nicht", e); - } - } - - @Override - public void requestVehicles(long operationId, Set vehicleIds) - throws InvalidOperationException, InvalidVehicleException, ServiceException { - Set vs = new HashSet<>(); - - try { - if (operationId <= 0) { - throw new InvalidOperationException("Einsatz-ID ist ungültig"); - } - Operation o = operationDAO.get(operationId); - validateOperation(o); - - if (o.opCode().trim().isEmpty() - || extractSeverityFromOpCode(o.opCode()) != o.severity()) { - throw new InvalidOperationException("Einsatzcode ist ungültig"); - } - - if (o.status() != Status.ACTIVE) { - throw new InvalidOperationException("Einsatz ist ungültig"); - } - - if (o.created() == null) { - throw new InvalidOperationException("Erstellungszeitpunkt darf nicht leer sein"); - } - - for (Long id : vehicleIds) { - if (id <= 0) { - throw new InvalidVehicleException("Fahrzeug-ID ist ungültig"); - } - - try { - Vehicle v = vehicleDAO.get(id); - VehicleServiceImpl.validateVehicle(v); - if (v.status() != Vehicle.Status.FREI_FUNK - && v.status() != Vehicle.Status.FREI_WACHE) - throw new InvalidOperationException( - "Fahrzeug nicht verfügbar: " + v.status()); - - vs.add(v); - } catch (ElementNotFoundException e) { - throw new InvalidVehicleException("VehicleId ist invalid"); - } - } - - vs.addAll(o.vehicles()); - if (vs.equals(o.vehicles())) return; - - operationDAO.update(o.toBuilder().vehicles(vs).build()); - } catch (ElementNotFoundException e) { - throw new InvalidOperationException("Kein Einsatz mit dieser ID existiert"); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - } - - @Override - public void complete(long operationId, Status status) - throws InvalidOperationException, ServiceException { - try { - Operation o = operationDAO.get(operationId); - operationDAO.update(o.toBuilder().status(status).build()); - } catch (ElementNotFoundException e) { - throw new InvalidOperationException(e); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - } - - @Override - public SortedSet rankVehicles(String opCode) - throws InvalidOperationException, ServiceException { - Set vehicles = - vehicleService.list(EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET))); - - List> priorities = new ArrayList<>(); - Predicate ktw = v -> v.type() == VehicleType.KTW; - Predicate rtwNoNEF = v -> v.type() == VehicleType.RTW && !v.hasNef(); - Predicate rtwNEF = v -> v.type() == VehicleType.RTW && v.hasNef(); - Predicate nef = v -> v.type() == VehicleType.NEF; - Predicate nah = v -> v.type() == VehicleType.NAH; - - switch (extractSeverityFromOpCode(opCode)) { - case A: - // fallthrough - case B: - // fallthrough - case O: - priorities.add(ktw); - priorities.add(rtwNoNEF); - priorities.add(rtwNEF); - break; - case C: - priorities.add(rtwNEF); - priorities.add(rtwNoNEF); - priorities.add(ktw); - break; - case D: - priorities.add(rtwNEF); - priorities.add(nef); - priorities.add(nah); - priorities.add(rtwNoNEF); - priorities.add(ktw); - break; - case E: - priorities.add(nah); - priorities.add(nef); - priorities.add(rtwNEF); - priorities.add(rtwNoNEF); - priorities.add(ktw); - break; - } - - Comparator vehicleComparator = - (v1, v2) -> { - for (Predicate priority : priorities) { - if (priority.test(v1)) { - return -1; - } - if (priority.test(v2)) { - return +1; - } - } - return 0; - }; - - Supplier> supplier = () -> new TreeSet<>(vehicleComparator); - - return vehicles.stream().collect(Collectors.toCollection(supplier)); - } - - @Override - public Set list(EnumSet statuses) throws ServiceException { - try { - Set operations = operationDAO.list(statuses); - for (Operation o : operations) validateOperation(o); - - return operations; - } catch (PersistenceException e) { - throw new ServiceException(e); - } catch (InvalidOperationException e) { - // database returned invalid values - throw new ServiceException("DB returned invalid operation", e); - } - } - - private static void validateOperation(Operation o) throws InvalidOperationException { - if (o.vehicles().isEmpty()) { - throw new InvalidOperationException( - "Es muss mindestens ein Fahrzeug ausgewählt werden!"); - } - - for (Vehicle v : o.vehicles()) { - try { - VehicleServiceImpl.validateVehicle(v); - } catch (InvalidVehicleException e) { - throw new InvalidOperationException("Fahrzeug " + v.name() + " ist ungültig", e); - } - - // TODO: validate if NEF/RTW/NAH conditions? - } - - Instant created = o.created(); - if (created != null && created.isAfter(Instant.now())) { - throw new InvalidOperationException("Einsatz wurde in der Zukunft erstellt"); - } - - if (o.destination() == null || o.destination().trim().isEmpty()) { - throw new InvalidOperationException("Adresse darf nicht leer sein"); - } - - if (o.destination().length() > 100) { - throw new InvalidOperationException("Adresse darf 100 Zeichen nicht überschreiten"); - } - - if (o.additionalInfo() != null && o.additionalInfo().length() > 100) { - throw new InvalidOperationException("Anmerkung darf 100 Zeichen nicht überschreiten"); - } - } - - private static final Pattern opCodePattern = - Pattern.compile("(?:\\w{1,3}-\\d{0,2})([ABCDEO])(?:.*)"); - - private static Severity extractSeverityFromOpCode(String opCode) - throws InvalidOperationException { - Matcher m = opCodePattern.matcher(opCode); - - if (!m.matches()) { - throw new InvalidOperationException("Einsatzcode ist ungültig"); - } - - return Severity.valueOf(m.group(1)); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationService.java deleted file mode 100644 index b7d8eef..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationService.java +++ /dev/null @@ -1,32 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.Set; - -public interface RegistrationService { - - /** - * Register employee to a vehicle. - * - * @param vehicleId the id of the target vehicle - * @param registrations that should be added to the vehicle - * @return the list of ids that were assigned - * @throws InvalidVehicleException if the vehicleId is invalid or does not exist - * @throws InvalidRegistrationException if the registration is invalid - * @throws ServiceException if the registration could not be persisted - */ - Set add(long vehicleId, Set registrations) - throws InvalidVehicleException, InvalidRegistrationException, ServiceException; - - /** - * Remove given registration from the store. - * - * @param registrationId the id of the registration that should be removed - * @throws InvalidRegistrationException if the registration is invalid or does not exist - * @throws ServiceException if the registration could not be removed from the store - */ - void remove(long registrationId) throws InvalidRegistrationException, ServiceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImpl.java deleted file mode 100644 index 1d92644..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.RegistrationDAO; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.VehicleDAO; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.RegistrationValidator; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.Set; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class RegistrationServiceImpl implements RegistrationService { - - private final RegistrationDAO registrationDAO; - private final VehicleDAO vehicleDAO; - - @Autowired - public RegistrationServiceImpl(RegistrationDAO registrationDAO, VehicleDAO vehicleDAO) { - this.registrationDAO = registrationDAO; - this.vehicleDAO = vehicleDAO; - } - - @Override - public Set add(long vehicleId, Set registrations) - throws InvalidVehicleException, InvalidRegistrationException, ServiceException { - - if (vehicleId <= 0) throw new InvalidVehicleException("VehicleId invalid"); - - try { - Vehicle vehicle = vehicleDAO.get(vehicleId); - - RegistrationValidator.validate(vehicle, registrations); - - return registrationDAO.add(vehicle.id(), registrations); - } catch (PersistenceException e) { - throw new ServiceException(e); - } catch (ElementNotFoundException e) { - throw new InvalidVehicleException(e); - } - } - - @Override - public void remove(long registrationId) throws InvalidRegistrationException, ServiceException { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleService.java deleted file mode 100644 index fe09ca1..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleService.java +++ /dev/null @@ -1,49 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.EnumSet; -import java.util.Set; - -public interface VehicleService { - - /** - * Add given vehicle to the store. - * - * @param vehicle that should be added to the store - * @return the id that was assigned - * @throws InvalidVehicleException if the vehicle is invalid - * @throws ServiceException if the vehicle could not be persisted - */ - long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException; - - /** - * Update the given vehicle. - * - * @param vehicle that should be updated - * @return the updated vehicle - * @throws InvalidVehicleException if the vehicle is invalid - * @throws ServiceException if the updated vehicle could not be persisted - */ - Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException; - - /** - * Get all stored vehicles with matching status. - * - * @param statuses set containing all statuses that should be matched - * @return list containing all stored vehicles - * @throws ServiceException if loading the stored vehicles failed - */ - Set list(EnumSet statuses) throws ServiceException; - - /** - * Remove vehicle with the given id from the store. - * - * @param id of the vehicle that should be removed - * @throws InvalidVehicleException if given vehicle id is invalid or does not exist - * @throws ServiceException if the vehicle could not be removed from the store - */ - void remove(long id) throws InvalidVehicleException, ServiceException; -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java deleted file mode 100644 index 0bf4aa6..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java +++ /dev/null @@ -1,116 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.VehicleDAO; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.ConstructionType; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; -import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; -import java.util.EnumSet; -import java.util.Set; -import java.util.stream.Collectors; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - -@Service -public class VehicleServiceImpl implements VehicleService { - - private VehicleDAO vehiclePersistence; - - public VehicleServiceImpl(VehicleDAO vehiclePersistence) { - this.vehiclePersistence = vehiclePersistence; - } - - public long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException { - if (!CollectionUtils.isEmpty(vehicle.registrations())) { - throw new InvalidVehicleException( - "Fahrzeug kann nicht mit Anmeldungen erstellt werden"); - } - - validateVehicle(vehicle); - try { - vehiclePersistence.add(vehicle); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - return 0; - } - - public Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException { - validateVehicle(vehicle); - try { - vehiclePersistence.update(vehicle); - } catch (ElementNotFoundException e) { - throw new ServiceException("Element not found", e); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - return vehicle; - } - - protected static void validateVehicle(Vehicle vehicle) throws InvalidVehicleException { - switch (vehicle.type()) { - case RTW: - if (vehicle.constructionType() == ConstructionType.NORMAL) { - throw new InvalidVehicleException("RTW darf kein Normales Dach haben"); - } else if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { - throw new InvalidVehicleException("RTW darf kein Mittelhochdach haben"); - } - break; - case KTW: - if (vehicle.constructionType() == ConstructionType.NORMAL) { - throw new InvalidVehicleException("KTW darf kein Normales Dach haben"); - } - break; - case KTW_B: - if (vehicle.constructionType() == ConstructionType.NORMAL) { - throw new InvalidVehicleException("KTW-B darf kein Normales Dach haben"); - } - break; - case NEF: - if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { - throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben"); - } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) { - throw new InvalidVehicleException("NEF darf kein Hochdach haben"); - } - break; - case NAH: - if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { - throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben"); - } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) { - throw new InvalidVehicleException("NEF darf kein Hochdach haben"); - } - break; - case BKTW: - break; - default: - throw new IllegalStateException("BUG: invalid vehicle type" + vehicle.type()); - } - } - - @Override - public Set list(EnumSet statuses) throws ServiceException { - if (statuses == null) { - throw new ServiceException("Statuses may not be null"); - } - - Set vehicles; - - try { - vehicles = vehiclePersistence.list(); - } catch (PersistenceException e) { - throw new ServiceException(e); - } - - return vehicles.stream() - .filter(vehicle -> statuses.contains(vehicle.status())) - .collect(Collectors.toSet()); - } - - @Override - public void remove(long id) throws InvalidVehicleException, ServiceException { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ArchiveOperationController.java new file mode 100644 index 0000000..6e0c89d --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ArchiveOperationController.java @@ -0,0 +1,213 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.OperationService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class ArchiveOperationController { + + private static final Logger LOG = LoggerFactory.getLogger(ArchiveOperationController.class); + + @FXML private ImageView imvVehicleDetail; + @FXML private Label lblStatus; + @FXML private AnchorPane apMainDetails; + @FXML private Label lblOperations; + @FXML private Label lblCompleted; + @FXML private Label lblCancelled; + @FXML private AnchorPane backApMain; + @FXML private AnchorPane backApDetails; + @FXML private AnchorPane archiveOperationAP; + @FXML private AnchorPane apDetails; + @FXML private Label lblCodeHeader; + @FXML private Label lblOpCode; + @FXML private Label lblVehicles; + @FXML private Label lblDate; + @FXML private Label lblAddress; + @FXML private FlowPane fpVehicles; + private final OperationService operationService; + @FXML private FlowPane archiveOperationFlowPane; + private final CreateOperationController createOperationController; + private Set list = new HashSet<>(); + private final SpringFXMLLoader fxmlLoader; + + public ArchiveOperationController( + OperationService operationService, + CreateOperationController createOperationController, + SpringFXMLLoader fxmlLoader) { + this.operationService = operationService; + this.createOperationController = createOperationController; + this.fxmlLoader = fxmlLoader; + } + + @FXML + private void initialize() { + update(); + } + + public void update() { + archiveOperationFlowPane.getChildren().clear(); + list.clear(); + try { + list.addAll(operationService.list(EnumSet.of(Status.CANCELLED, Status.COMPLETED))); + long cancelledAmount = 0; + long completedAmount = 0; + for (Operation operation : list) { + if (operation.status() == Status.CANCELLED) cancelledAmount++; + else completedAmount++; + } + lblCancelled.setText("storniert: " + cancelledAmount); + lblCompleted.setText("abgeschlossen: " + completedAmount); + lblOperations.setText("Einsätze: " + list.size()); + } catch (ServiceException e) { + LOG.error("ServiceException in update().", e); + showServiceExceptionAlertAndWait("Die Einsätze konnten nicht geladen werden!"); + ; + } + setFlowPane(); + } + + private void setFlowPane() { + try { + archiveOperationFlowPane.getChildren().clear(); + for (Operation operation : sortSet(list)) { + OperationInArchiveController opInAController = + OperationInArchiveController.create(); + opInAController.set(operation); + opInAController + .getRoot() + .setOnMouseClicked( + event -> { + detailOperation = operation; + backApMain.setVisible(false); + apMainDetails.setVisible(false); + backApDetails.setVisible(true); + setOperation(); + setDetailsVisible(true); + imvVehicleDetail.setImage(new Image("/images/Vehicle.png")); + }); + archiveOperationFlowPane.getChildren().add(opInAController.getRoot()); + } + } catch (IOException e) { + LOG.error("IOException in setFlowPane(). ", e); + showServiceExceptionAlertAndWait("Die Elemente konnten nicht geladen werden!"); + } + } + + private Operation detailOperation; + + private List sortSet(Set operationsSet) { + Operation[] array = operationsSet.toArray(new Operation[operationsSet.size()]); + for (int i = array.length - 1; i > 0; i--) { + for (int j = 0; j < i; j++) { + LocalDateTime first = + LocalDateTime.ofInstant( + Objects.requireNonNull(array[j].created()), ZoneOffset.UTC); + LocalDateTime second = + LocalDateTime.ofInstant( + Objects.requireNonNull(array[j + 1].created()), ZoneOffset.UTC); + if (first.isBefore(second)) { + Operation help = array[j]; + array[j] = array[j + 1]; + array[j + 1] = help; + } + } + } + return Arrays.asList(array); + } + + private void setOperation() { + lblCodeHeader.setText(detailOperation.opCode()); + if (detailOperation.created() != null) { + LocalDateTime dateTime = + LocalDateTime.ofInstant( + Objects.requireNonNull(detailOperation.created()), ZoneOffset.UTC); + lblDate.setText( + "am " + + dateTime.getDayOfMonth() + + "." + + dateTime.getMonth().getValue() + + "." + + dateTime.getYear()); + } else { + lblDate.setText("---"); + } + lblStatus.setText( + "Status: " + + (detailOperation.status() == Status.CANCELLED + ? "storniert" + : "abgeschlossen")); + lblOpCode.setText(detailOperation.opCode()); + Collection elements = + detailOperation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); + String result = String.join(", ", elements); + + lblVehicles.setText(result); + lblAddress.setText(detailOperation.destination()); + + fpVehicles.getChildren().clear(); + try { + for (Vehicle vehicle : detailOperation.vehicles()) { + DetailArchiveOperationController controller = null; + + controller = DetailArchiveOperationController.create(fxmlLoader); + + controller.set(vehicle); + fpVehicles.getChildren().add(controller.getRoot()); + } + } catch (IOException e) { + LOG.error("IOException in setOperation(). ", e); + showServiceExceptionAlertAndWait("Die Element konnte nicht geladen werden!"); + } + } + + private void setDetailsVisible(boolean b) { + apDetails.setVisible(b); + } + + public void backClicked() { + LOG.debug("Hyperlink \"Zurück\" in archive detail view clicked."); + fpVehicles.getChildren().clear(); + setDetailsVisible(false); + backApDetails.setVisible(false); + apMainDetails.setVisible(true); + backApMain.setVisible(true); + } + + public void backToMain() { + LOG.debug("Hyperlink \"Zurück\" in archive main view clicked."); + this.setVisible(false); + createOperationController.setVisible(true); + } + + void setVisible(boolean b) { + archiveOperationAP.setVisible(b); + backApMain.setVisible(b); + apMainDetails.setVisible(b); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateCarController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateCarController.java new file mode 100644 index 0000000..aa76535 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateCarController.java @@ -0,0 +1,231 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showSuccessAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showValidationErrorAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.ConstructionType; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.VehicleType; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.VehicleService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.io.IOException; +import java.util.EnumSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ChoiceBox; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class CreateCarController { + + @FXML private AnchorPane createCarAP; + @FXML private ChoiceBox cmbCtype; + @FXML private ChoiceBox cmbTyp; + + @FXML private Button btnCreate; + @FXML private CheckBox cbxNEF; + @FXML private FlowPane fpVehicleList; + private final CreateOperationController createOperationController; + + private static final Logger LOG = LoggerFactory.getLogger(CreateCarController.class); + private final VehicleService vehicleService; + private boolean update = false; + private long vid = -1; + + private Vehicle chooseVehicle; + + public CreateCarController( + CreateOperationController createOperationController, VehicleService vehicleService) { + this.createOperationController = createOperationController; + this.vehicleService = vehicleService; + } + + @FXML + private void initialize() { + fpVehicleList.setHgap(5); + fpVehicleList.setVgap(5); + + cmbCtype.setItems( + FXCollections.observableArrayList( + Stream.of( + ConstructionType.NORMAL, + ConstructionType.MITTELHOCHDACH, + ConstructionType.HOCHDACH) + .map(Enum::toString) + .collect(Collectors.toList()))); + cmbCtype.setValue(ConstructionType.NORMAL.toString()); + cmbTyp.setItems( + FXCollections.observableArrayList( + Stream.of( + VehicleType.BKTW, + VehicleType.KTW_B, + VehicleType.KTW, + VehicleType.RTW, + VehicleType.NEF, + VehicleType.NAH) + .map(Enum::toString) + .collect(Collectors.toList()))); + cmbTyp.setValue(VehicleType.BKTW.toString()); + + updateVehiclePane(); + } + + @FXML + private void createCar(ActionEvent actionEvent) { + + if (!update) { + LOG.debug("Button \"Erstellen\" clicked."); + Vehicle vehicle = + Vehicle.builder() + .constructionType(parseConstructionType()) + .type(parseType()) + .name("") + .status(Status.ABGEMELDET) + .hasNef(cbxNEF.isSelected()) + .build(); + try { + vehicleService.add(vehicle); + setToStart(); + } catch (InvalidVehicleException e) { + LOG.debug("Validation of Vehicle failed"); + showValidationErrorAlertAndWait(e.getMessage()); + setToStart(); + return; + } catch (ServiceException e) { + LOG.error("ServiceException in createCar(). ", e); + showServiceExceptionAlertAndWait( + "Ein Fehler beim Erstellen des Fahrzeuges ist aufgetreten."); + setToStart(); + return; + } + showSuccessAlertAndWait("Auto wurde erfolgreich angelegt."); + } else { + LOG.debug("Button \"Speichern\" clicked."); + try { + Vehicle vehicle = + Vehicle.builder() + .id(vid) + .constructionType(parseConstructionType()) + .type(parseType()) + .name("") + .status(Status.ABGEMELDET) + .hasNef(cbxNEF.isSelected()) + .build(); + vehicleService.update(vehicle); + setToStart(); + chooseVehicle = null; + } catch (InvalidVehicleException e) { + LOG.debug("Validation of Vehicle failed"); + showValidationErrorAlertAndWait(e.getMessage()); + setToStart(); + return; + } catch (ServiceException e) { + LOG.error("ServiceException in createCar(). ", e); + showServiceExceptionAlertAndWait(e.getMessage()); + setToStart(); + return; + } + showSuccessAlertAndWait("Auto wurde erfolgreich bearbeitet."); + } + + updateVehiclePane(); + } + + private ConstructionType parseConstructionType() { + if (cmbCtype.getSelectionModel().getSelectedItem() == null) { + return ConstructionType.NORMAL; + } + return ConstructionType.valueOf(cmbCtype.getSelectionModel().getSelectedItem()); + } + + private VehicleType parseType() { + if (cmbTyp.getSelectionModel().getSelectedItem() == null) { + return VehicleType.BKTW; + } + return VehicleType.valueOf(cmbTyp.getSelectionModel().getSelectedItem()); + } + + private void setToStart() { + btnCreate.setText("Erstellen"); + cbxNEF.setSelected(false); + cmbTyp.setValue(VehicleType.BKTW.name()); + cmbCtype.setValue(ConstructionType.NORMAL.name()); + update = false; + } + + private void updateVehicle(Vehicle vehicle) { + + cmbCtype.setValue(vehicle.constructionType().name()); + cmbTyp.setValue(vehicle.type().name()); + cbxNEF.setSelected(vehicle.hasNef()); + btnCreate.setText("Speichern"); + vid = vehicle.id(); + update = true; + chooseVehicle = vehicle; + } + + public void setVisible(boolean b) { + createCarAP.setVisible(b); + } + + @FXML + private void backToMain() { + LOG.debug("Hyperlink \"zurück\" clicked."); + this.setVisible(false); + createOperationController.setVisible(true); + } + + private void updateVehiclePane() { + try { + fpVehicleList.getChildren().clear(); + + Set vehicles; + + vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET)); + + for (Vehicle vehicle : vehicles) { + VehiclePaneController controller = VehiclePaneController.createVehiclePane(); + + controller.setData(vehicle, false, false); + controller + .getRootElement() + .setOnMouseClicked( + event -> { + if (event.getButton().equals(MouseButton.PRIMARY)) { + if (chooseVehicle == null || vehicle == chooseVehicle) { + if (update == false) { + chooseVehicle = vehicle; + updateVehicle(vehicle); + controller.setSelected(true); + } else { + setToStart(); + controller.setSelected(false); + + chooseVehicle = null; + } + } + } + }); + + fpVehicleList.getChildren().add(controller.getRootElement()); + } + } catch (ServiceException | IOException e) { + LOG.error("Exception in updateVehiclePane(). ", e); + showServiceExceptionAlertAndWait(e.getMessage()); + } + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateNewEmployeeController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateNewEmployeeController.java new file mode 100644 index 0000000..433bfa6 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateNewEmployeeController.java @@ -0,0 +1,174 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showSuccessAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showValidationErrorAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee.EducationLevel; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; +import java.io.IOException; +import java.time.LocalDate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; + +@Controller +@Scope("prototype") +public class CreateNewEmployeeController { + + private static final Logger LOG = LoggerFactory.getLogger(CreateNewEmployeeController.class); + private final EmployeeService employeeService; + + @FXML private Label lblHeader; + @FXML private CheckBox inputIsDriver; + @FXML private CheckBox inputIsPilot; + @FXML private TextField inputName; + @FXML private ChoiceBox inputQualification; + @FXML private Button btnCreate; + + private Node rootElement; + private Employee employee; + private boolean isEdit; + + private Runnable consumerCancelClicked; + private Runnable consumerCreateClicked; + + public CreateNewEmployeeController(EmployeeService employeeService) { + this.employeeService = employeeService; + } + + @FXML + private void initialize() { + inputQualification.setItems( + FXCollections.observableArrayList( + Stream.of( + EducationLevel.RS, + EducationLevel.NFS, + EducationLevel.NKV, + EducationLevel.NKA, + EducationLevel.NKI, + EducationLevel.NA) + .map(Enum::toString) + .collect(Collectors.toList()))); + + inputQualification.setValue(EducationLevel.RS.toString()); + employee = + Employee.builder() + .name("") + .educationLevel(EducationLevel.RS) + .isDriver(false) + .isPilot(false) + .birthday(LocalDate.MIN) + .build(); + } + + @FXML + private void onCancelClicked() { + LOG.debug("Hyperlink \"abbrechen\" clicked."); + if (consumerCancelClicked != null) { + consumerCancelClicked.run(); + } + } + + @FXML + private void onCreateClicked() { + LOG.debug("Button {} clicked.", btnCreate.getText()); + + employee = + employee.toBuilder() + .name(inputName.getText()) + .educationLevel(parseEducationLevel()) + .birthday(LocalDate.MIN) // TODO: change UI to include birthday field + .isDriver(inputIsDriver.isSelected()) + .isPilot(inputIsPilot.isSelected()) + .build(); + + try { + if (isEdit) { + employeeService.update(employee); + } else { + employeeService.add(employee); + } + } catch (InvalidEmployeeException e) { + LOG.debug("Validation for Employee failed"); + showValidationErrorAlertAndWait(e.getMessage()); + return; + } catch (ServiceException e) { + LOG.error("ServiceException in onCreateClicked(). ", e); + showServiceExceptionAlertAndWait( + "Der Eintrag konnte nicht gespeichert werden. Bitte versuchen Sie es erneut."); + return; + } + + showSuccessAlertAndWait( + "Der/die MitarbeiterIn wurde erfolgreich angelegt und gespeichert!"); + + if (consumerCreateClicked != null) { + consumerCreateClicked.run(); + } + } + + private EducationLevel parseEducationLevel() { + if (inputQualification.getSelectionModel().getSelectedItem() == null) { + return EducationLevel.RS; + } + return EducationLevel.valueOf(inputQualification.getSelectionModel().getSelectedItem()); + } + + private void setData(Employee employee) { + isEdit = true; + this.employee = employee; + inputName.setText(employee.name()); + inputQualification.setValue(employee.educationLevel().name()); + inputIsDriver.setSelected(employee.isDriver()); + inputIsPilot.setSelected(employee.isPilot()); + lblHeader.setText("Person bearbeiten"); + btnCreate.setText("Speichern"); + } + + public static CreateNewEmployeeController createCreateNewEmployeeController( + SpringFXMLLoader fxmlLoader, Employee employee) throws IOException { + CreateNewEmployeeController controller = createCreateNewEmployeeController(fxmlLoader); + controller.setData(employee); + return controller; + } + + public static CreateNewEmployeeController createCreateNewEmployeeController( + SpringFXMLLoader fxmlLoader) throws IOException { + FXMLWrapper wrapper = + fxmlLoader.loadAndWrap( + "/fxml/createNewEmployee.fxml", CreateNewEmployeeController.class); + Node root = (Node) wrapper.getLoadedObject(); + CreateNewEmployeeController controller = wrapper.getController(); + controller.rootElement = root; + return controller; + } + + public Node getRootElement() { + return rootElement; + } + + public void setConsumerCancelClicked(Runnable consumerCancelClicked) { + this.consumerCancelClicked = consumerCancelClicked; + } + + public void setConsumerCreateClicked(Runnable consumerCreateClicked) { + this.consumerCreateClicked = consumerCreateClicked; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateOperationController.java new file mode 100644 index 0000000..b237265 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CreateOperationController.java @@ -0,0 +1,371 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showSuccessAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showValidationErrorAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.OperationService; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.VehicleService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.control.MenuItem; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.GridPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class CreateOperationController { + + private static final Logger LOG = LoggerFactory.getLogger(CreateOperationController.class); + + public AnchorPane apCreateOperation; + @FXML private GridPane grdWindowContainer; + @FXML private TextField txtCode; + @FXML private TextField txtAddress; + @FXML private TextField txtNote; + @FXML private Button btnCreateOperation; + @FXML private ListView lvVehicles; + @FXML private ListView lvActiveOperations; + @FXML private Label lblChosenVehicles; + @FXML private AnchorPane apInvisible; + @FXML private OperationDetailsController operationDetailsController; + @FXML private ManageEmployeesController manageEmployeesController; + @FXML private CreateCarController createCarController; + @FXML private RegistrationWindowController registrationWindowController; + @FXML private ArchiveOperationController archiveOperationController; + @FXML private FlowPane fpVehicles; + + private LinkedList chosenVehicles = new LinkedList<>(); + + private final OperationService operationService; + private final VehicleService vehicleService; + + public CreateOperationController( + OperationService operationService, VehicleService vehicleService) { + this.operationService = operationService; + this.vehicleService = vehicleService; + } + + @FXML + private void initialize() { + + lblChosenVehicles.setText("keine ausgewählt"); + lvActiveOperations.setCellFactory(param -> generateOpCodeListItem()); + + lvActiveOperations.setOnMouseClicked( + event -> { + if (event.getClickCount() == 2) { + if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { + return; + } + openDetailsWindow(lvActiveOperations.getSelectionModel().getSelectedItem()); + } + }); + + setVisible(true); + createCarController.setVisible(false); + registrationWindowController.setVisible(false); + } + + public void updateList() { + try { + fpVehicles.getChildren().clear(); + + // TODO: this should probably be handled differently + Set vehicles; + if (txtCode.getText().isEmpty()) { + vehicles = + vehicleService.list( + EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET))); + } else { + vehicles = operationService.rankVehicles(txtCode.getText()); + } + + for (Vehicle vehicle : vehicles) { + VehiclePaneController controller = VehiclePaneController.createVehiclePane(); + + controller.setData(vehicle, true, false); + controller + .getRootElement() + .setOnMouseClicked( + event -> { + if (event.getButton().equals(MouseButton.SECONDARY)) { + createContextMenu(vehicle, vehicleService) + .show( + controller.getRootElement(), + event.getScreenX(), + event.getScreenY()); + } else { + if (chosenVehicles.contains(vehicle)) { + chosenVehicles.remove(vehicle); + controller.setSelected(false); + } else { + chosenVehicles.add(vehicle); + controller.setSelected(true); + } + + StringBuilder result = new StringBuilder(); + for (int i = 0; i < chosenVehicles.size(); i++) { + if (i == chosenVehicles.size() - 1) { + result.append(chosenVehicles.get(i).name()); + } else { + result.append(chosenVehicles.get(i).name()) + .append(", "); + } + } + if (result.toString().equals("")) { + lblChosenVehicles.setText("keine ausgewählt"); + } else { + lblChosenVehicles.setText(result.toString()); + } + } + }); + + if (chosenVehicles.stream().anyMatch(v -> v.id() == vehicle.id())) + controller.setSelected(true); + + fpVehicles.getChildren().add(controller.getRootElement()); + } + } catch (ServiceException | IOException e) { + LOG.error("Exception in updateList(). ", e); + showServiceExceptionAlertAndWait( + "Beim Erstellen des Ranking ist ein Fehler aufgetreten."); + } catch (InvalidOperationException e) { + LOG.debug("Validation error in updateList(). ", e); + showValidationErrorAlertAndWait(e.getMessage()); + } + try { + lvActiveOperations.setItems( + FXCollections.observableArrayList( + operationService.list(EnumSet.of(Status.ACTIVE)))); + } catch (ServiceException e) { + LOG.error("ServiceException in updateList(). ", e); + showServiceExceptionAlertAndWait( + "Beim Holen der aktiven Einsätze ist ein Fehler aufgetreten"); + } + } + + private ContextMenu createContextMenu(Vehicle data, VehicleService vehicleService) { + ContextMenu menu = new ContextMenu(); + + for (Vehicle.Status status : Vehicle.Status.values()) { + if (status == Vehicle.Status.ABGEMELDET) { + continue; + } + + MenuItem mi = new MenuItem(status.name()); + + if (status == Vehicle.Status.FREI_FUNK || status == Vehicle.Status.FREI_WACHE) { + mi.getStyleClass().add("mi-free"); + } else { + mi.getStyleClass().add("mi-other"); + } + + mi.setOnAction( + event -> { + try { + vehicleService.update(data.toBuilder().status(status).build()); + this.updateList(); + } catch (InvalidVehicleException e) { + LOG.debug( + "Validation error in createContextMenu(). (mi.setOnAction) ", + e); + showValidationErrorAlertAndWait(e.getMessage()); + } catch (ServiceException e) { + LOG.error("Exception in createContextMenu(). (mi.setOnAction) ", e); + showServiceExceptionAlertAndWait( + "Beim Aktualisieren der Fahrzeuge ist ein Fehler aufgetreten."); + } + }); + + menu.getItems().add(mi); + } + + MenuItem abmelden = new MenuItem("abmelden"); + + abmelden.setOnAction( + event -> { + try { + List registrations = data.registrations(); + assert registrations + != null; // Otherwise the element shouldn't be in the list. + + List newRegistrations = new ArrayList<>(); + Instant now = Instant.now(); + + for (Registration registration : registrations) { + if (registration.start().isBefore(now) + && registration.end().isAfter(now)) { + newRegistrations.add( + registration + .toBuilder() + .end(Instant.now().minus(1, ChronoUnit.SECONDS)) + .build()); + } else newRegistrations.add(registration); + } + + vehicleService.update( + data.toBuilder() + .registrations(newRegistrations) + .status(Vehicle.Status.ABGEMELDET) + .build()); + + this.updateList(); + } catch (InvalidVehicleException e) { + LOG.debug( + "Validation error in createContextMenu(). (abmelden.setOnAction) ", + e); + showValidationErrorAlertAndWait(e.getMessage()); + } catch (ServiceException e) { + LOG.error("Exception in createContextMenu(). (abmelden.setOnAction) ", e); + showServiceExceptionAlertAndWait( + "Beim Aktualisieren der Fahrzeuge ist ein Fehler aufgetreten."); + } + }); + + menu.getItems().add(abmelden); + return menu; + } + + @FXML + protected void createOperationClicked() { + LOG.debug("Button \"Erstellen\" clicked."); + Vehicle[] vehicles = new Vehicle[chosenVehicles.size()]; + for (int i = 0; i < chosenVehicles.size(); i++) { + vehicles[i] = chosenVehicles.get(i); + } + Operation operation = + Operation.builder() + .additionalInfo(txtNote.getText()) + .destination(txtAddress.getText()) + .opCode(txtCode.getText()) + .status(Status.ACTIVE) + .vehicles(Set.of(vehicles)) + .build(); + try { + operationService.add(operation); + } catch (ServiceException e) { + LOG.error("Exception in createOperationClicked(). ", e); + showServiceExceptionAlertAndWait( + "Beim Erstellen des Einsatzes ist ein Fehler aufgetreten."); + return; + } catch (InvalidOperationException e) { + LOG.debug("Validation error in createOperationClicked(). ", e); + showValidationErrorAlertAndWait(e.getMessage()); + return; + } + showSuccessAlertAndWait("Der Einsatz wurde erfolgreich gespeichert."); + updateList(); + lblChosenVehicles.setText("keine ausgewählt"); + txtAddress.setText(""); + txtCode.setText(""); + txtNote.setText(""); + chosenVehicles = new LinkedList<>(); + } + + @FXML + private void onRegistrationLinkClicked() { + LOG.debug("Hyperlink \"Anmeldungen\" clicked."); + openRegistrationWindow(); + } + + @FXML + private void onEmployeeLinkClicked() { + LOG.debug("Hyperlink \"Personen\" clicked."); + openCreateNewEmployeeWindow(); + } + + @FXML + private void onVehicleLinkClicked() { + LOG.debug("Hyperlink \"Fahrzeuge\" clicked."); + openCreateCarWindow(); + } + + @FXML + private void onArchivLinkClicked() { + LOG.debug("Hyperlink \"Archiv\" clicked."); + archiveOperationController.update(); + openArchivWindow(); + } + + private void openArchivWindow() { + archiveOperationController.setVisible(true); + this.setVisible(false); + } + + void setVisible(boolean b) { + apInvisible.setVisible(!b); + grdWindowContainer.setVisible(!b); + + updateList(); + } + + private void openDetailsWindow(Operation operation) { + operationDetailsController.initOperation(operation); + this.setVisible(false); + } + + private void openCreateNewEmployeeWindow() { + this.setVisible(false); + manageEmployeesController.setVisible(true); + } + + private void openCreateCarWindow() { + this.setVisible(false); + createCarController.setVisible(true); + } + + private void openRegistrationWindow() { + this.setVisible(false); + registrationWindowController.setVisible(true); + } + + @FXML + private void onOperationCodeChanged(KeyEvent keyEvent) { + if (keyEvent.getCode() == KeyCode.ENTER) { + updateList(); + } + } + + static ListCell generateOpCodeListItem() { + return new ListCell<>() { + @Override + protected void updateItem(Operation item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null || item.opCode() == null) { + setText(null); + } else { + setText(item.opCode()); + } + } + }; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CustomListItemController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CustomListItemController.java new file mode 100644 index 0000000..ced0c10 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/CustomListItemController.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import javafx.scene.Node; + +public abstract class CustomListItemController { + + protected Node rootElement; + + public Node getRootElement() { + return rootElement; + } + + public void setSelected(boolean selected) { + rootElement.getStyleClass().clear(); + + if (selected) { + rootElement.getStyleClass().add("bg-yellow"); + rootElement.getStyleClass().add("shadowed"); + } else { + rootElement.getStyleClass().add("bg-white"); + rootElement.getStyleClass().add("shadowed"); + } + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/DetailArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/DetailArchiveOperationController.java new file mode 100644 index 0000000..32630a5 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/DetailArchiveOperationController.java @@ -0,0 +1,77 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; +import java.io.IOException; +import java.util.Objects; +import javafx.fxml.FXML; +import javafx.scene.Node; +import javafx.scene.layout.VBox; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class DetailArchiveOperationController { + private static final Logger LOG = + LoggerFactory.getLogger(DetailArchiveOperationController.class); + + @FXML private VBox vBoxVehicle; + @FXML private VBox vBoxPeople; + private final SpringFXMLLoader fxmlLoader; + + public DetailArchiveOperationController(SpringFXMLLoader fxmlLoader) { + this.fxmlLoader = fxmlLoader; + } + + static DetailArchiveOperationController create(SpringFXMLLoader fxmlLoader) throws IOException { + FXMLWrapper wrapper = + fxmlLoader.loadAndWrap( + "/fxml/DetailArchiveOperation.fxml", + DetailArchiveOperationController.class); + + Node root = (Node) wrapper.getLoadedObject(); + DetailArchiveOperationController result = wrapper.getController(); + result.rootElement = root; + + return result; + } + + public Node getRoot() { + return rootElement; + } + + private Node rootElement; + + public void set(Vehicle vehicle) { + VehiclePaneController controller; + try { + controller = VehiclePaneController.createVehiclePane(); + controller.setData(vehicle, false, false); + vBoxVehicle.getChildren().add(controller.getRootElement()); + } catch (IOException e) { + LOG.error("IOException in set(Vehicle). (vBoxVehicle) ", e); + showServiceExceptionAlertAndWait( + "Ein interner Fehler ist aufgetreten. Bitte wenden Sie sich an den/die SystemadministratorIn."); + } + try { + for (int i = 0; i < Objects.requireNonNull(vehicle.registrations()).size(); i++) { + Employee employee = + Objects.requireNonNull(vehicle.registrations()).get(i).employee(); + + EmployeeListItemController employeeListItemController = + EmployeeListItemController.createEmployeeListItemController( + fxmlLoader, employee); + vBoxPeople.getChildren().add(employeeListItemController.getRootElement()); + } + } catch (IOException e) { + LOG.error("IOException in set(Vehicle). (vBoxPeople) ", e); + showServiceExceptionAlertAndWait( + "Ein interner Fehler ist aufgetreten. Bitte wenden Sie sich an den/die SystemadministratorIn."); + } + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListController.java new file mode 100644 index 0000000..12f6bff --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListController.java @@ -0,0 +1,133 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.scene.Node; +import javafx.scene.layout.FlowPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; + +@Controller +@Scope("prototype") +public class EmployeeListController { + + private static final Logger LOG = LoggerFactory.getLogger(EmployeeListController.class); + + @FXML private FlowPane flowPaneEmployeeList; + + private Consumer onEmployeeClicked; + + private final SpringFXMLLoader fxmlLoader; + private Node rootElement; + private List employeeListItemControllers; + private Insets listItemMargins = new Insets(10, 5, 0, 5); + + public EmployeeListController(SpringFXMLLoader fxmlLoader) { + this.fxmlLoader = fxmlLoader; + this.employeeListItemControllers = new ArrayList<>(); + } + + public void setListItemMargins(Insets value) { + this.listItemMargins = value; + } + + public void setData(Set employeeList) { + setData(employeeList, null, null); + } + + public void setData(Set employeeList, Consumer onEmployeeClicked) { + setData(employeeList, onEmployeeClicked, null); + } + + public void setData( + Set employeeList, + Consumer onEmployeeClicked, + Consumer onEmployeeListItemClicked) { + + flowPaneEmployeeList.getChildren().clear(); + employeeListItemControllers.clear(); + employeeList.forEach( + employee -> + addEmployeeToFlowPane( + employee, onEmployeeClicked, onEmployeeListItemClicked)); + } + + private void addEmployeeToFlowPane( + Employee employee, + Consumer onEmployeeClicked, + Consumer onEmployeeListItemClicked) { + + try { + EmployeeListItemController controller = + EmployeeListItemController.createEmployeeListItemController( + fxmlLoader, employee); + Node rootElement = controller.getRootElement(); + flowPaneEmployeeList.getChildren().add(rootElement); + employeeListItemControllers.add(controller); + FlowPane.setMargin(rootElement, listItemMargins); + if (onEmployeeClicked != null) { + controller.setConsumerEmployeeClicked(onEmployeeClicked); + } + if (onEmployeeListItemClicked != null) { + controller.setConsumerEmployeeListItemClicked( + employeeListItemController -> { + onEmployeeListItemClicked.accept(employeeListItemController); + if (this.onEmployeeClicked != null) { + this.onEmployeeClicked.accept( + employeeListItemController.getEmployee()); + } + }); + } + } catch (IOException e) { + LOG.error("IOException in addEmployeeToFlowPane. ", e); + } + } + + private void setEmployeeSelected(Employee employee, boolean selected) { + employeeListItemControllers + .stream() + .filter(controller -> controller.getEmployee().equals(employee)) + .forEach(controller -> controller.setSelected(selected)); + } + + public void selectEmployee(Employee employee) { + setEmployeeSelected(employee, true); + } + + public void deselectEmployee(Employee employee) { + setEmployeeSelected(employee, false); + } + + public void deselectAllEmployees() { + employeeListItemControllers.forEach( + employeeListItemController -> employeeListItemController.setSelected(false)); + } + + public static EmployeeListController createEmployeeListController(SpringFXMLLoader loader) + throws IOException { + FXMLWrapper wrapper = + loader.loadAndWrap("/fxml/employeeList.fxml", EmployeeListController.class); + Node root = (Node) wrapper.getLoadedObject(); + EmployeeListController controller = wrapper.getController(); + controller.rootElement = root; + return controller; + } + + public Node getRootElement() { + return rootElement; + } + + public void setOnEmployeeClicked(Consumer onEmployeeClicked) { + this.onEmployeeClicked = onEmployeeClicked; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListItemController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListItemController.java new file mode 100644 index 0000000..543fe0d --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/EmployeeListItemController.java @@ -0,0 +1,87 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; +import java.io.IOException; +import java.util.function.Consumer; +import javafx.fxml.FXML; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; + +@Controller +@Scope("prototype") +public class EmployeeListItemController extends CustomListItemController { + + @FXML private Label lblName; + @FXML private Label lblQualification; + @FXML private Label lblPilot; + @FXML private Label lblDriver; + @FXML private ImageView imgPilot; + @FXML private ImageView imgDriver; + @FXML private ImageView imgQualification; + + private Employee employee; + + private Consumer consumerEmployeeClicked; + private Consumer consumerEmployeeListItemClicked; + + @FXML + private void onEmployeeClicked() { + if (consumerEmployeeClicked != null) { + consumerEmployeeClicked.accept(employee); + } + if (consumerEmployeeListItemClicked != null) { + consumerEmployeeListItemClicked.accept(this); + } + } + + private void setData(Employee employee) { + this.employee = employee; + lblName.setText(employee.name()); + lblQualification.setText(employee.educationLevel().name()); + lblPilot.setText(String.format("%s Pilot", employee.isPilot() ? "ist" : "nicht")); + lblDriver.setText(String.format("%s Fahrer", employee.isDriver() ? "ist" : "nicht")); + imgQualification.setImage(new Image("/images/Qualification.png")); + String imgSrcPilot = + String.format("/images/%s", employee.isPilot() ? "Pilot.png" : "NotPilot.png"); + imgPilot.setImage(new Image(imgSrcPilot)); + String imgSrcDriver = + String.format("/images/%s", employee.isDriver() ? "Driver.png" : "NotDriver.png"); + imgDriver.setImage(new Image(imgSrcDriver)); + } + + public static EmployeeListItemController createEmployeeListItemController( + SpringFXMLLoader fxmlLoader, Employee employee) throws IOException { + EmployeeListItemController controller = createEmployeeListItemController(fxmlLoader); + controller.setData(employee); + return controller; + } + + public static EmployeeListItemController createEmployeeListItemController( + SpringFXMLLoader loader) throws IOException { + FXMLWrapper wrapper = + loader.loadAndWrap("/fxml/employeeListItem.fxml", EmployeeListItemController.class); + Node root = (Node) wrapper.getLoadedObject(); + EmployeeListItemController controller = wrapper.getController(); + controller.rootElement = root; + return controller; + } + + public Employee getEmployee() { + return employee; + } + + public void setConsumerEmployeeClicked(Consumer consumerEmployeeClicked) { + this.consumerEmployeeClicked = consumerEmployeeClicked; + } + + public void setConsumerEmployeeListItemClicked( + Consumer consumerEmployeeListItemClicked) { + this.consumerEmployeeListItemClicked = consumerEmployeeListItemClicked; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/FilterEmployeesController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/FilterEmployeesController.java new file mode 100644 index 0000000..a31c3e3 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/FilterEmployeesController.java @@ -0,0 +1,65 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader.FXMLWrapper; +import java.io.IOException; +import java.util.function.Consumer; +import javafx.fxml.FXML; +import javafx.scene.Node; +import javafx.scene.control.TextField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; + +@Controller +@Scope("prototype") +public class FilterEmployeesController { + private static final Logger LOG = LoggerFactory.getLogger(FilterEmployeesController.class); + + @FXML private TextField inputFilterString; + + private Consumer consumerFilterTextChanged; + private Runnable consumerAddEmployeeClicked; + + private Node rootElement; + + @FXML + private void onAddEmployeeClicked() { + LOG.debug("Button \"Person hinzufügen\" clicked."); + if (consumerAddEmployeeClicked != null) { + consumerAddEmployeeClicked.run(); + } + } + + @FXML + private void onFilterTextChanged() { + LOG.debug("Filter text changed."); + if (consumerFilterTextChanged != null) { + consumerFilterTextChanged.accept(inputFilterString.getText()); + } + } + + public void setOnFilterTextChangedListener(Consumer callback) { + this.consumerFilterTextChanged = callback; + } + + public void setOnAddEmployeeClickedListener(Runnable callback) { + this.consumerAddEmployeeClicked = callback; + } + + public static FilterEmployeesController createFilterEmployeesController( + SpringFXMLLoader fxmlLoader) throws IOException { + FXMLWrapper wrapper = + fxmlLoader.loadAndWrap( + "/fxml/filterEmployeesControl.fxml", FilterEmployeesController.class); + Node root = (Node) wrapper.getLoadedObject(); + FilterEmployeesController controller = wrapper.getController(); + controller.rootElement = root; + return controller; + } + + public Node getRootElement() { + return rootElement; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/Helper.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/Helper.java new file mode 100644 index 0000000..f120eb6 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/Helper.java @@ -0,0 +1,34 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonType; + +public class Helper { + + static final String ALERT_TITLE_VALIDATION_ERROR = "Validierungsfehler"; + static final String ALERT_TITLE_SERVICE_EXCEPTION = "Fehler"; + static final String ALERT_TITLE_SUCCESS = "Erfolg"; + + private Helper() {} // SonarLint insisted to create a private constructor to hide the public one + + static void showValidationErrorAlertAndWait(String message) { + showAlertWithOkButtonAndWait(AlertType.ERROR, ALERT_TITLE_VALIDATION_ERROR, message); + } + + static void showServiceExceptionAlertAndWait(String message) { + showAlertWithOkButtonAndWait(AlertType.ERROR, ALERT_TITLE_SERVICE_EXCEPTION, message); + } + + static void showSuccessAlertAndWait(String message) { + showAlertWithOkButtonAndWait(AlertType.INFORMATION, ALERT_TITLE_SUCCESS, message); + } + + static void showAlertWithOkButtonAndWait( + AlertType alertType, String headerText, String contentText) { + Alert alert = new Alert(alertType, contentText, ButtonType.OK); + alert.setTitle(headerText); + alert.setHeaderText(headerText); + alert.showAndWait(); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ManageEmployeesController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ManageEmployeesController.java new file mode 100644 index 0000000..6138094 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/ManageEmployeesController.java @@ -0,0 +1,120 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import java.io.IOException; +import java.util.HashSet; +import java.util.stream.Collectors; +import javafx.fxml.FXML; +import javafx.scene.layout.AnchorPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class ManageEmployeesController { + + private static final Logger LOG = LoggerFactory.getLogger(ManageEmployeesController.class); + @FXML private AnchorPane listEmployeesAP; + @FXML private AnchorPane containerHeader; + @FXML private EmployeeListController employeeListController; + + private final EmployeeService employeeService; + private final SpringFXMLLoader fxmlLoader; + + private final CreateOperationController createOperationController; + + public ManageEmployeesController( + EmployeeService employeeService, + SpringFXMLLoader fxmlLoader, + CreateOperationController createOperationController) { + this.employeeService = employeeService; + this.fxmlLoader = fxmlLoader; + this.createOperationController = createOperationController; + } + + @FXML + private void initialize() { + openFilter(); + } + + private void openFilter() { + try { + FilterEmployeesController filterEmployeesController = + FilterEmployeesController.createFilterEmployeesController(fxmlLoader); + containerHeader.getChildren().clear(); + containerHeader.getChildren().add(filterEmployeesController.getRootElement()); + filterEmployeesController.setOnFilterTextChangedListener(this::updateEmployeeList); + filterEmployeesController.setOnAddEmployeeClickedListener(this::openAddEmployee); + updateEmployeeList(); + + } catch (IOException e) { + LOG.error("IOException in openFilter().", e); + } + } + + private void openAddEmployee() { + employeeListController.deselectAllEmployees(); + openEmployee(null); + } + + private void openEditEmployee(Employee employee) { + employeeListController.deselectAllEmployees(); + employeeListController.selectEmployee(employee); + openEmployee(employee); + } + + private void openEmployee(Employee employee) { + try { + CreateNewEmployeeController createNewEmployeeController = + employee == null + ? CreateNewEmployeeController.createCreateNewEmployeeController( + fxmlLoader) + : CreateNewEmployeeController.createCreateNewEmployeeController( + fxmlLoader, employee); + containerHeader.getChildren().clear(); + containerHeader.getChildren().add(createNewEmployeeController.getRootElement()); + createNewEmployeeController.setConsumerCancelClicked(this::openFilter); + createNewEmployeeController.setConsumerCreateClicked(this::openFilter); + } catch (IOException e) { + LOG.error("IOException in openEmployee(). ", e); + } + } + + private void updateEmployeeList() { + updateEmployeeList(""); + } + + private void updateEmployeeList(String searchString) { + + try { + employeeListController.setData( + employeeService + .list() + .stream() + .filter( + employee -> + searchString.trim().isEmpty() + || employee.name() + .toLowerCase() + .contains(searchString.toLowerCase())) + .collect(Collectors.toCollection(HashSet::new)), + this::openEditEmployee); + + } catch (ServiceException e) { + LOG.error("ServiceException in updateEmployeeList(). ", e); + } + } + + public void setVisible(boolean b) { + listEmployeesAP.setVisible(b); + } + + public void backToMain() { + LOG.debug("Hyperlink \"Zurück\" clicked."); + this.setVisible(false); + createOperationController.setVisible(true); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationDetailsController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationDetailsController.java new file mode 100644 index 0000000..0476fc6 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationDetailsController.java @@ -0,0 +1,169 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showAlertWithOkButtonAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showSuccessAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showValidationErrorAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.OperationService; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.VehicleService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.io.IOException; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Set; +import java.util.stream.Collectors; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ListView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class OperationDetailsController { + private static final Logger LOG = LoggerFactory.getLogger(OperationDetailsController.class); + + public Operation operation; + private final OperationService operationService; + private final VehicleService vehicleService; + private final CreateOperationController createOperationController; + @FXML private FlowPane fpVehicles; + @FXML private ListView lvActiveOperations; + @FXML private Label lblChosenVehicles; + @FXML private Button btnCloseOperation; + @FXML private Button btnCancelOperation; + @FXML private Label lblCode, lblAdditionalInfo, lblAddress; + @FXML private AnchorPane operationDetailsAP; + + public OperationDetailsController( + OperationService operationService, + VehicleService vehicleService, + CreateOperationController createOperationController) { + this.operationService = operationService; + this.vehicleService = vehicleService; + this.createOperationController = createOperationController; + } + + @FXML + private void initialize() { + lvActiveOperations.setCellFactory( + param -> CreateOperationController.generateOpCodeListItem()); + lvActiveOperations.setOnMouseClicked( + event -> { + if (event.getClickCount() == 2) { + if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { + return; + } + initOperation(lvActiveOperations.getSelectionModel().getSelectedItem()); + } + }); + } + + private void updateFlowPane() { + try { + fpVehicles.getChildren().clear(); + for (Vehicle vehicle : operation.vehicles()) { + VehiclePaneController controller = VehiclePaneController.createVehiclePane(); + controller.setData(vehicle, true, true); + controller.getBtnRequest().setOnAction(e -> requestVehicleClicked(controller)); + fpVehicles.getChildren().add(controller.getRootElement()); + } + } catch (IOException e) { + LOG.error("Error while updating list.", e); + showServiceExceptionAlertAndWait("Error while updating list."); + } + } + + void initOperation(Operation operation) { + fillActiveList(); + this.operation = operation; + lblCode.setText(operation.opCode()); + Collection vehicleNames = + operation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); + String result = String.join(", ", vehicleNames); + lblChosenVehicles.setText(result.toString()); + lblAdditionalInfo.setText(operation.additionalInfo()); + lblAddress.setText(operation.destination()); + updateFlowPane(); + operationDetailsAP.setVisible(true); + } + + private void fillActiveList() { + try { + lvActiveOperations.setItems( + FXCollections.observableArrayList( + operationService.list(EnumSet.of(Status.ACTIVE)))); + } catch (ServiceException e) { + LOG.error("ServiceException in fillActiveList(). ", e); + showServiceExceptionAlertAndWait(e.getMessage()); + } + } + + @FXML + public void closeOperationClicked() { + LOG.debug("Button \"Abschließen\" clicked."); + try { + operationService.complete(operation.id(), Status.COMPLETED); + } catch (InvalidOperationException e) { + LOG.debug("Validation error in closeOperationClicked(). ", e); + showAlertWithOkButtonAndWait(AlertType.ERROR, "Validierungsfehler", e.getMessage()); + return; + } catch (ServiceException e) { + LOG.error("Exception in closeOperationClicked(). ", e); + showServiceExceptionAlertAndWait(e.getMessage()); + return; + } + showSuccessAlertAndWait("Der Einsatz wurde erfolgreich aktualisiert"); + createOperationController.updateList(); + closeWindow(); + } + + public void cancelOperationClicked() { + LOG.debug("Button \"Stornieren\" clicked."); + try { + operationService.complete(operation.id(), Status.CANCELLED); + } catch (InvalidOperationException e) { + LOG.debug("Validation error in cancelOperationClicked(). ", e); + showValidationErrorAlertAndWait(e.getMessage()); + return; + } catch (ServiceException e) { + LOG.error("Exception in cancelOperationClicked(). ", e); + showServiceExceptionAlertAndWait(e.getMessage()); + return; + } + showSuccessAlertAndWait("Der Einsatz wurde erfolgreich aktualisiert"); + createOperationController.updateList(); + closeWindow(); + } + + private void requestVehicleClicked(VehiclePaneController v) { + LOG.debug("Button \"Nachfordern\" clicked."); + + try { + operationService.requestVehicles(operation.id(), Set.of(v.getData().id())); + } catch (ServiceException | InvalidOperationException | InvalidVehicleException e) { + LOG.error("Exception in requestVehicleClicked()", e); + showServiceExceptionAlertAndWait(e.getMessage()); + return; + } + showSuccessAlertAndWait("Das Fahrzeug wurde erfolgreich angefordert"); + createOperationController.updateList(); + } + + public void closeWindow() { + LOG.debug("Hyperlink \"Zurück\" clicked."); + operationDetailsAP.setVisible(false); + this.createOperationController.setVisible(true); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationInArchiveController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationInArchiveController.java new file mode 100644 index 0000000..17f0f55 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/OperationInArchiveController.java @@ -0,0 +1,65 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Collection; +import java.util.Objects; +import java.util.stream.Collectors; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.text.Text; + +public class OperationInArchiveController { + + @FXML private Text txtAddress; + @FXML private Text txtVehicles; + @FXML private Text txtDate; + @FXML private Text txtOpCode; + + static OperationInArchiveController create() throws IOException { + FXMLLoader fxmlLoader = + new FXMLLoader( + OperationInArchiveController.class.getResource( + "/fxml/OperationInArchive.fxml")); + Node root = fxmlLoader.load(); + OperationInArchiveController result = fxmlLoader.getController(); + result.rootElement = root; + + return result; + } + + public Node getRoot() { + return rootElement; + } + + private Node rootElement; + + public void set(Operation operation) { + txtAddress.setText(operation.destination()); + String date = "am "; + if (operation.created() != null) { + LocalDateTime myDateTime = + LocalDateTime.ofInstant( + Objects.requireNonNull(operation.created()), ZoneOffset.UTC); + date += + myDateTime.getDayOfMonth() + + "." + + myDateTime.getMonth().getValue() + + "." + + myDateTime.getYear(); + txtDate.setText(date); + } else { + txtDate.setText("---"); + } + txtOpCode.setText(operation.opCode()); + Collection elements = + operation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); + String result = String.join(", ", elements); + + txtVehicles.setText(result); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/RegistrationWindowController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/RegistrationWindowController.java new file mode 100644 index 0000000..9c47fe4 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/RegistrationWindowController.java @@ -0,0 +1,279 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; +import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showValidationErrorAlertAndWait; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.RegistrationService; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.VehicleService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.scene.Node; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.VBox; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class RegistrationWindowController { + + private static final Logger LOG = LoggerFactory.getLogger(RegistrationWindowController.class); + + private final EmployeeService employeeService; + private final VehicleService vehicleService; + private final RegistrationService registrationService; + private final CreateOperationController createOperationController; + private final SpringFXMLLoader fxmlLoader; + + @FXML private GridPane root; + @FXML private VBox vbVehicles; + @FXML private ScrollPane listEmployee; + @FXML private ChoiceBox cbStart; + @FXML private ChoiceBox cbEnd; + @FXML private Label lVehicles; + @FXML private Label lEmployees; + @FXML private TextField tfVehicleSearch; + @FXML private TextField tfEmployeeSearch; + private EmployeeListController employeeListController; + + private Vehicle chosenVehicle; + private List chosenEmployees = new LinkedList<>(); + + public RegistrationWindowController( + EmployeeService employeeService, + VehicleService vehicleService, + CreateOperationController createOperationController, + RegistrationService registrationService, + SpringFXMLLoader fxmlLoader) { + this.employeeService = employeeService; + this.vehicleService = vehicleService; + this.createOperationController = createOperationController; + this.registrationService = registrationService; + this.fxmlLoader = fxmlLoader; + } + + @FXML + private void initialize() throws IOException { + employeeListController = EmployeeListController.createEmployeeListController(fxmlLoader); + employeeListController.setListItemMargins(new Insets(10, 6, 0, 6)); + // listEmployee. .getChildren().add(employeeListController.getRootElement()); + Node emplList = employeeListController.getRootElement(); + // emplList.(360); + listEmployee.setContent(emplList); + + ObservableList hours = + FXCollections.observableArrayList( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23); + cbStart.setItems(hours); + cbStart.setValue(0); + cbEnd.setItems(hours); + cbEnd.setValue(12); + + reset(); + } + + private void updateEmplList() { + employeeListController.deselectAllEmployees(); + + try { + Set employees = + employeeService + .list() + .stream() + .filter( + e -> + e.name() + .toLowerCase() + .contains( + tfEmployeeSearch + .getText() + .toLowerCase())) + .collect(Collectors.toCollection(HashSet::new)); + employeeListController.setData( + employees, + selection -> { + if (selection == null) { + return; + } else if (chosenEmployees.contains(selection)) { + chosenEmployees.remove(selection); + } else { + chosenEmployees.add(selection); + } + + StringBuilder text = new StringBuilder(); + boolean first = true; + for (Employee employee : chosenEmployees) { + if (!first) { + text.append(", "); + } + text.append(employee.name()); + first = false; + } + lEmployees.setText(text.toString()); + }, + contr -> contr.setSelected(chosenEmployees.contains(contr.getEmployee()))); + + employees.forEach( + e -> { + if (chosenEmployees.contains(e)) employeeListController.selectEmployee(e); + }); + } catch (ServiceException e) { + LOG.error("ServiceException in updateEmplList(). ", e); + showServiceExceptionAlertAndWait( + "Beim Auflisten des Personals ist ein Fehler aufgetreten."); + } + } + + private void updateVehList() { + vbVehicles.getChildren().clear(); + + try { + Set vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET)); + + boolean anyMatch = false; + + for (Vehicle vehicle : vehicles) { + if (!vehicle.name().toLowerCase().contains(tfVehicleSearch.getText().toLowerCase())) + continue; + + anyMatch = true; + + VehiclePaneController vp = VehiclePaneController.createVehiclePane(); + vp.setData(vehicle, false, false); + vbVehicles.getChildren().add(vp.getRootElement()); + + vp.getRootElement() + .setOnMouseClicked( + event -> { + if (event.getButton() == MouseButton.PRIMARY) { + chosenVehicle = vehicle; + lVehicles.setText(chosenVehicle.name()); + updateVehList(); + } + }); + if (chosenVehicle != null && chosenVehicle.id() == vehicle.id()) + vp.setSelected(true); + } + + if (!anyMatch) { + // Kind of ugly, but best way to get the size of a VehiclePane + VehiclePaneController vp = VehiclePaneController.createVehiclePane(); + vp.getRootElement().setVisible(false); + vbVehicles.getChildren().add(vp.getRootElement()); + } + } catch (ServiceException e) { + LOG.error("ServiceException in updateVehList(). ", e); + showServiceExceptionAlertAndWait( + "Beim Auflisten der Fahrzeuge ist ein Fehler aufgetreten"); + } catch (IOException e) { + LOG.error("IOException in updateVehList(). ", e); + showServiceExceptionAlertAndWait("Beim Laden der Fahrzeuge ist ein Fehler aufgetreten"); + } + } + + public void cancel() { + LOG.debug("Hyperlink \"schließen\" clicked"); + reset(); + this.setVisible(false); + createOperationController.setVisible(true); + } + + private void reset() { + chosenEmployees.clear(); + chosenVehicle = null; + tfEmployeeSearch.setText(""); + tfVehicleSearch.setText(""); + lEmployees.setText("-"); + lVehicles.setText("-"); + updateVehList(); + updateEmplList(); + } + + public void create() { + LOG.debug("Button \"ERSTELLEN\" clicked"); + + Set registrations = new HashSet<>(); + try { + if (chosenVehicle == null) { + throw new InvalidVehicleException("no Vehicle"); + } + for (Employee employee : chosenEmployees) { + registrations.add( + Registration.builder() + .id(chosenVehicle.id()) + .employee(employee) + .start( + LocalDateTime.of( + LocalDate.now(), + LocalTime.of(cbStart.getValue(), 0)) + .toInstant(OffsetDateTime.now().getOffset())) + .end( + LocalDateTime.of( + LocalDate.now(), + LocalTime.of(cbEnd.getValue(), 0)) + .toInstant(OffsetDateTime.now().getOffset())) + .build()); + } + + registrationService.add(chosenVehicle.id(), registrations); + chosenEmployees.clear(); + // ((Stage) lVehicles.getScene().getWindow()).close(); + this.setVisible(false); + createOperationController.setVisible(true); + reset(); + } catch (InvalidVehicleException e) { + LOG.debug("Validation of Vehicle in Registration failed."); + showValidationErrorAlertAndWait("Das spezifizierte Fahrzeug ist nicht gültig."); + } catch (ServiceException e) { + LOG.error("ServiceException in create(). ", e); + showServiceExceptionAlertAndWait( + "Beim Erstellen der Anmeldung ist ein Fehler aufgetreten."); + } catch (InvalidRegistrationException e) { + LOG.debug("Validation of Registration failed."); + showValidationErrorAlertAndWait( + "Die gewählte Kombination von Fahrzeug und Personal ist nicht gültig!"); + } + } + + public void setVisible(boolean b) { + root.setVisible(b); + reset(); + } + + public void tfVehicleSearch_TextChanged(KeyEvent keyEvent) { + updateVehList(); + } + + public void tfEmployeeSearch_TextChanged(KeyEvent keyEvent) { + updateEmplList(); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/VehiclePaneController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/VehiclePaneController.java new file mode 100644 index 0000000..66b45d2 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/controller/VehiclePaneController.java @@ -0,0 +1,118 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee.EducationLevel; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status; +import java.io.IOException; +import java.time.Instant; +import java.util.List; +import java.util.Optional; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.text.Text; + +public class VehiclePaneController extends CustomListItemController { + + public static VehiclePaneController createVehiclePane() throws IOException { + FXMLLoader fxmlLoader = + new FXMLLoader(VehiclePaneController.class.getResource("/fxml/vehiclePane.fxml")); + Node root = fxmlLoader.load(); + VehiclePaneController result = fxmlLoader.getController(); + result.rootElement = root; + + return result; + } + + @FXML private Label txtStatus; + @FXML private Text txtType; + @FXML private Text txtNumber; + @FXML private ImageView ivNEF; + @FXML private Text txtNEF; + @FXML private ImageView ivQualification; + @FXML private Text txtQualification; + @FXML private Text txtRooftype; + @FXML private Button btnRequest; + + private Vehicle data; + + public Vehicle getData() { + return data; + } + + /** + * * Set the displayed data of this VehiclePane. + * + * @param vehicle The data to display. + * @param showStatusInfo If true, the highest qualification of the vehicle's active registration + * and the vehicle's status will be shown. + */ + public void setData(Vehicle vehicle, boolean showStatusInfo, boolean showRequestVehicle) { + txtType.setText(vehicle.type().name()); + String constrType = vehicle.constructionType().name(); + txtRooftype.setText( + constrType.substring(0, 1).toUpperCase() + constrType.substring(1).toLowerCase()); + txtNumber.setText("-" + vehicle.id()); + if (vehicle.hasNef()) { + ivNEF.setImage(new Image("images/NEF.png")); + txtNEF.setText("hat NEF-Halterung"); + } else { + ivNEF.setImage(new Image("images/NotNEF.png")); + txtNEF.setText("keine NEF-Halterung"); + } + + if (showRequestVehicle) { + btnRequest.setVisible(true); + btnRequest.setManaged(true); + } else { + btnRequest.setVisible(false); + btnRequest.setManaged(false); + } + + if (showStatusInfo) { + txtStatus.setText(vehicle.status().name()); + if (vehicle.status() == Status.FREI_FUNK || vehicle.status() == Status.FREI_WACHE) { + txtStatus.getStyleClass().add("bg-status-green"); + } else { + txtStatus.getStyleClass().add("bg-status-orange"); + } + + Instant now = Instant.now(); + List regs = vehicle.registrations(); + + if (regs == null) { + return; + } + + Optional edu = + regs.stream() + .filter(reg -> reg.start().isBefore(now) && reg.end().isAfter(now)) + .map(reg -> reg.employee().educationLevel()) + .max(EducationLevel::compareTo); + + if (!edu.isPresent()) { + return; + } + + txtQualification.setText(edu.get().name()); + } else { + txtQualification.setVisible(false); + txtQualification.setManaged(false); + ivQualification.setVisible(false); + ivQualification.setManaged(false); + + txtStatus.setVisible(false); + } + + this.data = vehicle; + } + + public Button getBtnRequest() { + return btnRequest; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDAO.java new file mode 100644 index 0000000..d8ac513 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDAO.java @@ -0,0 +1,44 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import java.util.Set; + +public interface EmployeeDAO { + + /** + * Persist the given employee. + * + * @param employee that should be stored + * @return the id that was assigned + * @throws PersistenceException if the employee could not be persisted + */ + long add(Employee employee) throws PersistenceException; + + /** + * Update the given employee. + * + * @param employee that should be updated + * @throws ElementNotFoundException if no employee with the given id exists + * @throws PersistenceException if the employee could not be updated + */ + void update(Employee employee) throws ElementNotFoundException, PersistenceException; + + /** + * Get all stored employees. + * + * @return list containing all stored employees + * @throws PersistenceException if loading the stored employees failed + */ + Set list() throws PersistenceException; + + /** + * Remove employee with the given id from the store. + * + * @param id of the employee that should be removed + * @throws ElementNotFoundException if no employee with the given id exists + * @throws PersistenceException if the employee could not be removed + */ + void remove(long id) throws ElementNotFoundException, PersistenceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDatabaseDAO.java new file mode 100644 index 0000000..889b0fc --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/EmployeeDatabaseDAO.java @@ -0,0 +1,144 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee.EducationLevel; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; +import org.springframework.stereotype.Repository; + +@Repository +public class EmployeeDatabaseDAO implements EmployeeDAO { + + private JDBCConnectionManager jdbcConnectionManager; + + public EmployeeDatabaseDAO(JDBCConnectionManager jdbcConnectionManager) { + this.jdbcConnectionManager = jdbcConnectionManager; + } + + private long createEmployeeVersion(Connection con, Employee e) + throws PersistenceException, SQLException { + String sql = + "INSERT INTO EmployeeVersion(name, birthday, educationLevel, isDriver, isPilot) " + + "VALUES(?, ?, ?, ?, ?)"; + + try (PreparedStatement pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setString(1, e.name()); + pstmt.setObject(2, e.birthday()); + pstmt.setInt(3, e.educationLevel().ordinal()); + pstmt.setBoolean(4, e.isDriver()); + pstmt.setBoolean(5, e.isPilot()); + pstmt.executeUpdate(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + if (!rs.next()) throw new PersistenceException("Failed to insert EmployeeVersion"); + + return rs.getLong(1); + } + } + } + + @Override + public long add(Employee employee) throws PersistenceException { + String sql = "INSERT INTO Employee(version) VALUES(?)"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + + long versionId = createEmployeeVersion(con, employee); + + try (PreparedStatement pstmt = + con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setLong(1, versionId); + pstmt.executeUpdate(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + if (!rs.next()) { + con.rollback(); + throw new PersistenceException("Failed to insert Employee"); + } + + con.commit(); + return rs.getLong(1); + } + } + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public void update(Employee employee) throws ElementNotFoundException, PersistenceException { + String sql = "UPDATE Employee SET version = ? WHERE id = ?"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + + long versionId = createEmployeeVersion(con, employee); + + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setLong(1, versionId); + pstmt.setLong(2, employee.id()); + + if (pstmt.executeUpdate() != 1) { + con.rollback(); + throw new ElementNotFoundException("No such employeeId exists"); + } + } + + con.commit(); + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public Set list() throws PersistenceException { + String sql = + "SELECT emp.id, v.name, v.birthday, v.educationLevel, v.isDriver, v.isPilot " + + "FROM employee emp " + + "JOIN EmployeeVersion v ON v.id = emp.version"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + Set employees = new HashSet<>(); + + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + try (ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + employees.add( + Employee.builder() + .id(rs.getLong(1)) + .name(rs.getString(2)) + .birthday(rs.getObject(3, LocalDate.class)) + .educationLevel(EducationLevel.valueOf(rs.getString(4))) + .isDriver(rs.getBoolean(5)) + .isPilot(rs.getBoolean(6)) + .build()); + } + } + } + + return employees; + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + @Override + public void remove(long id) throws ElementNotFoundException, PersistenceException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDAO.java new file mode 100644 index 0000000..c0ef5d4 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDAO.java @@ -0,0 +1,48 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import java.util.EnumSet; +import java.util.Set; + +public interface OperationDAO { + + /** + * Persist the given operation. + * + * @param operation that should be stored + * @return the id that was assigned + * @throws PersistenceException if the operation could not be persisted + */ + long add(Operation operation) throws PersistenceException; + + /** + * Update the given operation. + * + * @param operation that should be updated + * @throws ElementNotFoundException if no operation with the given id exists + * @throws PersistenceException if the operation could not be updated + */ + void update(Operation operation) throws ElementNotFoundException, PersistenceException; + + /** + * Returns the operation with the given id. + * + * @param operationId id of the operation that should be returned + * @return operation with the given id + * @throws ElementNotFoundException if no operation with the given id exists + * @throws PersistenceException if the operation could not be loaded + */ + Operation get(long operationId) throws ElementNotFoundException, PersistenceException; + + /** + * Get all stored operations with matching status. + * + * @param statuses set containing all statuses that should be matched + * @return list containing all matched operations + * @throws PersistenceException if loading the stored operations failed + */ + Set list(EnumSet statuses) throws PersistenceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDatabaseDAO.java new file mode 100644 index 0000000..1641720 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/OperationDatabaseDAO.java @@ -0,0 +1,221 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Severity; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Repository; + +@Repository +public class OperationDatabaseDAO implements OperationDAO { + + private JDBCConnectionManager jdbcConnectionManager; + private VehicleDAO vehicleDAO; + + public OperationDatabaseDAO( + JDBCConnectionManager jdbcConnectionManager, VehicleDAO vehicleDAO) { + this.jdbcConnectionManager = jdbcConnectionManager; + this.vehicleDAO = vehicleDAO; + } + + @Override + public long add(@NonNull Operation o) throws PersistenceException { + String sql = + "INSERT INTO Operation(opCode, severity, created, destination, additionalInfo," + + " status) VALUES (?, ?, ?, ?, ?, ?)"; + String sql2 = "INSERT INTO VehicleOperation(vehicleId, operationId) VALUES (?, ?)"; + long operationId; + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setString(1, o.opCode()); + pstmt.setInt(2, o.severity().ordinal()); + pstmt.setObject(3, OffsetDateTime.ofInstant(o.created(), ZoneId.systemDefault())); + pstmt.setString(4, o.destination()); + pstmt.setString(5, o.additionalInfo()); + pstmt.setInt(6, o.status().ordinal()); + pstmt.executeUpdate(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + if (!rs.next()) throw new PersistenceException("Failed to persist operation"); + + operationId = rs.getLong(1); + } + } + + try (PreparedStatement pstmt = con.prepareStatement(sql2)) { + pstmt.setLong(2, operationId); + + for (long id : (Iterable) o.vehicles().stream().map(Vehicle::id)::iterator) { + pstmt.setLong(1, id); + pstmt.addBatch(); + } + + pstmt.executeBatch(); + } + con.commit(); + return operationId; + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public void update(@NonNull Operation o) throws ElementNotFoundException, PersistenceException { + // Note this will, by design, not update created + String sql = + "UPDATE Operation SET opCode = ?, severity = ?, destination = ?," + + " additionalInfo = ?, status = ? WHERE id = ?"; + String sql2 = "DELETE FROM VehicleOperation WHERE operationId = ?"; + String sql3 = "INSERT INTO VehicleOperation(vehicleId, operationId) VALUES (?, ?)"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setString(1, o.opCode()); + pstmt.setInt(2, o.severity().ordinal()); + pstmt.setString(3, o.destination()); + pstmt.setString(4, o.additionalInfo()); + pstmt.setInt(5, o.status().ordinal()); + pstmt.setLong(6, o.id()); + + if (pstmt.executeUpdate() != 1) + throw new ElementNotFoundException("No such operationId exists"); + } + + try (PreparedStatement pstmt = con.prepareStatement(sql2)) { + pstmt.setLong(1, o.id()); + pstmt.executeUpdate(); + } + + try (PreparedStatement pstmt = con.prepareStatement(sql3)) { + pstmt.setLong(2, o.id()); + + for (long id : (Iterable) o.vehicles().stream().map(Vehicle::id)::iterator) { + pstmt.setLong(1, id); + pstmt.addBatch(); + } + + pstmt.executeBatch(); + } + con.commit(); + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public Operation get(long operationId) throws ElementNotFoundException, PersistenceException { + String sql = "Select * from operation where id = ?"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setLong(1, operationId); + pstmt.execute(); + + try (ResultSet rs = pstmt.getResultSet()) { + if (!rs.next()) + throw new ElementNotFoundException("No such element could be found"); + + return operationFromRS(rs); + } + } + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + @Override + public Set list(EnumSet statuses) throws PersistenceException { + // This hack exists because H2 currently has a bug that prevents IN (?) with an array of + // ids, i.e. pstmt.setArray(1, con.createArrayOf("INT", intarray) from working. See + // commented code below. + + // SELECT * FROM Operation WHERE status IN ('COMPLETED', 'CANCELLED') is BUGGED on H2! + // for this reason we use the ordinal values instead + String str = + statuses.stream() + .map(e -> Integer.toString(e.ordinal())) + .collect(Collectors.joining(",")); + + String sql = "SELECT * FROM Operation WHERE status IN (" + str + ")"; + Set operations = new HashSet<>(); + + try { + Connection con = jdbcConnectionManager.getConnection(); + + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + // Object[] arr = statuses.stream().map(Enum::ordinal).toArray(); + // pstmt.setArray(1, con.createArrayOf("INT", arr)); + + try (ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) operations.add(operationFromRS(rs)); + } + } + + return operations; + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + private Operation operationFromRS(ResultSet rs) throws PersistenceException, SQLException { + Long operationId = rs.getLong("id"); + + return Operation.builder() + .id(operationId) + .opCode(rs.getString("opCode")) + .severity(Severity.valueOf(rs.getString("severity"))) + .status(Status.valueOf(rs.getString("status"))) + .vehicles(getVehiclesFromOperationId(operationId)) + .created((rs.getObject("created", OffsetDateTime.class)).toInstant()) + .destination(rs.getString("destination")) + .additionalInfo(rs.getString("additionalInfo")) + .build(); + } + + private Set getVehiclesFromOperationId(long operationId) throws PersistenceException { + String sql = "SELECT vehicleId FROM VehicleOperation WHERE operationId = ?"; + Set vehicles = new HashSet<>(); + + try { + Connection con = jdbcConnectionManager.getConnection(); + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setLong(1, operationId); + pstmt.execute(); + + try (ResultSet rs = pstmt.getResultSet()) { + while (rs.next()) { + vehicles.add(vehicleDAO.get(rs.getLong("vehicleId"))); + } + } + } + } catch (SQLException e) { + throw new PersistenceException(e); + } catch (ElementNotFoundException e) { + throw new PersistenceException("VehicleOperation contained nonexistent vehicle", e); + } + + return vehicles; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDAO.java new file mode 100644 index 0000000..02e742c --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDAO.java @@ -0,0 +1,28 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import java.util.Set; + +public interface RegistrationDAO { + + /** + * Persist the given registration. + * + * @param vehicleId the id of the target vehicle + * @param registrations that should be stored + * @return a list of the ids that were assigned + * @throws PersistenceException if the registration could not be persisted + */ + Set add(long vehicleId, Set registrations) throws PersistenceException; + + /** + * Make registration with the given id inactive. + * + * @param id of the registration that should be made inactive + * @throws ElementNotFoundException if no registration with the given id exists + * @throws PersistenceException if the registration could not be made inactive + */ + void remove(long id) throws ElementNotFoundException, PersistenceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDatabaseDAO.java new file mode 100644 index 0000000..1006a33 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/RegistrationDatabaseDAO.java @@ -0,0 +1,130 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +@Repository +public class RegistrationDatabaseDAO implements RegistrationDAO { + + private JDBCConnectionManager jdbcConnectionManager; + private EmployeeDAO employeePersistence; + + @Autowired + public RegistrationDatabaseDAO( + JDBCConnectionManager jdbcConnectionManager, EmployeeDAO employeePersistence) { + this.jdbcConnectionManager = jdbcConnectionManager; + this.employeePersistence = employeePersistence; + } + + @Override + public Set add(long vehicleId, Set registrations) + throws PersistenceException { + String sql = + "INSERT INTO Registration (vehicleId, employeeId, start, end, active) VALUES (?,?,?,?,?)"; + String sql2 = "UPDATE Vehicle SET status = 'FREI_WACHE' WHERE id = ?;"; + + Set vehicleIds = new HashSet<>(); + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + + try (PreparedStatement pstmt = + con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setLong(1, vehicleId); + + for (Registration r : registrations) { + pstmt.setLong(2, r.employee().id()); + pstmt.setObject(3, OffsetDateTime.ofInstant(r.start(), ZoneId.systemDefault())); + pstmt.setObject(4, OffsetDateTime.ofInstant(r.end(), ZoneId.systemDefault())); + pstmt.setBoolean(5, true); + pstmt.addBatch(); + } + + pstmt.executeBatch(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + while (rs.next()) vehicleIds.add(rs.getLong(1)); + } + } + + try (PreparedStatement pstmt = con.prepareStatement(sql2)) { + pstmt.setLong(1, vehicleId); + if (pstmt.executeUpdate() != 1) { + con.rollback(); + throw new PersistenceException("Failed to persist registration"); + } + } + + con.commit(); + return vehicleIds; + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public void remove(long id) throws ElementNotFoundException, PersistenceException { + throw new UnsupportedOperationException(); + } + + protected List list(long vehicleId) throws PersistenceException { + String sql = "SELECT * FROM Registration WHERE vehicleId = ?"; + + List registrationList = new ArrayList<>(); + try { + Connection con = jdbcConnectionManager.getConnection(); + + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setLong(1, vehicleId); + + try (ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + long employeeId = rs.getLong("employeeId"); + // TODO: replace the following with employeePersistence.get once implemented + Employee emp = + employeePersistence + .list() + .stream() + .filter(employee -> employee.id() == employeeId) + .findAny() + .orElse(null); + Registration registration = + Registration.builder() + .id(rs.getLong("id")) + .start( + (rs.getObject("start", OffsetDateTime.class)) + .toInstant()) + .end( + (rs.getObject("end", OffsetDateTime.class)) + .toInstant()) + .employee(emp) + .build(); + registrationList.add(registration); + } + } + } + + return registrationList; + } catch (SQLException e) { + throw new PersistenceException(e); + } + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDAO.java new file mode 100644 index 0000000..ed24498 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDAO.java @@ -0,0 +1,54 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import java.util.Set; + +public interface VehicleDAO { + + /** + * Persist the given vehicle. + * + * @param vehicle that should be stored + * @return the id that was assigned + * @throws PersistenceException if the vehicle could not be persisted + */ + long add(Vehicle vehicle) throws PersistenceException; + + /** + * Update the given vehicle. + * + * @param vehicle that should be updated + * @throws ElementNotFoundException if no vehicle with the given id exists + * @throws PersistenceException if the vehicle could not be updated + */ + void update(Vehicle vehicle) throws ElementNotFoundException, PersistenceException; + + /** + * Get all stored vehicles. + * + * @return list containing all stored vehicles + * @throws PersistenceException if loading the stored vehicles failed + */ + Set list() throws PersistenceException; + + /** + * Returns the vehicle with the given id. + * + * @param vehicleId id of the vehicle that should be returned + * @return vehicle with the given id + * @throws ElementNotFoundException if no vehicle with the given id exists + * @throws PersistenceException if the vehicle could not be loaded + */ + Vehicle get(long vehicleId) throws ElementNotFoundException, PersistenceException; + + /** + * Remove vehicle with the given id from the store. + * + * @param id of the vehicle that should be removed + * @throws ElementNotFoundException if no vehicle with the given id exists + * @throws PersistenceException if the vehicle could not be removed + */ + void remove(long id) throws ElementNotFoundException, PersistenceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDatabaseDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDatabaseDAO.java new file mode 100644 index 0000000..dd7c0f2 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dao/VehicleDatabaseDAO.java @@ -0,0 +1,211 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.ConstructionType; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.VehicleType; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashSet; +import java.util.Set; +import org.springframework.stereotype.Repository; + +@Repository +public class VehicleDatabaseDAO implements VehicleDAO { + + private final JDBCConnectionManager jdbcConnectionManager; + private RegistrationDatabaseDAO registrationDatabaseDao; + + public VehicleDatabaseDAO( + JDBCConnectionManager j, RegistrationDatabaseDAO registrationDatabaseDao) { + jdbcConnectionManager = j; + this.registrationDatabaseDao = registrationDatabaseDao; + } + + @Override + public long add(Vehicle v) throws PersistenceException { + String sql = + "INSERT INTO VehicleVersion (name,hasNef,constructionType,type) VALUES (?,?,?,?)"; + String sql2 = "INSERT INTO Vehicle (version,status) VALUES (?,?)"; + String sql3 = "UPDATE VehicleVersion SET name=? WHERE id=?"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + String name = ""; + long version, id; + + try (PreparedStatement pstmt = + con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setString(1, name); + pstmt.setBoolean(2, v.hasNef()); + pstmt.setInt(3, v.constructionType().ordinal()); + pstmt.setString(4, v.type().name()); + pstmt.executeUpdate(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + if (!rs.next()) + throw new PersistenceException("Failed to insert into VehicleVersion"); + + version = rs.getLong(1); + } + } + + try (PreparedStatement pstmt = + con.prepareStatement(sql2, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setLong(1, version); + pstmt.setInt(2, Status.ABGEMELDET.ordinal()); + pstmt.executeUpdate(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + if (!rs.next()) { + con.rollback(); + throw new PersistenceException("Failed to insert into Vehicle"); + } + + id = rs.getLong(1); + } + + name = v.type().name() + "-" + id; + } + + try (PreparedStatement pstmt = con.prepareStatement(sql3)) { + pstmt.setString(1, name); + pstmt.setLong(2, version); + + if (pstmt.executeUpdate() != 1) { + con.rollback(); + throw new PersistenceException("Failed to update VehicleVersion"); + } + } + + con.commit(); + return id; + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public void update(Vehicle v) throws ElementNotFoundException, PersistenceException { + String sql = "SELECT version FROM Vehicle WHERE id = ?"; + String sql2 = + "MERGE INTO VehicleVersion(name, constructionType, type, hasNef)" + + " KEY(name, constructionType, type, hasNef) VALUES(?, ?, ?, ?)"; + String sql3 = "UPDATE Vehicle SET version = ?, status = ? WHERE id = ?"; + + long versionId; + + try { + Connection con = jdbcConnectionManager.getConnection(); + con.setAutoCommit(false); + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setLong(1, v.id()); + + try (ResultSet rs = pstmt.executeQuery()) { + if (!rs.next()) throw new ElementNotFoundException("No such vehicleId exists"); + + versionId = rs.getLong(1); + } + } + + try (PreparedStatement pstmt = + con.prepareStatement(sql2, Statement.RETURN_GENERATED_KEYS)) { + pstmt.setString(1, v.type().name() + "-" + v.id()); + pstmt.setString(2, v.constructionType().name()); + pstmt.setString(3, v.type().name()); + pstmt.setBoolean(4, v.hasNef()); + pstmt.executeUpdate(); + + try (ResultSet rs = pstmt.getGeneratedKeys()) { + if (rs.next()) { + // version changed, update it + versionId = rs.getLong(1); + } + } + } + + try (PreparedStatement pstmt = con.prepareStatement(sql3)) { + pstmt.setLong(1, versionId); + pstmt.setString(2, v.status().name()); + pstmt.setLong(3, v.id()); + pstmt.executeUpdate(); + } + + con.commit(); + } catch (SQLException e) { + jdbcConnectionManager.rollbackConnection(); + throw new PersistenceException(e); + } + } + + @Override + public Set list() throws PersistenceException { + Set result = new HashSet<>(); + + String sql = + "Select * from VehicleVersion, Vehicle where VehicleVersion.id=Vehicle.version"; + + try (PreparedStatement pstmt = + jdbcConnectionManager.getConnection().prepareStatement(sql)) { + pstmt.executeQuery(); + try (ResultSet rs = pstmt.getResultSet()) { + while (rs.next()) { + result.add(vehicleFromRS(rs)); + } + } + } catch (SQLException e) { + throw new PersistenceException(e); + } + return result; + } + + @Override + public Vehicle get(long id) throws ElementNotFoundException, PersistenceException { + String sql = + "SELECT a.id, b.name, b.constructionType, b.type, a.status, b.hasNef" + + " FROM Vehicle a" + + " INNER JOIN VehicleVersion b" + + " ON version = b.id" + + " WHERE a.id = ?"; + + try { + Connection con = jdbcConnectionManager.getConnection(); + try (PreparedStatement pstmt = con.prepareStatement(sql)) { + pstmt.setLong(1, id); + + try (ResultSet rs = pstmt.executeQuery()) { + if (!rs.first()) throw new ElementNotFoundException("No such vehicle exists"); + + return vehicleFromRS(rs); + } + } + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + @Override + public void remove(long id) throws ElementNotFoundException, PersistenceException { + throw new UnsupportedOperationException(); + } + + private Vehicle vehicleFromRS(ResultSet rs) throws SQLException, PersistenceException { + return Vehicle.builder() + .id(rs.getLong("Vehicle.id")) + .name(rs.getString("name")) + .constructionType(ConstructionType.values()[rs.getInt("constructionType")]) + .type(VehicleType.valueOf(rs.getString("type"))) + .status(Status.values()[rs.getInt("status")]) + .hasNef(rs.getBoolean("hasNef")) + .registrations(registrationDatabaseDao.list(rs.getLong("id"))) + .build(); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Employee.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Employee.java new file mode 100644 index 0000000..f45550e --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Employee.java @@ -0,0 +1,51 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto; + +import com.google.auto.value.AutoValue; +import java.time.LocalDate; + +@AutoValue +public abstract class Employee { + public enum EducationLevel { + RS, + NFS, + NKV, + NKA, + NKI, + NA + } + + public abstract long id(); + + public abstract String name(); + + public abstract LocalDate birthday(); + + public abstract EducationLevel educationLevel(); + + public abstract boolean isDriver(); + + public abstract boolean isPilot(); + + public static Builder builder() { + return new AutoValue_Employee.Builder().id(0); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder id(long id); + + public abstract Builder name(String name); + + public abstract Builder birthday(LocalDate birthday); + + public abstract Builder educationLevel(EducationLevel educationLevel); + + public abstract Builder isDriver(boolean isDriver); + + public abstract Builder isPilot(boolean isPilot); + + public abstract Employee build(); + } + + public abstract Builder toBuilder(); +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/EmployeeValidator.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/EmployeeValidator.java new file mode 100644 index 0000000..b03fa04 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/EmployeeValidator.java @@ -0,0 +1,23 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto; + +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; + +public class EmployeeValidator { + + public static boolean validate(Employee employee) throws InvalidEmployeeException { + + if (employee.name() == null || employee.name().trim().length() == 0) { + throw new InvalidEmployeeException("Name darf nicht leer sein!"); + } + + if (employee.birthday() == null) { + throw new InvalidEmployeeException("Geburtsdatum darf nicht leer sein!"); + } + + if (employee.educationLevel() == null) { + throw new InvalidEmployeeException("Ausbildungsgrad darf nicht leer sein!"); + } + + return true; + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Operation.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Operation.java new file mode 100644 index 0000000..e119622 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Operation.java @@ -0,0 +1,70 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto; + +import com.google.auto.value.AutoValue; +import java.time.Instant; +import java.util.Set; +import javax.annotation.Nullable; + +@AutoValue +public abstract class Operation { + public enum Severity { + A, + B, + C, + D, + E, + O, + } + + public enum Status { + ACTIVE, + COMPLETED, + CANCELLED, + } + + public abstract long id(); + + public abstract String opCode(); + + @Nullable + public abstract Severity severity(); + + public abstract Status status(); + + public abstract Set vehicles(); + + @Nullable + public abstract Instant created(); + + public abstract String destination(); + + @Nullable + public abstract String additionalInfo(); + + public static Builder builder() { + return new AutoValue_Operation.Builder().id(0); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder id(long id); + + public abstract Builder opCode(String opCode); + + public abstract Builder severity(Severity severity); + + public abstract Builder status(Status status); + + public abstract Builder vehicles(Set vehicles); + + public abstract Builder created(Instant created); + + public abstract Builder destination(String destination); + + public abstract Builder additionalInfo(String additionalInfo); + + public abstract Operation build(); + } + + public abstract Builder toBuilder(); +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Registration.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Registration.java new file mode 100644 index 0000000..a12c038 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Registration.java @@ -0,0 +1,34 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto; + +import com.google.auto.value.AutoValue; +import java.time.Instant; + +@AutoValue +public abstract class Registration { + public abstract long id(); + + public abstract Instant start(); + + public abstract Instant end(); + + public abstract Employee employee(); + + public static Builder builder() { + return new AutoValue_Registration.Builder().id(0); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder id(long id); + + public abstract Builder start(Instant start); + + public abstract Builder end(Instant end); + + public abstract Builder employee(Employee employee); + + public abstract Registration build(); + } + + public abstract Builder toBuilder(); +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/RegistrationValidator.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/RegistrationValidator.java new file mode 100644 index 0000000..9512f64 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/RegistrationValidator.java @@ -0,0 +1,174 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee.EducationLevel; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.VehicleType; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +public class RegistrationValidator { + + private RegistrationValidator() {} + + public static void validate(Vehicle vehicle, Set registrations) + throws InvalidVehicleException, InvalidRegistrationException { + /* + Vehicles and Employees are assumed to be valid. + They have been checked at creation, and for them to be checked again, access to + VehicleValidator and EmployeeValidator are needed, which are not available at this time. + */ + /* + The method used here goes as follows: All given employees are inspected in regards to their + qualifications, and added to the appropriate lists of the roles they could fill. + For example, an NFS, who is also a driver, would be added to the lists driverIds, nfsIds + and rsIds (because an NFS can always substitute an RS). + Afterwards, the number of people is checked according to the chosen vehicle type, and if + the number is okay, the program tries to find a valid combination of roles for the vehicle. + For example, for an RTW, first a driver is chosen, their ID marked as found in the aptly + titled HashMap, and then for the second RS, the list of RS is checked, excluding the chosen + driver. If no other valid RS is found, the next possible driver is chosen, and so on. If no + valid combination is found, an InvalidRegistrationException is thrown. + */ + List pilotIds = new LinkedList<>(); + List driverIds = new LinkedList<>(); + List naIds = new LinkedList<>(); + List nfsIds = new LinkedList<>(); + List rsIds = new LinkedList<>(); + HashMap found = + new HashMap<>(); // needed later in DFS, checks that no person is chosen twice + int total = 0; + for (Registration registration : registrations) { + total++; + if (found.put(registration.employee().id(), false) != null) { + throw new InvalidRegistrationException( + "Person mit der ID: " + + registration.employee().id() + + " wurde mehrmals hinzugefügt!"); + } + if (registration.employee().isPilot()) { + pilotIds.add(registration.employee().id()); + } + if (registration.employee().isDriver()) { + driverIds.add(registration.employee().id()); + } + if (registration.employee().educationLevel() == EducationLevel.NA) { + naIds.add(registration.employee().id()); + nfsIds.add(registration.employee().id()); + rsIds.add(registration.employee().id()); + } else if (isNFS(registration.employee())) { + nfsIds.add(registration.employee().id()); + rsIds.add(registration.employee().id()); + } else { // only RS left + rsIds.add(registration.employee().id()); + } + } + if (total <= 0) { + throw new InvalidRegistrationException("Kein Personal ausgewählt!"); + } + if (vehicle.type() == VehicleType.NAH) { + /* + NAH + 1 Pilot + 1 NFS + 1 NA + 3-4 Personen + */ + if (total < 3) { + throw new InvalidRegistrationException("Zu wenig Personal für NAH!"); + } else if (total > 4) { + throw new InvalidRegistrationException("Zu viel Personal für NAH!"); + } + for (long pilot_id : pilotIds) { + found.put(pilot_id, true); + for (long na_id : naIds) { + if (found.get(na_id)) continue; + found.put(na_id, true); + for (long nfs_id : nfsIds) { + if (found.get(nfs_id)) continue; + return; + } + found.put(na_id, false); + } + found.put(pilot_id, false); + } + throw new InvalidRegistrationException( + "Keine gültige Kombination von Personen für NAH!"); + } else if (vehicle.type() == VehicleType.NEF) { + /* + NEF + 1 Driver (has to be NFS) + 1 NA + */ + if (total < 2) { + throw new InvalidRegistrationException("Zu wenig Personal für NEF!"); + } else if (total > 3) { + throw new InvalidRegistrationException("Zu viel Personal für NEF!"); + } + for (long driver_id : driverIds) { + if (!nfsIds.contains(driver_id)) + continue; // if possible driver is not NFS, skip him + found.put(driver_id, true); + for (long na_id : naIds) { + if (found.get(na_id)) continue; + return; + } + found.put(driver_id, false); + } + throw new InvalidRegistrationException( + "Keine gültige Kombination von Personen für NEF!"); + } else if (vehicle.type() == VehicleType.BKTW) { + /* + BKTW + 1 Driver + */ + if (total > 3) { + throw new InvalidRegistrationException("Zu viel Personal für BKTW!"); + } + if (!driverIds.isEmpty()) { + return; + } + throw new InvalidRegistrationException("Kein Fahrer gefunden für BKTW!"); + } else { // KTW or RTW, both have the same requirements + /* + RTW/KTW + 1 Driver + 1 RS + */ + if (total < 2) { + throw new InvalidRegistrationException( + "Zu wenig Personal für " + vehicle.type().name() + "!"); + } else if (total > 4) { + throw new InvalidRegistrationException( + "Zu viel Persoanl für " + vehicle.type().name() + "!"); + } + for (long driver_id : driverIds) { // driver includes rs + found.put(driver_id, true); + for (long rs_id : rsIds) { + if (found.get(rs_id)) continue; + return; + } + } + throw new InvalidRegistrationException( + "Keine gültige Kombination von Personen für " + vehicle.type().name() + "!"); + } + } + + private static boolean isNFS(Employee employee) { + EducationLevel educationLevel = employee.educationLevel(); + switch (educationLevel) { + case NFS: + return true; + case NKA: + return true; + case NKI: + return true; + case NKV: + return true; + default: + return false; + } + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Vehicle.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Vehicle.java new file mode 100644 index 0000000..c2033f5 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/dto/Vehicle.java @@ -0,0 +1,73 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto; + +import com.google.auto.value.AutoValue; +import java.util.List; +import javax.annotation.Nullable; + +@AutoValue +public abstract class Vehicle { + public enum ConstructionType { + NORMAL, + HOCHDACH, + MITTELHOCHDACH, + } + + public enum VehicleType { + BKTW, + KTW_B, + KTW, + RTW, + NEF, + NAH, + } + + public enum Status { + ABGEMELDET, + FREI_WACHE, + FREI_FUNK, + ZUM_BERUFUNGSORT, + AM_BERUFUNGSORT, + ZUM_ZIELORT, + AM_ZIELORT, + } + + public abstract long id(); + + public abstract String name(); + + public abstract ConstructionType constructionType(); + + public abstract VehicleType type(); + + public abstract Status status(); + + public abstract boolean hasNef(); + + @Nullable + public abstract List registrations(); + + public static Builder builder() { + return new AutoValue_Vehicle.Builder().id(0); + } + + @AutoValue.Builder + public abstract static class Builder { + public abstract Builder id(long id); + + public abstract Builder name(String name); + + public abstract Builder constructionType(ConstructionType constructionType); + + public abstract Builder type(VehicleType type); + + public abstract Builder status(Status status); + + public abstract Builder hasNef(boolean hasNef); + + public abstract Builder registrations(List registrations); + + public abstract Vehicle build(); + } + + public abstract Builder toBuilder(); +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java new file mode 100644 index 0000000..fa4d0e6 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java @@ -0,0 +1,46 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.Set; + +public interface EmployeeService { + + /** + * Add given employee to the store. + * + * @param employee that should be added to the store + * @return the id that was assigned + * @throws InvalidEmployeeException if the employee is invalid + * @throws ServiceException if the employee could not be persisted + */ + long add(Employee employee) throws InvalidEmployeeException, ServiceException; + + /** + * Update the given employee. + * + * @param employee that should be updated + * @return the updated employee + * @throws InvalidEmployeeException if the employee is invalid + * @throws ServiceException if the updated employee could not be persisted + */ + Employee update(Employee employee) throws InvalidEmployeeException, ServiceException; + + /** + * Get all stored employees. + * + * @return list containing all stored employees + * @throws ServiceException if loading the stored employees failed + */ + Set list() throws ServiceException; + + /** + * Remove employee with the given id from the store. + * + * @param id of the employee that should be removed + * @throws InvalidEmployeeException if given employee id is invalid or does not exist + * @throws ServiceException if the employee could not be removed from the store + */ + void remove(long id) throws InvalidEmployeeException, ServiceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java new file mode 100644 index 0000000..945fb49 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java @@ -0,0 +1,59 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.EmployeeDAO; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.EmployeeValidator; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.Set; +import org.springframework.stereotype.Service; + +@Service +public class EmployeeServiceImpl implements EmployeeService { + + private final EmployeeDAO employeePersistence; + + public EmployeeServiceImpl(EmployeeDAO employeePersistence) { + this.employeePersistence = employeePersistence; + } + + @Override + public long add(Employee employee) throws InvalidEmployeeException, ServiceException { + + EmployeeValidator.validate(employee); + try { + return employeePersistence.add(employee); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + } + + @Override + public Employee update(Employee employee) throws InvalidEmployeeException, ServiceException { + + EmployeeValidator.validate(employee); + try { + employeePersistence.update(employee); + return employee; + } catch (ElementNotFoundException | PersistenceException e) { + throw new ServiceException(e); + } + } + + @Override + public Set list() throws ServiceException { + + try { + return employeePersistence.list(); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + } + + @Override + public void remove(long id) throws InvalidEmployeeException, ServiceException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java new file mode 100644 index 0000000..ca1dce9 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java @@ -0,0 +1,70 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.EnumSet; +import java.util.Set; +import java.util.SortedSet; + +public interface OperationService { + + /** + * Add given operation to the store. + * + * @param operation that should be added to the store + * @return the id that was assigned + * @throws InvalidOperationException if the operation is invalid + * @throws ServiceException if the operation could not be persisted + */ + long add(Operation operation) throws InvalidOperationException, ServiceException; + + /** + * Request new vehicles to the given operation. + * + * @param operationId id of the operation that the vehicles should be send to + * @param vehicleIds the ids of the vehicles that should be send to the given operation + * @throws InvalidOperationException if the operationId is invalid or does not exist + * @throws InvalidVehicleException if one of the vehicle ids is invalid or does not exist + * @throws ServiceException if the vehicles could not be loaded or the operation could not be + * persisted + */ + void requestVehicles(long operationId, Set vehicleIds) + throws InvalidOperationException, InvalidVehicleException, ServiceException; + + /** + * Completes the given operation with the specified status. + * + * @param operationId id of the operation that should be completed + * @param status of the completed operation, either {@link Status#COMPLETED} or {@link + * Status#CANCELLED} + * @throws InvalidOperationException if the operationId is invalid or does not exist + * @throws ServiceException if the operation could not be persisted + */ + void complete(long operationId, Status status) + throws InvalidOperationException, ServiceException; + + /** + * Get all available vehicles, sorted by how well they fit to the given opCode, starting with + * the best fitting. + * + * @param opCode the operation code that is used to determine the ranking + * @return a sorted list containing all available vehicles + * @throws InvalidOperationException if the opCode is invalid + * @throws ServiceException if loading the stored vehicles failed + */ + SortedSet rankVehicles(String opCode) + throws InvalidOperationException, ServiceException; + + /** + * Get all stored operations with matching status. + * + * @param statuses set containing all statuses that should be matched + * @return list containing all matched operations + * @throws ServiceException if loading the stored operations failed + */ + Set list(EnumSet statuses) throws ServiceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java new file mode 100644 index 0000000..baae598 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java @@ -0,0 +1,286 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.OperationDAO; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.VehicleDAO; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Severity; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.VehicleType; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class OperationServiceImpl implements OperationService { + + private static final Logger LOG = LoggerFactory.getLogger(OperationServiceImpl.class); + + private final OperationDAO operationDAO; + private final VehicleDAO vehicleDAO; + private final VehicleService vehicleService; + + public OperationServiceImpl( + OperationDAO operationDAO, VehicleDAO vehicleDAO, VehicleService vehicleService) { + this.operationDAO = operationDAO; + this.vehicleDAO = vehicleDAO; + this.vehicleService = vehicleService; + } + + @Override + public long add(Operation o) throws InvalidOperationException, ServiceException { + if (o.created() != null) { + throw new InvalidOperationException("Erstellungszeitpunkt darf nicht gesetzt sein"); + } + + if (o.severity() != null) { + throw new InvalidOperationException("Der Schweregrad darf nicht gesetzt sein"); + } + + if (o.id() != 0) { + throw new InvalidOperationException("Einsatz-ID muss 0 sein"); + } + + if (o.status() != Status.ACTIVE) + LOG.info("Status was set but will be overridden"); // TODO: nullable instead?? + + try { + for (long id : (Iterable) o.vehicles().stream().map(Vehicle::id)::iterator) { + Vehicle v = vehicleDAO.get(id); + VehicleServiceImpl.validateVehicle(v); + + if (v.status() != Vehicle.Status.FREI_FUNK + && v.status() != Vehicle.Status.FREI_WACHE) + throw new InvalidOperationException("Fahrzeug nicht verfügbar: " + v.status()); + } + + validateOperation(o); + + return operationDAO.add( + o.toBuilder() + .created(Instant.now()) + .severity(extractSeverityFromOpCode(o.opCode())) + .status(Status.ACTIVE) + .build()); + } catch (PersistenceException e) { + throw new ServiceException(e); + } catch (InvalidVehicleException e) { + // already logged as invalid vehicle + throw new InvalidOperationException("Enthaltenes Fahrzeug ist ungültig", e); + } catch (ElementNotFoundException e) { + throw new InvalidOperationException("Enthaltenes Fahrzeug existiert nicht", e); + } + } + + @Override + public void requestVehicles(long operationId, Set vehicleIds) + throws InvalidOperationException, InvalidVehicleException, ServiceException { + Set vs = new HashSet<>(); + + try { + if (operationId <= 0) { + throw new InvalidOperationException("Einsatz-ID ist ungültig"); + } + Operation o = operationDAO.get(operationId); + validateOperation(o); + + if (o.opCode().trim().isEmpty() + || extractSeverityFromOpCode(o.opCode()) != o.severity()) { + throw new InvalidOperationException("Einsatzcode ist ungültig"); + } + + if (o.status() != Status.ACTIVE) { + throw new InvalidOperationException("Einsatz ist ungültig"); + } + + if (o.created() == null) { + throw new InvalidOperationException("Erstellungszeitpunkt darf nicht leer sein"); + } + + for (Long id : vehicleIds) { + if (id <= 0) { + throw new InvalidVehicleException("Fahrzeug-ID ist ungültig"); + } + + try { + Vehicle v = vehicleDAO.get(id); + VehicleServiceImpl.validateVehicle(v); + if (v.status() != Vehicle.Status.FREI_FUNK + && v.status() != Vehicle.Status.FREI_WACHE) + throw new InvalidOperationException( + "Fahrzeug nicht verfügbar: " + v.status()); + + vs.add(v); + } catch (ElementNotFoundException e) { + throw new InvalidVehicleException("VehicleId ist invalid"); + } + } + + vs.addAll(o.vehicles()); + if (vs.equals(o.vehicles())) return; + + operationDAO.update(o.toBuilder().vehicles(vs).build()); + } catch (ElementNotFoundException e) { + throw new InvalidOperationException("Kein Einsatz mit dieser ID existiert"); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + } + + @Override + public void complete(long operationId, Status status) + throws InvalidOperationException, ServiceException { + try { + Operation o = operationDAO.get(operationId); + operationDAO.update(o.toBuilder().status(status).build()); + } catch (ElementNotFoundException e) { + throw new InvalidOperationException(e); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + } + + @Override + public SortedSet rankVehicles(String opCode) + throws InvalidOperationException, ServiceException { + Set vehicles = + vehicleService.list(EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET))); + + List> priorities = new ArrayList<>(); + Predicate ktw = v -> v.type() == VehicleType.KTW; + Predicate rtwNoNEF = v -> v.type() == VehicleType.RTW && !v.hasNef(); + Predicate rtwNEF = v -> v.type() == VehicleType.RTW && v.hasNef(); + Predicate nef = v -> v.type() == VehicleType.NEF; + Predicate nah = v -> v.type() == VehicleType.NAH; + + switch (extractSeverityFromOpCode(opCode)) { + case A: + // fallthrough + case B: + // fallthrough + case O: + priorities.add(ktw); + priorities.add(rtwNoNEF); + priorities.add(rtwNEF); + break; + case C: + priorities.add(rtwNEF); + priorities.add(rtwNoNEF); + priorities.add(ktw); + break; + case D: + priorities.add(rtwNEF); + priorities.add(nef); + priorities.add(nah); + priorities.add(rtwNoNEF); + priorities.add(ktw); + break; + case E: + priorities.add(nah); + priorities.add(nef); + priorities.add(rtwNEF); + priorities.add(rtwNoNEF); + priorities.add(ktw); + break; + } + + Comparator vehicleComparator = + (v1, v2) -> { + for (Predicate priority : priorities) { + if (priority.test(v1)) { + return -1; + } + if (priority.test(v2)) { + return +1; + } + } + return 0; + }; + + Supplier> supplier = () -> new TreeSet<>(vehicleComparator); + + return vehicles.stream().collect(Collectors.toCollection(supplier)); + } + + @Override + public Set list(EnumSet statuses) throws ServiceException { + try { + Set operations = operationDAO.list(statuses); + for (Operation o : operations) validateOperation(o); + + return operations; + } catch (PersistenceException e) { + throw new ServiceException(e); + } catch (InvalidOperationException e) { + // database returned invalid values + throw new ServiceException("DB returned invalid operation", e); + } + } + + private static void validateOperation(Operation o) throws InvalidOperationException { + if (o.vehicles().isEmpty()) { + throw new InvalidOperationException( + "Es muss mindestens ein Fahrzeug ausgewählt werden!"); + } + + for (Vehicle v : o.vehicles()) { + try { + VehicleServiceImpl.validateVehicle(v); + } catch (InvalidVehicleException e) { + throw new InvalidOperationException("Fahrzeug " + v.name() + " ist ungültig", e); + } + + // TODO: validate if NEF/RTW/NAH conditions? + } + + Instant created = o.created(); + if (created != null && created.isAfter(Instant.now())) { + throw new InvalidOperationException("Einsatz wurde in der Zukunft erstellt"); + } + + if (o.destination() == null || o.destination().trim().isEmpty()) { + throw new InvalidOperationException("Adresse darf nicht leer sein"); + } + + if (o.destination().length() > 100) { + throw new InvalidOperationException("Adresse darf 100 Zeichen nicht überschreiten"); + } + + if (o.additionalInfo() != null && o.additionalInfo().length() > 100) { + throw new InvalidOperationException("Anmerkung darf 100 Zeichen nicht überschreiten"); + } + } + + private static final Pattern opCodePattern = + Pattern.compile("(?:\\w{1,3}-\\d{0,2})([ABCDEO])(?:.*)"); + + private static Severity extractSeverityFromOpCode(String opCode) + throws InvalidOperationException { + Matcher m = opCodePattern.matcher(opCode); + + if (!m.matches()) { + throw new InvalidOperationException("Einsatzcode ist ungültig"); + } + + return Severity.valueOf(m.group(1)); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java new file mode 100644 index 0000000..027417f --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java @@ -0,0 +1,32 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.Set; + +public interface RegistrationService { + + /** + * Register employee to a vehicle. + * + * @param vehicleId the id of the target vehicle + * @param registrations that should be added to the vehicle + * @return the list of ids that were assigned + * @throws InvalidVehicleException if the vehicleId is invalid or does not exist + * @throws InvalidRegistrationException if the registration is invalid + * @throws ServiceException if the registration could not be persisted + */ + Set add(long vehicleId, Set registrations) + throws InvalidVehicleException, InvalidRegistrationException, ServiceException; + + /** + * Remove given registration from the store. + * + * @param registrationId the id of the registration that should be removed + * @throws InvalidRegistrationException if the registration is invalid or does not exist + * @throws ServiceException if the registration could not be removed from the store + */ + void remove(long registrationId) throws InvalidRegistrationException, ServiceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java new file mode 100644 index 0000000..3ec69e7 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java @@ -0,0 +1,52 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.RegistrationDAO; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.VehicleDAO; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.RegistrationValidator; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class RegistrationServiceImpl implements RegistrationService { + + private final RegistrationDAO registrationDAO; + private final VehicleDAO vehicleDAO; + + @Autowired + public RegistrationServiceImpl(RegistrationDAO registrationDAO, VehicleDAO vehicleDAO) { + this.registrationDAO = registrationDAO; + this.vehicleDAO = vehicleDAO; + } + + @Override + public Set add(long vehicleId, Set registrations) + throws InvalidVehicleException, InvalidRegistrationException, ServiceException { + + if (vehicleId <= 0) throw new InvalidVehicleException("VehicleId invalid"); + + try { + Vehicle vehicle = vehicleDAO.get(vehicleId); + + RegistrationValidator.validate(vehicle, registrations); + + return registrationDAO.add(vehicle.id(), registrations); + } catch (PersistenceException e) { + throw new ServiceException(e); + } catch (ElementNotFoundException e) { + throw new InvalidVehicleException(e); + } + } + + @Override + public void remove(long registrationId) throws InvalidRegistrationException, ServiceException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java new file mode 100644 index 0000000..d96dfb7 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java @@ -0,0 +1,49 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.EnumSet; +import java.util.Set; + +public interface VehicleService { + + /** + * Add given vehicle to the store. + * + * @param vehicle that should be added to the store + * @return the id that was assigned + * @throws InvalidVehicleException if the vehicle is invalid + * @throws ServiceException if the vehicle could not be persisted + */ + long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException; + + /** + * Update the given vehicle. + * + * @param vehicle that should be updated + * @return the updated vehicle + * @throws InvalidVehicleException if the vehicle is invalid + * @throws ServiceException if the updated vehicle could not be persisted + */ + Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException; + + /** + * Get all stored vehicles with matching status. + * + * @param statuses set containing all statuses that should be matched + * @return list containing all stored vehicles + * @throws ServiceException if loading the stored vehicles failed + */ + Set list(EnumSet statuses) throws ServiceException; + + /** + * Remove vehicle with the given id from the store. + * + * @param id of the vehicle that should be removed + * @throws InvalidVehicleException if given vehicle id is invalid or does not exist + * @throws ServiceException if the vehicle could not be removed from the store + */ + void remove(long id) throws InvalidVehicleException, ServiceException; +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java new file mode 100644 index 0000000..6a035c6 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java @@ -0,0 +1,116 @@ +package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service; + +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.VehicleDAO; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.ConstructionType; +import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.EnumSet; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +@Service +public class VehicleServiceImpl implements VehicleService { + + private VehicleDAO vehiclePersistence; + + public VehicleServiceImpl(VehicleDAO vehiclePersistence) { + this.vehiclePersistence = vehiclePersistence; + } + + public long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException { + if (!CollectionUtils.isEmpty(vehicle.registrations())) { + throw new InvalidVehicleException( + "Fahrzeug kann nicht mit Anmeldungen erstellt werden"); + } + + validateVehicle(vehicle); + try { + vehiclePersistence.add(vehicle); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + return 0; + } + + public Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException { + validateVehicle(vehicle); + try { + vehiclePersistence.update(vehicle); + } catch (ElementNotFoundException e) { + throw new ServiceException("Element not found", e); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + return vehicle; + } + + protected static void validateVehicle(Vehicle vehicle) throws InvalidVehicleException { + switch (vehicle.type()) { + case RTW: + if (vehicle.constructionType() == ConstructionType.NORMAL) { + throw new InvalidVehicleException("RTW darf kein Normales Dach haben"); + } else if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { + throw new InvalidVehicleException("RTW darf kein Mittelhochdach haben"); + } + break; + case KTW: + if (vehicle.constructionType() == ConstructionType.NORMAL) { + throw new InvalidVehicleException("KTW darf kein Normales Dach haben"); + } + break; + case KTW_B: + if (vehicle.constructionType() == ConstructionType.NORMAL) { + throw new InvalidVehicleException("KTW-B darf kein Normales Dach haben"); + } + break; + case NEF: + if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { + throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben"); + } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) { + throw new InvalidVehicleException("NEF darf kein Hochdach haben"); + } + break; + case NAH: + if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { + throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben"); + } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) { + throw new InvalidVehicleException("NEF darf kein Hochdach haben"); + } + break; + case BKTW: + break; + default: + throw new IllegalStateException("BUG: invalid vehicle type" + vehicle.type()); + } + } + + @Override + public Set list(EnumSet statuses) throws ServiceException { + if (statuses == null) { + throw new ServiceException("Statuses may not be null"); + } + + Set vehicles; + + try { + vehicles = vehiclePersistence.list(); + } catch (PersistenceException e) { + throw new ServiceException(e); + } + + return vehicles.stream() + .filter(vehicle -> statuses.contains(vehicle.status())) + .collect(Collectors.toSet()); + } + + @Override + public void remove(long id) throws InvalidVehicleException, ServiceException { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/resources/fxml/ArchiveOperation.fxml b/src/main/resources/fxml/ArchiveOperation.fxml index 0150d81..e9549ae 100644 --- a/src/main/resources/fxml/ArchiveOperation.fxml +++ b/src/main/resources/fxml/ArchiveOperation.fxml @@ -12,7 +12,7 @@ - + diff --git a/src/main/resources/fxml/CreateOperationController.fxml b/src/main/resources/fxml/CreateOperationController.fxml index 0c82e29..56e0c90 100644 --- a/src/main/resources/fxml/CreateOperationController.fxml +++ b/src/main/resources/fxml/CreateOperationController.fxml @@ -14,7 +14,7 @@ - +