diff options
author | Tharre <tharre3@gmail.com> | 2018-05-24 20:28:05 +0200 |
---|---|---|
committer | Tharre <tharre3@gmail.com> | 2018-05-24 20:28:05 +0200 |
commit | f5bc7925a8fbbe247972a6f0e0571cc7e92fbefa (patch) | |
tree | 25c6010b1c96de0302ac618bc3aeee61100655fe /src/main/java/at/ac | |
parent | f7d14a76123911f0bced08356a0c69e61147cb1b (diff) | |
parent | 58f6ea4ad233f4cbb57b57734a5067e0856b6341 (diff) | |
download | sepm-groupproject-2.0.tar.gz sepm-groupproject-2.0.tar.xz sepm-groupproject-2.0.zip |
Merge branch 'develop'v2.0
Diffstat (limited to 'src/main/java/at/ac')
34 files changed, 2213 insertions, 916 deletions
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 01c04d3..d8365a7 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.userInterface.CreateOperationController; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.CreateOperationController; import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; import javafx.application.Application; import javafx.application.Platform; 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 new file mode 100644 index 0000000..80d9fc4 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ArchiveOperationController.java @@ -0,0 +1,127 @@ +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.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 java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedList; +import java.util.Objects; +import java.util.stream.Collectors; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import org.springframework.stereotype.Controller; + +@Controller +public class ArchiveOperationController { + @FXML private AnchorPane apDetails; + @FXML private Label lblCodeHeader; + @FXML private Hyperlink hypBack; + @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 LinkedList<Operation> list = new LinkedList<>(); + + public ArchiveOperationController(OperationService operationService) { + this.operationService = operationService; + } + + @FXML + private void initialize() { + try { + list.addAll(operationService.list(EnumSet.of(Status.CANCELLED, Status.COMPLETED))); + } catch (ServiceException e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler!"); + alert.setContentText("Die Einsätze konnten nicht geladen werden!"); + alert.showAndWait(); + } + 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 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); + setOperation(); + setDetailsVisible(true); + } + + private void setOperation() { + lblCodeHeader.setText(detailOperation.opCode()); + String date = "am "; + if (detailOperation.created() != null) { + LocalDateTime myDateTime = + LocalDateTime.ofInstant( + Objects.requireNonNull(detailOperation.created()), ZoneOffset.UTC); + date += + myDateTime.getDayOfMonth() + + "." + + myDateTime.getMonth().getValue() + + "." + + myDateTime.getYear(); + lblDate.setText(date); + } else { + lblDate.setText("---"); + } + + lblOpCode.setText(detailOperation.opCode()); + Collection<String> elements = + detailOperation.vehicles().stream().map(Vehicle::name).collect(Collectors.toList()); + String result = String.join(", ", elements); + + lblVehicles.setText(result); + lblAddress.setText(detailOperation.destination()); + + for (Vehicle vehicle : detailOperation.vehicles()) { + Button b = new Button(); + b.setPrefHeight(200); + b.setPrefWidth(600 / 2); + b.setText(vehicle.name()); + fpVehicles.getChildren().add(b); + } + } + + public void setListVisible(boolean b) { + archiveOperationFlowPane.setVisible(b); + } + + private void setDetailsVisible(boolean b) { + apDetails.setVisible(b); + } + + public void backClicked() { + fpVehicles.getChildren().clear(); + setDetailsVisible(false); + } +} 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 index b6693d0..ce795da 100644 --- 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 @@ -8,17 +8,22 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.Vehicle import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; import java.lang.invoke.MethodHandles; +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.geometry.HPos; +import javafx.geometry.Orientation; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.ButtonType; import javafx.scene.control.CheckBox; import javafx.scene.control.ChoiceBox; +import javafx.scene.layout.FlowPane; import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,17 +35,21 @@ public class CreateCarController { @FXML private ChoiceBox<String> cmb_Ctyp; @FXML private ChoiceBox<String> cmb_typ; @FXML private Button btn_cancel; + @FXML private Button btn_create; @FXML private CheckBox cbx_NEF; + @FXML private FlowPane fp_vehicleList; private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private final VehicleService vehicleService; + private boolean update = false; + private long vid = -1; public CreateCarController(VehicleService vehicleService) { this.vehicleService = vehicleService; } @FXML - public void initialize() { + private void initialize() { cmb_Ctyp.setItems( FXCollections.observableArrayList( Stream.of( @@ -62,36 +71,74 @@ public class CreateCarController { .map(Enum::toString) .collect(Collectors.toList()))); cmb_typ.setValue(VehicleType.BKTW.toString()); + vehicleListFP(); } @FXML - public void onCancelClicked() { + private void onCancelClicked() { ((Stage) btn_cancel.getScene().getWindow()).close(); } @FXML - public void createCar(ActionEvent actionEvent) { - Vehicle vehicle = - Vehicle.builder() - .constructionType(parseConstructionType()) - .type(parseType()) - .name("") - .status(Status.ABGEMELDET) - .hasNef(cbx_NEF.isSelected()) - .build(); - try { - vehicleService.add(vehicle); - } catch (InvalidVehicleException e) { - LOG.error("Invalid Vehicle: {}", e); - createComplete(AlertType.ERROR, "Ungültige Eingabe", e.getMessage()); - return; - } catch (ServiceException e) { - LOG.error("Exception: {}", e); - createComplete(AlertType.ERROR, "Fehler", e.getMessage()); - return; + private void createCar(ActionEvent actionEvent) { + + if (!update) { + Vehicle vehicle = + Vehicle.builder() + .constructionType(parseConstructionType()) + .type(parseType()) + .name("") + .status(Status.ABGEMELDET) + .hasNef(cbx_NEF.isSelected()) + .build(); + try { + vehicleService.add(vehicle); + setToStart(); + } catch (InvalidVehicleException e) { + LOG.error("Invalid Vehicle: {}", e); + createComplete(AlertType.ERROR, "Ungültige Eingabe", e.getMessage()); + setToStart(); + return; + } catch (ServiceException e) { + LOG.error("Exception: {}", e); + createComplete(AlertType.ERROR, "Fehler", e.getMessage()); + setToStart(); + return; + } + createComplete( + AlertType.CONFIRMATION, + "Speichern Erfolgreich", + "Auto wurde erfolgreich angelegt"); + } else { + try { + Vehicle vehicle = + Vehicle.builder() + .id(vid) + .constructionType(parseConstructionType()) + .type(parseType()) + .name("") + .status(Status.ABGEMELDET) + .hasNef(cbx_NEF.isSelected()) + .build(); + vehicleService.update(vehicle); + setToStart(); + } catch (InvalidVehicleException e) { + LOG.error("Invalid Vehicle: {}", e); + createComplete(AlertType.ERROR, "Ungültige Eingabe", e.getMessage()); + setToStart(); + return; + } catch (ServiceException e) { + LOG.error("Exception: {}", e); + createComplete(AlertType.ERROR, "Fehler", e.getMessage()); + setToStart(); + return; + } + createComplete( + AlertType.CONFIRMATION, + "Bearbiten Erfolgreich", + "Auto wurde erfolgreich bearbeitet"); } - createComplete( - AlertType.CONFIRMATION, "Speichern Erfolgreich", "Auto wurde erfolgreich angelegt"); + vehicleListFP(); } private ConstructionType parseConstructionType() { @@ -113,4 +160,47 @@ public class CreateCarController { alert.setHeaderText(headerText); alert.showAndWait(); } + + private void vehicleListFP() { + Set<Vehicle> vehicleList = null; + fp_vehicleList.getChildren().clear(); + try { + vehicleList = vehicleService.list(EnumSet.range(Status.ABGEMELDET, Status.FREI_FUNK)); + } catch (ServiceException e) { + e.printStackTrace(); + } + + fp_vehicleList.setOrientation(Orientation.HORIZONTAL); + fp_vehicleList.setColumnHalignment(HPos.LEFT); // align labels on left + fp_vehicleList.setPrefWrapLength(200); // preferred height = 200 + + for (Vehicle v : vehicleList) { + Button b = new Button(v.name()); + b.setOnAction(event -> updateVehicle(v)); + fp_vehicleList.getChildren().add(b); + } + fp_vehicleList.setVisible(true); + } + + private void setToStart() { + btn_create.setText("Erstellen"); + cbx_NEF.setSelected(false); + cmb_typ.setValue(VehicleType.BKTW.name()); + cmb_Ctyp.setValue(ConstructionType.NORMAL.name()); + update = false; + } + + private void updateVehicle(Vehicle vehicle) { + cmb_Ctyp.setValue(vehicle.constructionType().name()); + cmb_typ.setValue(vehicle.type().name()); + cbx_NEF.setSelected(vehicle.hasNef()); + btn_create.setText("Speichern"); + vid = vehicle.id(); + update = true; + } + + @FXML + public void cancelAction(ActionEvent actionEvent) { + setToStart(); + } } 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 index d81f6d7..15282cc 100644 --- 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 @@ -5,44 +5,56 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.Ed 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.lang.invoke.MethodHandles; 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.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.ButtonType; import javafx.scene.control.CheckBox; import javafx.scene.control.ChoiceBox; -import javafx.scene.control.Hyperlink; +import javafx.scene.control.Label; import javafx.scene.control.TextField; -import javafx.stage.Stage; 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(MethodHandles.lookup().lookupClass()); private final EmployeeService employeeService; + @FXML private Label lblHeader; @FXML private CheckBox inputIsDriver; @FXML private CheckBox inputIsPilot; - @FXML private Hyperlink btnCancel; - @FXML private Button btnCreate; @FXML private TextField inputName; @FXML private ChoiceBox<String> 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 - public void initialize() { + private void initialize() { inputQualification.setItems( FXCollections.observableArrayList( Stream.of( @@ -56,18 +68,28 @@ public class CreateNewEmployeeController { .collect(Collectors.toList()))); inputQualification.setValue(EducationLevel.RS.toString()); + employee = + Employee.builder() + .name("") + .educationLevel(EducationLevel.RS) + .isDriver(false) + .isPilot(false) + .birthday(LocalDate.MIN) + .build(); } @FXML - public void onCancelClicked() { - ((Stage) inputQualification.getScene().getWindow()).close(); + private void onCancelClicked() { + if (consumerCancelClicked != null) { + consumerCancelClicked.run(); + } } @FXML - public void onCreateClicked() { + private void onCreateClicked() { - Employee employee = - Employee.builder() + employee = + employee.toBuilder() .name(inputName.getText()) .educationLevel(parseEducationLevel()) .birthday(LocalDate.MIN) // TODO: change UI to include birthday field @@ -76,7 +98,11 @@ public class CreateNewEmployeeController { .build(); try { - employeeService.add(employee); + if (isEdit) { + employeeService.update(employee); + } else { + employeeService.add(employee); + } } catch (InvalidEmployeeException e) { LOG.error("Invalid Employee: {}", e); @@ -99,6 +125,10 @@ public class CreateNewEmployeeController { AlertType.INFORMATION, "Erfolgreich angelegt", "Mitarbeiter wurde erfolgreich angelegt und gespeichert!"); + + if (consumerCreateClicked != null) { + consumerCreateClicked.run(); + } } private void showModalDialogWithOkButton( @@ -114,4 +144,46 @@ public class CreateNewEmployeeController { } 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<Object, CreateNewEmployeeController> 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 new file mode 100644 index 0000000..57759e3 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateOperationController.java @@ -0,0 +1,365 @@ +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.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 at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import java.io.IOException; +import java.lang.invoke.MethodHandles; +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.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +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.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class CreateOperationController { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + public AnchorPane apCreateOperation; + @FXML private TextField txtCode; + @FXML private TextField txtAddress; + @FXML private TextField txtNote; + @FXML private Button btnCreateOperation; + @FXML private ListView<Vehicle> lvVehicles; + @FXML private ListView<Operation> lvActiveOperations; + @FXML private Label lblChosenVehicles; + @FXML private AnchorPane apInvisible; + @FXML private OperationDetailsController operationDetailsController; + @FXML private FlowPane fpVehicles; + + private LinkedList<Vehicle> chosenVehicles = new LinkedList<>(); + + private final OperationService operationService; + private final VehicleService vehicleService; + private final SpringFXMLLoader fxmlLoader; + + public CreateOperationController( + OperationService operationService, + VehicleService vehicleService, + SpringFXMLLoader fxmlLoader) { + this.operationService = operationService; + this.vehicleService = vehicleService; + this.fxmlLoader = fxmlLoader; + } + + @FXML + private void initialize() { + lblChosenVehicles.setText("keine ausgewählt"); + lvActiveOperations.setCellFactory( + param -> + 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()); + } + } + }); + lvActiveOperations.setOnMouseClicked( + event -> { + if (event.getClickCount() == 2) { + if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { + return; + } + openDetailsWindow(lvActiveOperations.getSelectionModel().getSelectedItem()); + } + }); + } + + public void updateList() { + try { + fpVehicles.getChildren().clear(); + + // TODO: this should probably be handled differently + Set<Vehicle> 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); + 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()); + } + } + }); + + fpVehicles.getChildren().add(controller.getRootElement()); + } + } catch (ServiceException | IOException | InvalidOperationException e) { + LOG.error("Error while updating list.", e); + + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler!"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + try { + lvActiveOperations.setItems( + FXCollections.observableArrayList( + operationService.list(EnumSet.of(Status.ACTIVE)))); + } catch (ServiceException e) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Fehler - Einsätze"); + alert.setHeaderText("Beim Holen der aktiven Einsätze ist ein Fehler aufgetreten."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + + 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 | ServiceException e) { + LOG.error("Error while setting status.", e); + Alert a = new Alert(AlertType.ERROR, e.getMessage()); + a.show(); + } + }); + + menu.getItems().add(mi); + } + + MenuItem abmelden = new MenuItem("abmelden"); + + abmelden.setOnAction( + event -> { + try { + List<Registration> registrations = data.registrations(); + assert registrations + != null; // Otherwise the element shouldn't be in the list. + + List<Registration> 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 | ServiceException e) { + LOG.error("Error while unregistering.", e); + Alert a = new Alert(AlertType.ERROR, e.getMessage()); + a.show(); + } + }); + + menu.getItems().add(abmelden); + return menu; + } + + @FXML + protected void createOperationClicked() { + 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 | InvalidOperationException e) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler!"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + return; + } + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Erfolg"); + alert.setHeaderText("Erfolgreich gespeichert"); + alert.setContentText("Der Einsatz wurde erfolgreich gespeichert."); + alert.showAndWait(); + updateList(); + lblChosenVehicles.setText("keine ausgewählt"); + txtAddress.setText(""); + txtCode.setText(""); + txtNote.setText(""); + chosenVehicles = new LinkedList<>(); + } + + public void onRegistrationLinkClicked(ActionEvent actionEvent) { + openNewWindow("RegistrationWindow.fxml"); + } + + public void onEmployeeLinkClicked(ActionEvent actionEvent) { + openNewWindow("listEmployees.fxml"); + } + + public void onVehicleLinkClicked(ActionEvent actionEvent) { + openNewWindow("createCar.fxml"); + } + + public void onArchivLinkClicked() { + openNewArchivWindow(); + } + + private void openNewArchivWindow() { + Stage stage = new Stage(); + try { + stage.setScene( + new Scene( + (Parent) + fxmlLoader.load( + getClass() + .getResourceAsStream( + "/fxml/ArchiveOperation.fxml")))); + } catch (IOException e) { + LOG.error("Could not open new window: {}", e); + } + stage.setTitle("Einsatz erstellen"); + stage.centerOnScreen(); + stage.show(); + updateList(); + } + + private void openNewWindow(String fxmlFileName) { + + Stage stage = new Stage(); + try { + stage.setScene( + new Scene( + (Parent) + fxmlLoader.load( + getClass() + .getResourceAsStream( + "/fxml/" + fxmlFileName)))); + } catch (IOException e) { + LOG.error("Could not open new window: {}", e); + } + + stage.setTitle("Ressourcenverwaltung"); + stage.centerOnScreen(); + stage.showAndWait(); // important to call wait so that updateList is executed afterwards + + updateList(); + } + + void setVisible(boolean b) { + apInvisible.setVisible(!b); + } + + private void openDetailsWindow(Operation operation) { + operationDetailsController.initOperation(operation); + this.setVisible(false); + } + + @FXML + public void onOperationCodeChanged(KeyEvent keyEvent) { + if (keyEvent.getCode() == KeyCode.ENTER) { + updateList(); + } + } +} 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 new file mode 100644 index 0000000..11b5626 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/EmployeeListItemController.java @@ -0,0 +1,83 @@ +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 { + + @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 Node rootElement; + private Employee employee; + + private Consumer<Employee> consumerEditEmployeeClicked; + + @FXML + public void onEditEmployeeClicked() { + if (consumerEditEmployeeClicked != null) { + consumerEditEmployeeClicked.accept(employee); + } + } + + 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<Object, EmployeeListItemController> wrapper = + loader.loadAndWrap("/fxml/employeeListItem.fxml", EmployeeListItemController.class); + Node root = (Node) wrapper.getLoadedObject(); + EmployeeListItemController controller = wrapper.getController(); + controller.rootElement = root; + return controller; + } + + public Node getRootElement() { + return rootElement; + } + + public Employee getEmployee() { + return employee; + } + + public void setConsumerEditEmployeeClicked(Consumer<Employee> consumerEditEmployeeClicked) { + this.consumerEditEmployeeClicked = consumerEditEmployeeClicked; + } +} 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 new file mode 100644 index 0000000..6d6214d --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/FilterEmployeesController.java @@ -0,0 +1,60 @@ +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.springframework.context.annotation.Scope; +import org.springframework.stereotype.Controller; + +@Controller +@Scope("prototype") +public class FilterEmployeesController { + + @FXML private TextField inputFilterString; + + private Consumer<String> consumerFilterTextChanged; + private Runnable consumerAddEmployeeClicked; + + private Node rootElement; + + @FXML + private void onAddEmployeeClicked() { + if (consumerAddEmployeeClicked != null) { + consumerAddEmployeeClicked.run(); + } + } + + @FXML + private void onFilterTextChanged() { + if (consumerFilterTextChanged != null) { + consumerFilterTextChanged.accept(inputFilterString.getText()); + } + } + + public void setOnFilterTextChangedListener(Consumer<String> callback) { + this.consumerFilterTextChanged = callback; + } + + public void setOnAddEmployeeClickedListener(Runnable callback) { + this.consumerAddEmployeeClicked = callback; + } + + public static FilterEmployeesController createFilterEmployeesController( + SpringFXMLLoader fxmlLoader) throws IOException { + FXMLWrapper<Object, FilterEmployeesController> 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/ListEmployeesController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ListEmployeesController.java new file mode 100644 index 0000000..25f1263 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/ListEmployeesController.java @@ -0,0 +1,117 @@ +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.lang.invoke.MethodHandles; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.scene.Node; +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 ListEmployeesController { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + @FXML private AnchorPane containerHeader; + @FXML private FlowPane flowPaneEmployeeList; + + private final EmployeeService employeeService; + private final SpringFXMLLoader fxmlLoader; + + public ListEmployeesController(EmployeeService employeeService, SpringFXMLLoader fxmlLoader) { + this.employeeService = employeeService; + this.fxmlLoader = fxmlLoader; + } + + @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("Could not initialize controller: {}", e); + } + } + + private void openAddEmployee() { + openEmployee(null); + } + + private void openEditEmployee(Employee 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("Could not prepare UI for adding employee: {}", e); + } + } + + private void updateEmployeeList() { + updateEmployeeList(""); + } + + private void updateEmployeeList(String searchString) { + try { + flowPaneEmployeeList.getChildren().clear(); + employeeService + .list() + .stream() + .filter( + employee -> + searchString.trim().isEmpty() + || employee.name() + .toLowerCase() + .contains(searchString.toLowerCase())) + .forEach(this::addEmployeeToFlowPane); + } catch (ServiceException e) { + LOG.error("Could not fetch employee list: {}", e); + } + } + + private void addEmployeeToFlowPane(Employee employee) { + Insets listItemMargins = new Insets(0, 5, 10, 5); + + try { + EmployeeListItemController controller = + EmployeeListItemController.createEmployeeListItemController( + fxmlLoader, employee); + Node rootElement = controller.getRootElement(); + flowPaneEmployeeList.getChildren().add(rootElement); + FlowPane.setMargin(rootElement, listItemMargins); + controller.setConsumerEditEmployeeClicked(this::openEditEmployee); + } catch (IOException e) { + LOG.error("Could not create a new EmployeeListItem: {}", e); + } + } +} 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 new file mode 100644 index 0000000..dc7e969 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/OperationDetailsController.java @@ -0,0 +1,162 @@ +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.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.ServiceException; +import java.util.Collection; +import java.util.EnumSet; +import java.util.stream.Collectors; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.layout.AnchorPane; +import org.springframework.stereotype.Controller; + +@Controller +public class OperationDetailsController { + + public Operation operation; + private final OperationService operationService; + private final VehicleService vehicleService; + private final CreateOperationController createOperationController; + @FXML private ListView<Vehicle> lvVehicles; + @FXML private ListView<Operation> 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() { + lvVehicles.setCellFactory( + param -> + new ListCell<>() { + @Override + protected void updateItem(Vehicle item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null || item.name() == null) { + setText(null); + } else { + setText(item.name()); + } + } + }); + lvActiveOperations.setCellFactory( + param -> + 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()); + } + } + }); + lvActiveOperations.setOnMouseClicked( + event -> { + if (event.getClickCount() == 2) { + if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { + return; + } + initOperation(lvActiveOperations.getSelectionModel().getSelectedItem()); + } + }); + } + + void initOperation(Operation operation) { + fillActiveList(); + this.operation = operation; + lblCode.setText(operation.opCode()); + Collection<String> 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()); + lvVehicles.setItems(FXCollections.observableArrayList(operation.vehicles())); + operationDetailsAP.setVisible(true); + } + + private void fillActiveList() { + try { + lvActiveOperations.setItems( + FXCollections.observableArrayList( + operationService.list(EnumSet.of(Status.ACTIVE)))); + } catch (ServiceException e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler!"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + + @FXML + public void closeOperationClicked() { + try { + operationService.complete(operation.id(), Status.COMPLETED); + } catch (InvalidOperationException | ServiceException e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler!"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + return; + } + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Erfolg"); + alert.setHeaderText("Erfolgreich aktualisiert"); + alert.setContentText("Der Einsatz wurde erfolgreich aktualisiert."); + alert.showAndWait(); + closeWindow(); + createOperationController.updateList(); + } + + public void cancelOperationClicked() { + try { + operationService.complete(operation.id(), Status.CANCELLED); + } catch (InvalidOperationException | ServiceException e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler!"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + return; + } + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Erfolg"); + alert.setHeaderText("Erfolgreich aktualisiert"); + alert.setContentText("Der Einsatz wurde erfolgreich aktualisiert."); + alert.showAndWait(); + closeWindow(); + createOperationController.updateList(); + } + + public void closeWindow() { + operationDetailsAP.setVisible(false); + this.createOperationController.setVisible(true); + } +} 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 index bf413bb..4653663 100644 --- 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 @@ -15,8 +15,10 @@ 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 javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -31,7 +33,6 @@ import javafx.scene.control.TextField; import javafx.stage.Stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller @@ -39,46 +40,40 @@ public class RegistrationWindowController { private static final Logger LOG = LoggerFactory.getLogger(RegistrationWindowController.class); - private EmployeeService employeeService; + private final EmployeeService employeeService; - private VehicleService vehicleService; + private final VehicleService vehicleService; - private RegistrationService registrationService; + private final RegistrationService registrationService; - @Autowired - public void setEmployeeService(EmployeeService employeeService) { + public RegistrationWindowController( + EmployeeService employeeService, + VehicleService vehicleService, + RegistrationService registrationService) { this.employeeService = employeeService; - } - - @Autowired - public void setVehicleService(VehicleService vehicleService) { this.vehicleService = vehicleService; - } - - @Autowired - public void setRegistrationService(RegistrationService registrationService) { this.registrationService = registrationService; } - @FXML public ChoiceBox<Integer> cbStart; - @FXML public ChoiceBox<Integer> cbEnd; - @FXML public Label lVehicles; - @FXML public Label lEmployees; - @FXML public TextField tfVehicleSearch; - @FXML public TextField tfEmployeeSearch; - @FXML public TableView<Vehicle> tvVehicles; - @FXML public TableView<Employee> tvEmployees; - @FXML public TableColumn<Vehicle, String> tcVehicles; - @FXML public TableColumn<Employee, String> tcEmployees; + @FXML private ChoiceBox<Integer> cbStart; + @FXML private ChoiceBox<Integer> cbEnd; + @FXML private Label lVehicles; + @FXML private Label lEmployees; + @FXML private TextField tfVehicleSearch; + @FXML private TextField tfEmployeeSearch; + @FXML private TableView<Vehicle> tvVehicles; + @FXML private TableView<Employee> tvEmployees; + @FXML private TableColumn<Vehicle, String> tcVehicles; + @FXML private TableColumn<Employee, String> tcEmployees; private Vehicle chosenVehicle; private List<Employee> chosenEmployees = new LinkedList<>(); @FXML - public void initialize() { + private void initialize() { // will have to be replaced for FlowPane try { - List<Vehicle> vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET)); + Set<Vehicle> vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET)); tcVehicles.setCellValueFactory(x -> new SimpleStringProperty(x.getValue().name())); tvVehicles.setItems(FXCollections.observableArrayList(vehicles)); } catch (ServiceException e) { @@ -92,7 +87,7 @@ public class RegistrationWindowController { alert.show(); } try { - List<Employee> employees = employeeService.list(); + Set<Employee> employees = employeeService.list(); tcEmployees.setCellValueFactory(x -> new SimpleStringProperty(x.getValue().name())); tvEmployees.setItems(FXCollections.observableArrayList(employees)); } catch (ServiceException e) { @@ -118,10 +113,15 @@ public class RegistrationWindowController { tvEmployees.setOnMousePressed( mouseEvent -> { if (mouseEvent.isPrimaryButtonDown() && mouseEvent.getClickCount() == 2) { - chosenEmployees.add(tvEmployees.getSelectionModel().getSelectedItem()); - if (chosenEmployees == null) { + Employee selection = tvEmployees.getSelectionModel().getSelectedItem(); + if (selection == null) { return; + } else if (chosenEmployees.contains(selection)) { + chosenEmployees.remove(selection); + } else { + chosenEmployees.add(selection); } + StringBuilder text = new StringBuilder(); for (Employee employee : chosenEmployees) { text.append(employee.name()).append("\n"); @@ -141,34 +141,40 @@ public class RegistrationWindowController { public void cancel() { LOG.debug("Cancel Button clicked"); + chosenEmployees.clear(); ((Stage) lVehicles.getScene().getWindow()).close(); } public void create() { LOG.debug("Create Button clicked"); - List<Registration> registrations = new LinkedList<>(); - - 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()); - } + Set<Registration> 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(); + } catch (InvalidVehicleException e) { // NOT THROWN ANYWHERE RIGHT NOW LOG.info( @@ -180,6 +186,7 @@ public class RegistrationWindowController { alert.setHeaderText("Das spezifizierte Fahrzeug ist nicht gültig."); alert.setContentText(e.getMessage()); alert.show(); + chosenEmployees.clear(); } catch (ServiceException e) { LOG.warn( "Caught ServiceException while getting vehicles. Showing it to user. Error message: {}", @@ -189,6 +196,7 @@ public class RegistrationWindowController { alert.setHeaderText("Beim Erstellen der Anmeldung ist ein Fehler aufgetreten."); alert.setContentText(e.getMessage()); alert.show(); + chosenEmployees.clear(); } catch (InvalidRegistrationException e) { LOG.info( "Caught InvalidRegistrationException. Showing it to user. Error message: {}", @@ -199,6 +207,7 @@ public class RegistrationWindowController { "Die gewählte Kombination von Fahrzeug und Personal ist nicht gültig!"); alert.setContentText(e.getMessage()); alert.show(); + chosenEmployees.clear(); } } } diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/ui/vehiclepane/VehiclePaneController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/VehiclePaneController.java index 2db6f37..6c0932b 100644 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/ui/vehiclepane/VehiclePaneController.java +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/VehiclePaneController.java @@ -1,11 +1,10 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.ui.vehiclepane; +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 java.io.IOException; import java.time.Instant; -import java.util.Date; import java.util.List; import java.util.Optional; import javafx.fxml.FXML; @@ -14,15 +13,12 @@ import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.text.Text; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class VehiclePaneController { - @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; + + private static Logger LOG = LoggerFactory.getLogger(VehiclePaneController.class); public static VehiclePaneController createVehiclePane() throws IOException { FXMLLoader fxmlLoader = @@ -34,12 +30,25 @@ public class VehiclePaneController { return result; } + @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; + private Node rootElement; + private Vehicle data; public Node getRootElement() { return rootElement; } + public Vehicle getData() { + return data; + } + /** * * Set the displayed data of this VehiclePane. * @@ -52,27 +61,33 @@ public class VehiclePaneController { String constrType = vehicle.constructionType().name(); txtRooftype.setText( constrType.substring(0, 1).toUpperCase() + constrType.substring(1).toLowerCase()); - txtNumber.setText("" + vehicle.id()); + txtNumber.setText("-" + vehicle.id()); if (vehicle.hasNef()) { - ivNEF.setImage(new Image("../images/NEF.png")); + ivNEF.setImage(new Image("images/NEF.png")); txtNEF.setText("hat NEF-Halterung"); } else { - ivNEF.setImage(new Image("../images/NotNEF.png")); + ivNEF.setImage(new Image("images/NotNEF.png")); txtNEF.setText("keine NEF-Halterung"); } if (showQualification) { - Instant now = (new Date()).toInstant(); + Instant now = Instant.now(); List<Registration> regs = vehicle.registrations(); - assert regs != null; + if (regs == null) { + return; + } + Optional<EducationLevel> edu = regs.stream() .filter(reg -> reg.start().isBefore(now) && reg.end().isAfter(now)) .map(reg -> reg.employee().educationLevel()) .max(EducationLevel::compareTo); - assert edu.isPresent(); + if (!edu.isPresent()) { + return; + } + txtQualification.setText(edu.get().name()); } else { txtQualification.setVisible(false); @@ -80,5 +95,19 @@ public class VehiclePaneController { ivQualification.setVisible(false); ivQualification.setManaged(false); } + + this.data = vehicle; + } + + 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/dao/DBOperationDAO.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/DBOperationDAO.java deleted file mode 100644 index 672424a..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/DBOperationDAO.java +++ /dev/null @@ -1,161 +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 at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.EnumSet; -import java.util.List; - -public class DBOperationDAO implements OperationDAO { - - private JDBCConnectionManager jdbcConnectionManager; - - public DBOperationDAO(JDBCConnectionManager j) { - jdbcConnectionManager = j; - } - - @Override - public long add(Operation operation) throws PersistenceException { - if (operation == null) { - throw new PersistenceException("Das der Datenbank übergebene Objekt ist fehlerhaft!"); - } - PreparedStatement pstmt = null; - try { - pstmt = - jdbcConnectionManager - .getConnection() - .prepareStatement( - "INSERT INTO operation(opCode, severity, " - + "created, destination, additionalInfo, status) values (?,?,?,?,?,?)", - java.sql.Statement.RETURN_GENERATED_KEYS); - - if (operation.opCode() == null) { - throw new PersistenceException("Code darf nicht null sein!"); - } else if (operation.opCode().length() > 20) - throw new PersistenceException( - "Länge des OP-Codes überschreitet erlaubte Länge von 100 Zeichen!"); - else pstmt.setString(1, operation.opCode()); - /*switch (operation.severity()) { - case A: - pstmt.setInt(2, 0); - break; - case B: - pstmt.setInt(2, 1); - break; - case C: - pstmt.setInt(2, 2); - break; - case D: - pstmt.setInt(2, 3); - break; - case E: - pstmt.setInt(2, 4); - break; - case O: - pstmt.setInt(2, 5); - break; - default: - throw new PersistenceException( - "Schwere des Einsatzes konnte nicht validiert werden!"); - }*/ - pstmt.setString(2, operation.severity().name()); - if (operation.created() != null) { - pstmt.setTimestamp(3, Timestamp.from(operation.created())); - } else { - throw new PersistenceException("Zeitpunkt der Erstellung darf nicht null sein!"); - } - - if (operation.destination() == null) { - throw new PersistenceException("Einsatzort darf nicht null sein!"); - } else if (operation.destination().length() > 100) { - throw new PersistenceException( - "Länge der Adresse überschreitet erlaubte Länge von 100 Zeichen!"); - } else { - pstmt.setString(4, operation.destination()); - } - if (operation.additionalInfo().length() > 100) - throw new PersistenceException( - "Länge der zusätzlichen Information überschreitet erlaubte Länge von 100 Zeichen!"); - else pstmt.setString(5, operation.additionalInfo()); - if (operation.status() == null) { - throw new PersistenceException("Status darf nicht null sein!"); - } else if (operation.status().toString().length() > 100) { - throw new PersistenceException( - "Länge des Status überschreitet erlaubte Länge von 100 Zeichen!"); - } else { - pstmt.setString(6, operation.status().toString()); - } - pstmt.executeUpdate(); - ResultSet rs = pstmt.getGeneratedKeys(); - if (rs.next()) return rs.getInt(1); - else throw new PersistenceException("Einsatz konnte nicht gespeichert werden"); - } catch (SQLException e) { - throw new PersistenceException(e); - } finally { - if (pstmt != null) { - try { - pstmt.close(); - } catch (SQLException e) { - throw new PersistenceException( - "Verbindung zur Datenbank konnte nicht geschlossen werden!", e); - } - } - } - } - - @Override - public void update(Operation operation) throws ElementNotFoundException, PersistenceException {} - - @Override - public Operation get(long operationId) throws ElementNotFoundException, PersistenceException { - return null; - } - - @Override - public List<Operation> list(EnumSet<Status> statuses) throws PersistenceException { - return null; - } - - @Override - public int connectVehicleToOperation(long vehicleID, long operationID) - throws PersistenceException { - PreparedStatement pstmt = null; - try { - pstmt = - jdbcConnectionManager - .getConnection() - .prepareStatement( - "insert into VehicleOperation(vehicleId, operationId)" - + "values (?,?)"); - pstmt.setLong(1, vehicleID); - pstmt.setLong(2, operationID); - pstmt.executeUpdate(); - - /* - ResultSet rs = pstmt.getGeneratedKeys(); - if (rs.next()) return rs.getInt(1); - else - throw new PersistenceException( - "Fahrzeug für die Operation konnte nicht abgespeichert werden!");*/ - } catch (SQLException e) { - throw new PersistenceException("Die Werte konnten nicht gespeichert werden!"); - } finally { - if (pstmt != null) { - try { - pstmt.close(); - } catch (SQLException e) { - throw new PersistenceException( - "Verbindung zur Datenbank konnte nicht geschlossen werden!", e); - } - } - } - - return 1; - } -} 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 index 564ce7c..539a8e5 100644 --- 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 @@ -3,7 +3,7 @@ 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.List; +import java.util.Set; public interface EmployeeDAO { @@ -31,7 +31,7 @@ public interface EmployeeDAO { * @return list containing all stored employees * @throws PersistenceException if loading the stored employees failed */ - List<Employee> list() throws PersistenceException; + Set<Employee> list() throws PersistenceException; /** * Remove employee with the given id from the store. 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 new file mode 100644 index 0000000..43a5c9d --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDAO.java @@ -0,0 +1,201 @@ +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.lang.invoke.MethodHandles; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.HashSet; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +@Repository +public class EmployeeDatabaseDAO implements EmployeeDAO { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final String INSERT_EMPLOYEE_VERSION = + "INSERT INTO EmployeeVersion(name, birthday, educationLevel, isDriver, isPilot) " + + "VALUES(?, ?, ?, ?, ?)"; + private static final String INSERT_EMPLOYEE = "INSERT INTO Employee(version) VALUES(?)"; + private static final String LIST_EMPLOYEE = + "SELECT emp.id, v.name, v.birthday, v.educationLevel, v.isDriver, v.isPilot " + + "FROM employee emp " + + "JOIN EmployeeVersion v ON v.id = emp.version"; + private static final String UPDATE_EMPLOYEE = "UPDATE Employee SET version = ? WHERE id = ?"; + + private final PreparedStatement insertEmployeeVersion, + insertEmployee, + listEmployee, + updateEmployee; + + private final Connection connection; + + public EmployeeDatabaseDAO(JDBCConnectionManager connectionManager) + throws PersistenceException { + + try { + + connection = connectionManager.getConnection(); + insertEmployeeVersion = + connection.prepareStatement( + INSERT_EMPLOYEE_VERSION, Statement.RETURN_GENERATED_KEYS); + insertEmployee = + connection.prepareStatement(INSERT_EMPLOYEE, Statement.RETURN_GENERATED_KEYS); + + listEmployee = connection.prepareStatement(LIST_EMPLOYEE); + + updateEmployee = connection.prepareStatement(UPDATE_EMPLOYEE); + + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + @Override + public long add(Employee employee) throws PersistenceException { + + // Assumption: the given employee is already validated (from service) + Savepoint savepoint = null; + try { + savepoint = connection.setSavepoint(); + connection.setAutoCommit(false); + insertEmployeeVersion.setString(1, employee.name()); + insertEmployeeVersion.setTimestamp( + 2, Timestamp.valueOf(employee.birthday().atStartOfDay())); + insertEmployeeVersion.setString(3, employee.educationLevel().toString()); + insertEmployeeVersion.setBoolean(4, employee.isDriver()); + insertEmployeeVersion.setBoolean(5, employee.isPilot()); + insertEmployeeVersion.executeUpdate(); + try (ResultSet resultSetEmployeeVersion = insertEmployeeVersion.getGeneratedKeys()) { + if (resultSetEmployeeVersion.next()) { + long versionId = resultSetEmployeeVersion.getLong(1); + + insertEmployee.setLong(1, versionId); + insertEmployee.executeUpdate(); + + try (ResultSet resultSetEmployee = insertEmployee.getGeneratedKeys()) { + if (resultSetEmployee.next()) { + connection.commit(); + return resultSetEmployee.getLong(1); + } + } + } + } + + throw new PersistenceException("Employee was not updated"); + + } catch (SQLException e) { + try { + if (savepoint != null) { + connection.rollback(savepoint); + } + } catch (SQLException e1) { + throw new PersistenceException(e); + } + throw new PersistenceException(e); + } finally { + try { + connection.setAutoCommit(true); + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + } + + @Override + public void update(Employee employee) throws ElementNotFoundException, PersistenceException { + + Savepoint savepoint = null; + try { + savepoint = connection.setSavepoint(); + connection.setAutoCommit(false); + + insertEmployeeVersion.setString(1, employee.name()); + insertEmployeeVersion.setTimestamp( + 2, Timestamp.valueOf(employee.birthday().atStartOfDay())); + insertEmployeeVersion.setString(3, employee.educationLevel().toString()); + insertEmployeeVersion.setBoolean(4, employee.isDriver()); + insertEmployeeVersion.setBoolean(5, employee.isPilot()); + insertEmployeeVersion.executeUpdate(); + try (ResultSet resultSetEmployeeVersion = insertEmployeeVersion.getGeneratedKeys()) { + + if (resultSetEmployeeVersion.next()) { + long versionId = resultSetEmployeeVersion.getLong(1); + + updateEmployee.setLong(1, versionId); + updateEmployee.setLong(2, employee.id()); + int affectedRows = updateEmployee.executeUpdate(); + + if (affectedRows == 1) { + connection.commit(); + } else { + throw new ElementNotFoundException( + "element not found with id: " + employee.id()); + } + } + } + + } catch (SQLException e) { + try { + if (savepoint != null) { + connection.rollback(savepoint); + } + } catch (SQLException e1) { + throw new PersistenceException(e); + } + throw new PersistenceException(e); + } finally { + try { + connection.setAutoCommit(true); + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + } + + @Override + public Set<Employee> list() throws PersistenceException { + + try { + Set<Employee> employees; + try (ResultSet rs = listEmployee.executeQuery()) { + + employees = new HashSet<>(); + while (rs.next()) { + + Employee employee = + Employee.builder() + .id(rs.getLong(1)) + .name(rs.getString(2)) + .birthday(rs.getTimestamp(3).toLocalDateTime().toLocalDate()) + .educationLevel(EducationLevel.valueOf(rs.getString(4))) + .isDriver(rs.getBoolean(5)) + .isPilot(rs.getBoolean(6)) + .build(); + + employees.add(employee); + } + } + + 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/EmployeeDatabaseDao.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDao.java deleted file mode 100644 index 3e4ba12..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDao.java +++ /dev/null @@ -1,124 +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.lang.invoke.MethodHandles; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Repository; - -@Repository -public class EmployeeDatabaseDao implements EmployeeDAO { - - private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private static final String INSERT_EMPLOYEE_VERSION = - "INSERT INTO EmployeeVersion(name, birthday, educationLevel, isDriver, isPilot) " - + "VALUES(?, ?, ?, ?, ?)"; - private static final String INSERT_EMPLOYEE = "INSERT INTO Employee(version) VALUES(?)"; - private static final String LIST_EMPLOYEE = - "SELECT emp.id, v.name, v.birthday, v.educationLevel, v.isDriver, v.isPilot " - + "FROM employee emp " - + "JOIN EmployeeVersion v ON v.id = emp.version"; - - private final PreparedStatement insertEmployeeVersion, insertEmployee, listEmployee; - - public EmployeeDatabaseDao(JDBCConnectionManager connectionManager) - throws PersistenceException { - - try { - - final var connection = connectionManager.getConnection(); - insertEmployeeVersion = - connection.prepareStatement( - INSERT_EMPLOYEE_VERSION, Statement.RETURN_GENERATED_KEYS); - insertEmployee = - connection.prepareStatement(INSERT_EMPLOYEE, Statement.RETURN_GENERATED_KEYS); - - listEmployee = connection.prepareStatement(LIST_EMPLOYEE); - - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - @Override - public long add(Employee employee) throws PersistenceException { - - // Assumption: the given employee is already validated (from service) - try { - insertEmployeeVersion.setString(1, employee.name()); - insertEmployeeVersion.setTimestamp( - 2, Timestamp.valueOf(employee.birthday().atStartOfDay())); - insertEmployeeVersion.setString(3, employee.educationLevel().toString()); - insertEmployeeVersion.setBoolean(4, employee.isDriver()); - insertEmployeeVersion.setBoolean(5, employee.isPilot()); - insertEmployeeVersion.executeUpdate(); - ResultSet resultSetEmployeeVersion = insertEmployeeVersion.getGeneratedKeys(); - if (resultSetEmployeeVersion.next()) { - long versionId = resultSetEmployeeVersion.getLong(1); - - insertEmployee.setLong(1, versionId); - insertEmployee.executeUpdate(); - - ResultSet resultSetEmployee = insertEmployee.getGeneratedKeys(); - if (resultSetEmployee.next()) { - return resultSetEmployee.getLong(1); - } - } - - throw new PersistenceException("Employee was not created"); - - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - @Override - public void update(Employee employee) throws ElementNotFoundException, PersistenceException { - throw new UnsupportedOperationException(); - } - - @Override - public List<Employee> list() throws PersistenceException { - - try { - ResultSet rs = listEmployee.executeQuery(); - - List<Employee> employees = new ArrayList<>(); - while (rs.next()) { - - Employee employee = - Employee.builder() - .id(rs.getLong(1)) - .name(rs.getString(2)) - .birthday(rs.getTimestamp(3).toLocalDateTime().toLocalDate()) - .educationLevel(EducationLevel.valueOf(rs.getString(4))) - .isDriver(rs.getBoolean(5)) - .isPilot(rs.getBoolean(6)) - .build(); - - employees.add(employee); - } - - 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 index dd1a189..d82f768 100644 --- 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 @@ -5,7 +5,7 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Operation.S 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.List; +import java.util.Set; public interface OperationDAO { @@ -44,7 +44,5 @@ public interface OperationDAO { * @return list containing all matched operations * @throws PersistenceException if loading the stored operations failed */ - List<Operation> list(EnumSet<Status> statuses) throws PersistenceException; - - int connectVehicleToOperation(long vehicleID, long operationID) throws PersistenceException; + Set<Operation> list(EnumSet<Status> 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 new file mode 100644 index 0000000..0a465f2 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/OperationDatabaseDAO.java @@ -0,0 +1,218 @@ +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.sql.Timestamp; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Objects; +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.setTimestamp(3, Timestamp.from(Objects.requireNonNull(o.created()))); + 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<Long>) o.vehicles().stream().map(Vehicle::id)::iterator) { + pstmt.setLong(1, id); + pstmt.addBatch(); + } + + pstmt.executeBatch(); + } + con.commit(); + con.setAutoCommit(true); + return operationId; + } catch (SQLException e) { + 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<Long>) o.vehicles().stream().map(Vehicle::id)::iterator) { + pstmt.setLong(1, id); + pstmt.addBatch(); + } + + pstmt.executeBatch(); + } + con.commit(); + con.setAutoCommit(true); + } catch (SQLException e) { + 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<Operation> list(EnumSet<Status> 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. + String str = + statuses.stream() + .map(Enum::name) + .map(s -> "'" + s + "'") + .collect(Collectors.joining(",")); + String sql = "SELECT * FROM Operation WHERE status IN (" + str + ")"; + Set<Operation> 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.getTimestamp("created").toInstant()) + .destination(rs.getString("destination")) + .additionalInfo(rs.getString("additionalInfo")) + .build(); + } + + private Set<Vehicle> getVehiclesFromOperationId(long operationId) throws PersistenceException { + String sql = "SELECT vehicleId FROM VehicleOperation WHERE operationId = ?"; + Set<Vehicle> 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 index ba8f909..36b6f1b 100644 --- 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 @@ -3,7 +3,7 @@ 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.List; +import java.util.Set; public interface RegistrationDAO { @@ -15,7 +15,7 @@ public interface RegistrationDAO { * @return a list of the ids that were assigned * @throws PersistenceException if the registration could not be persisted */ - List<Long> add(long vehicleId, List<Registration> registrations) throws PersistenceException; + Set<Long> add(long vehicleId, Set<Registration> registrations) throws PersistenceException; /** * Make registration with the given id inactive. 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 index 8fbcd18..13f2c0f 100644 --- 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 @@ -1,5 +1,6 @@ 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; @@ -10,8 +11,10 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; -import java.util.LinkedList; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -26,20 +29,27 @@ public class RegistrationDatabaseDAO implements RegistrationDAO { "INSERT INTO Registration (vehicleId, employeeId, start, end, active) VALUES (?,?,?,?,?);"; private static final String UPDATE_VEHICLE = "UPDATE Vehicle SET status = 'FREI_WACHE' WHERE id = ?;"; + private static final String FETCH_REGISTRATIONS = + "SELECT * FROM Registration WHERE vehicleId = ?"; private PreparedStatement addRegistration; private PreparedStatement updateVehicle; + private PreparedStatement fetchRegistrations; private Connection connection; + private EmployeeDAO employeePersistence; @Autowired - public RegistrationDatabaseDAO(JDBCConnectionManager connectionManager) + public RegistrationDatabaseDAO( + JDBCConnectionManager connectionManager, EmployeeDAO employeePersistence) throws PersistenceException { + this.employeePersistence = employeePersistence; try { connection = connectionManager.getConnection(); addRegistration = connection.prepareStatement(ADD_REGISTRATION, Statement.RETURN_GENERATED_KEYS); updateVehicle = connection.prepareStatement(UPDATE_VEHICLE); + fetchRegistrations = connection.prepareStatement(FETCH_REGISTRATIONS); } catch (SQLException e) { LOG.error("Could not get connection or preparation of statement failed"); throw new PersistenceException(e); @@ -47,16 +57,16 @@ public class RegistrationDatabaseDAO implements RegistrationDAO { } @Override - public List<Long> add(long vehicleId, List<Registration> registrations) + public Set<Long> add(long vehicleId, Set<Registration> registrations) throws PersistenceException { - List<Long> returnValues = new LinkedList<>(); + Set<Long> returnValues = new HashSet<>(); try { connection.setAutoCommit(false); for (Registration registration : registrations) { addRegistration.setLong(1, vehicleId); addRegistration.setLong(2, registration.employee().id()); addRegistration.setTimestamp(3, Timestamp.from(registration.start())); - addRegistration.setObject(4, registration.end()); + addRegistration.setTimestamp(4, Timestamp.from(registration.end())); addRegistration.setBoolean( 5, true); // ASSUMPTION: Registration gets created as active addRegistration.executeUpdate(); @@ -103,4 +113,35 @@ public class RegistrationDatabaseDAO implements RegistrationDAO { public void remove(long id) throws ElementNotFoundException, PersistenceException { throw new UnsupportedOperationException(); } + + public List<Registration> list(long vehicleId) throws PersistenceException { + List<Registration> registrationList = new ArrayList<>(); + try { + fetchRegistrations.setLong(1, vehicleId); + ResultSet rs = fetchRegistrations.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.getTimestamp("start").toInstant()) + .end(rs.getTimestamp("end").toInstant()) + .employee(emp) + .build(); + registrationList.add(registration); + } + } catch (SQLException e) { + throw new PersistenceException(e); + } + + return registrationList; + } } 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 index fe12952..5782fd9 100644 --- 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 @@ -3,7 +3,7 @@ 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.List; +import java.util.Set; public interface VehicleDAO { @@ -31,7 +31,17 @@ public interface VehicleDAO { * @return list containing all stored vehicles * @throws PersistenceException if loading the stored vehicles failed */ - List<Vehicle> list() throws PersistenceException; + Set<Vehicle> 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. 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 new file mode 100644 index 0000000..6d50588 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDAO.java @@ -0,0 +1,220 @@ +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; + } + + public long add(Vehicle vehicle) throws PersistenceException { + String query1 = + "INSERT INTO VehicleVersion (name,hasNef,constructionType,type) VALUES (?,?,?,?)"; + String query2 = "INSERT INTO Vehicle (version,status) VALUES (?,?)"; + + String status = "ABGEMELDET"; + String name = ""; + int id = -1; + int version = -1; + try { + Connection connection = jdbcConnectionManager.getConnection(); + connection.setAutoCommit(false); + try (PreparedStatement p1 = + connection.prepareStatement(query1, PreparedStatement.RETURN_GENERATED_KEYS)) { + + p1.setString(1, name); + p1.setBoolean(2, vehicle.hasNef()); + p1.setString(3, vehicle.constructionType().name()); + + p1.setString(4, vehicle.type().name()); + + p1.executeUpdate(); + try (ResultSet keyResultSet = p1.getGeneratedKeys()) { + + if (keyResultSet.next()) { + version = keyResultSet.getInt(1); + } + } + } + try (PreparedStatement p2 = + connection.prepareStatement(query2, Statement.RETURN_GENERATED_KEYS)) { + + p2.setInt(1, version); + p2.setString(2, status); + p2.executeUpdate(); + try (ResultSet keyResultSet = p2.getGeneratedKeys()) { + + if (keyResultSet.next()) { + id = keyResultSet.getInt(1); + } + } + + name = vehicle.type().name() + "-" + id; + } + query1 = "UPDATE VehicleVersion SET name=? WHERE id=?"; + try (PreparedStatement p3 = connection.prepareStatement(query1)) { + p3.setString(1, name); + p3.setInt(2, version); + p3.executeUpdate(); + } + + connection.commit(); + connection.setAutoCommit(true); + } catch (SQLException e) { + throw new PersistenceException(e); + } + return id; + } + + @Override + public void update(Vehicle vehicle) throws ElementNotFoundException, PersistenceException { + String query = "SELECT * FROM vehicle WHERE id=?"; + + long vehicleID = -1; + long vehicleVersion = -1; + try { + Connection connection = jdbcConnectionManager.getConnection(); + connection.setAutoCommit(false); + try (PreparedStatement p = + connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { + + p.setLong(1, vehicle.id()); + p.executeQuery(); + try (ResultSet rs = p.getResultSet()) { + while (rs.next()) { + vehicleID = rs.getLong("id"); + } + } + } + if (vehicleID == -1) { + throw new ElementNotFoundException("Vehicle don´t found"); + } + + query = + "INSERT INTO VehicleVersion (name,hasNef,constructionType,type) VALUES (?,?,?,?)"; + String name = ""; + try (PreparedStatement p = + connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { + p.setString(1, name); + p.setBoolean(2, vehicle.hasNef()); + p.setString(3, vehicle.constructionType().name()); + + p.setString(4, vehicle.type().name()); + + p.executeUpdate(); + + try (ResultSet keyResultSet = p.getGeneratedKeys()) { + + if (keyResultSet.next()) { + vehicleVersion = keyResultSet.getInt(1); + } + } + if (vehicleVersion == -1) { + throw new ElementNotFoundException("Vehicle don´t found"); + } + } + name = vehicle.type().name() + "-" + vehicleID; + + query = "UPDATE VehicleVersion SET name=? WHERE id=?"; + try (PreparedStatement p = connection.prepareStatement(query)) { + + p.setString(1, name); + p.setLong(2, vehicleVersion); + p.executeUpdate(); + } + query = "UPDATE Vehicle SET version=? WHERE id=?"; + try (PreparedStatement p = connection.prepareStatement(query)) { + + p.setLong(1, vehicleVersion); + p.setLong(2, vehicleID); + p.executeUpdate(); + } + connection.commit(); + connection.setAutoCommit(true); + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + @Override + public Set<Vehicle> list() throws PersistenceException { + Set<Vehicle> 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("Die Werte konnten nicht geladen werden.", 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 {} + + 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/dao/VehicleDatabaseDao.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDao.java deleted file mode 100644 index ca1d45c..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/VehicleDatabaseDao.java +++ /dev/null @@ -1,147 +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.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.LinkedList; -import java.util.List; -import org.springframework.stereotype.Repository; - -@Repository -public class VehicleDatabaseDao implements VehicleDAO { - - private final JDBCConnectionManager jdbcConnectionManager; - - public VehicleDatabaseDao(JDBCConnectionManager j) { - jdbcConnectionManager = j; - } - - public long add(Vehicle vehicle) throws PersistenceException { - String query1 = - "INSERT INTO VehicleVersion (name,hasNef,constructionType,type) VALUES (?,?,?,?)"; - String query2 = "INSERT INTO Vehicle (version,status) VALUES (?,?)"; - PreparedStatement p1 = null; - PreparedStatement p2 = null; - PreparedStatement p3 = null; - String status = "ABGEMELDET"; - String name = ""; - int id = -1; - try { - p1 = - jdbcConnectionManager - .getConnection() - .prepareStatement(query1, PreparedStatement.RETURN_GENERATED_KEYS); - p1.setString(1, name); - p1.setBoolean(2, vehicle.hasNef()); - p1.setString(3, vehicle.constructionType().name()); - if (vehicle.type() == VehicleType.KTW_B) { - p1.setString(4, "KTW-B"); - } else { - p1.setString(4, vehicle.type().name()); - } - p1.executeUpdate(); - - ResultSet keyResultSet = p1.getGeneratedKeys(); - - if (keyResultSet.next()) { - id = keyResultSet.getInt(1); - } - - name = vehicle.type().name() + "-" + id; - - } catch (SQLException e) { - throw new PersistenceException("SQL Excpetion : " + e.toString()); - } finally { - try { - p1.close(); - - } catch (SQLException e) { - throw new PersistenceException("SQL Excpetion : " + e.toString()); - } - } - try { - query1 = "UPDATE VehicleVersion SET name=? WHERE id=?"; - p3 = jdbcConnectionManager.getConnection().prepareStatement(query1); - p3.setString(1, name); - p3.setInt(2, id); - p3.executeUpdate(); - } catch (SQLException e) { - throw new PersistenceException("SQL Excpetion : " + e.toString()); - } finally { - try { - p3.close(); - } catch (SQLException e) { - throw new PersistenceException("SQL Excpetion : " + e.toString()); - } - } - try { - p2 = jdbcConnectionManager.getConnection().prepareStatement(query2); - p2.setInt(1, id); - p2.setString(2, status); - p2.executeUpdate(); - } catch (SQLException e) { - throw new PersistenceException("SQL Excpetion : " + e.toString()); - } finally { - try { - p2.close(); - } catch (SQLException e) { - throw new PersistenceException("SQL Excpetion : " + e.toString()); - } - } - return id; - } - - @Override - public void update(Vehicle vehicle) throws ElementNotFoundException, PersistenceException {} - - @Override - public List<Vehicle> list() throws PersistenceException { - PreparedStatement pstmt = null; - List<Vehicle> result = new LinkedList<>(); - try { - pstmt = - jdbcConnectionManager - .getConnection() - .prepareStatement( - "Select * from VehicleVersion, " - + "Vehicle where VehicleVersion.id=Vehicle.version"); - pstmt.executeQuery(); - ResultSet rs = pstmt.getResultSet(); - while (rs.next()) { - Vehicle vehicle = - Vehicle.builder() - .name(rs.getString("name")) - .constructionType( - ConstructionType.valueOf(rs.getString("constructionType"))) - .status(Status.valueOf(rs.getString("status"))) - .id(rs.getInt("id")) - .hasNef(rs.getBoolean("hasNef")) - .type(VehicleType.valueOf(rs.getString("type").replace("-", "_"))) - .build(); - result.add(vehicle); - } - } catch (SQLException e) { - throw new PersistenceException("Die Werte konnten nicht geladen werden.", e); - } finally { - if (pstmt != null) { - try { - pstmt.close(); - } catch (SQLException e) { - throw new PersistenceException( - "Verbindung zur Datenbank konnte nicht geschlossen werden!", e); - } - } - } - return result; - } - - @Override - public void remove(long id) throws ElementNotFoundException, PersistenceException {} -} 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 index 6641437..3a97dc7 100644 --- 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 @@ -2,7 +2,7 @@ package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; import com.google.auto.value.AutoValue; import java.time.Instant; -import java.util.List; +import java.util.Set; import javax.annotation.Nullable; @AutoValue @@ -26,17 +26,19 @@ public abstract class Operation { public abstract String opCode(); + @Nullable public abstract Severity severity(); public abstract Status status(); - public abstract List<Vehicle> vehicles(); + public abstract Set<Vehicle> vehicles(); @Nullable public abstract Instant created(); public abstract String destination(); + @Nullable public abstract String additionalInfo(); public static Builder builder() { @@ -53,7 +55,7 @@ public abstract class Operation { public abstract Builder status(Status status); - public abstract Builder vehicles(List<Vehicle> vehicles); + public abstract Builder vehicles(Set<Vehicle> vehicles); public abstract Builder created(Instant created); 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 index 295b615..610426c 100644 --- 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 @@ -7,6 +7,7 @@ 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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,7 +17,7 @@ public class RegistrationValidator { private RegistrationValidator() {} - public static void validate(Vehicle vehicle, List<Registration> registrations) + public static void validate(Vehicle vehicle, Set<Registration> registrations) throws InvalidVehicleException, InvalidRegistrationException { /* Vehicles and Employees are assumed to be valid. 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 index 84d9c92..e81db0b 100644 --- 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 @@ -24,11 +24,11 @@ public abstract class Vehicle { public enum Status { ABGEMELDET, FREI_WACHE, + FREI_FUNK, ZUM_BERUFUNGSORT, AM_BERUFUNGSORT, ZUM_ZIELORT, AM_ZIELORT, - FREI_FUNK, } public abstract long id(); 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 index 8753504..f7f8e71 100644 --- 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 @@ -3,7 +3,7 @@ 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.List; +import java.util.Set; public interface EmployeeService { @@ -33,7 +33,7 @@ public interface EmployeeService { * @return list containing all stored employees * @throws ServiceException if loading the stored employees failed */ - List<Employee> list() throws ServiceException; + Set<Employee> list() throws ServiceException; /** * Remove employee with the given id from the store. 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 index ed0fb1c..31b5acd 100644 --- 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 @@ -3,10 +3,11 @@ 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.List; +import java.util.Set; import org.springframework.stereotype.Service; @Service @@ -31,11 +32,18 @@ public class EmployeeServiceImpl implements EmployeeService { @Override public Employee update(Employee employee) throws InvalidEmployeeException, ServiceException { - return null; + + EmployeeValidator.validate(employee); + try { + employeePersistence.update(employee); + return employee; + } catch (ElementNotFoundException | PersistenceException e) { + throw new ServiceException(e); + } } @Override - public List<Employee> list() throws ServiceException { + public Set<Employee> list() throws ServiceException { try { return employeePersistence.list(); 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 index e21c10b..4b7e630 100644 --- 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 @@ -7,8 +7,8 @@ import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationExcepti 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.List; -import javafx.collections.transformation.SortedList; +import java.util.Set; +import java.util.SortedSet; public interface OperationService { @@ -32,7 +32,7 @@ public interface OperationService { * @throws ServiceException if the vehicles could not be loaded or the operation could not be * persisted */ - void requestVehicles(long operationId, List<Long> vehicleIds) + void requestVehicles(long operationId, Set<Long> vehicleIds) throws InvalidOperationException, InvalidVehicleException, ServiceException; /** @@ -48,15 +48,15 @@ public interface OperationService { throws InvalidOperationException, ServiceException; /** - * Get all available vehicles, sorted by how well they fit to the given operation, starting with + * Get all available vehicles, sorted by how well they fit to the given opCode, starting with * the best fitting. * - * @param operationId id of the operation that is used to determine the ranking + * @param opCode the operation code that is used to determine the ranking * @return a sorted list containing all available vehicles - * @throws InvalidOperationException if the operationId is invalid or does not exist + * @throws InvalidOperationException if the opCode is invalid * @throws ServiceException if loading the stored vehicles failed */ - SortedList<Vehicle> rankVehicles(long operationId) + SortedSet<Vehicle> rankVehicles(String opCode) throws InvalidOperationException, ServiceException; /** @@ -66,5 +66,5 @@ public interface OperationService { * @return list containing all matched operations * @throws ServiceException if loading the stored operations failed */ - List<Operation> list(EnumSet<Status> statuses) throws ServiceException; + Set<Operation> list(EnumSet<Status> 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 index 05a548c..d07f46f 100644 --- 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 @@ -1,131 +1,264 @@ 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.lang.invoke.MethodHandles; +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 javafx.collections.transformation.SortedList; +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 { - // TODO: anders? - private OperationDAO operationDAO; + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - public OperationServiceImpl(OperationDAO dao) { - this.operationDAO = dao; + 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 operation) throws InvalidOperationException, ServiceException { - List<Vehicle> vehicles = operation.vehicles(); - boolean rtw = false; - if (faultyInput(operation.opCode())) { - throw new InvalidOperationException("Code ist ungültig!"); - } - if (faultyInput(operation.destination())) { - throw new InvalidOperationException("Adresse ist ungültig!"); - } - if (operation.vehicles().size() == 0) { - throw new InvalidOperationException( - "Es muss mindestens ein Fahrzeug ausgewählt werden!"); + public long add(Operation o) throws InvalidOperationException, ServiceException { + if (o.created() != null) throw new InvalidOperationException("Created must not be set"); + + if (o.severity() != null) throw new InvalidOperationException("Severity must not be set"); + + if (o.id() != 0) throw new InvalidOperationException("Id must be 0"); + + if (o.status() != Status.ACTIVE) + LOG.warn("Status was set but will be overridden"); // TODO: nullable instead?? + + try { + for (long id : (Iterable<Long>) o.vehicles().stream().map(Vehicle::id)::iterator) { + Vehicle v = vehicleDAO.get(id); + VehicleServiceImpl.validateVehicle(v); + } + + validateOperation(o); + + return operationDAO.add( + o.toBuilder() + .created(Instant.now()) + .severity(extractSeverityFromOpCode(o.opCode())) + .status(Status.ACTIVE) + .build()); + } catch (PersistenceException e) { + LOG.error("PersistenceException while adding operation: {}", e); + throw new ServiceException(e); + } catch (InvalidVehicleException e) { + throw new InvalidOperationException("Enthaltenes Fahrzeug ist invalid", e); + } catch (ElementNotFoundException e) { + throw new InvalidOperationException("Enthaltenes Fahrzeug existiert nicht", e); } - for (Vehicle vehicle : vehicles) { - if (vehicle.status() == Vehicle.Status.ABGEMELDET - || (vehicle.status() != Vehicle.Status.FREI_FUNK - && vehicle.status() != Vehicle.Status.FREI_WACHE)) - throw new InvalidOperationException( - "Abgemeldete Fahrzeuge dürfen nicht zu einem Einsatz geschickt werden!"); - /*if (vehicle.type() == VehicleType.NEF && !rtw) { - for (Vehicle vehicleA : vehicles) { - if (vehicleA.type() == VehicleType.RTW && vehicleA.hasNef()) { - rtw = true; - break; - } - } - if (!rtw) - throw new InvalidOperationException( - "Zu einem Fahrzeug des Typs NEF muss auch ein Fahrzeug des Typs RTW mit NEF-Halterung geschickt werden!"); - }*/ - /* if (vehicle.type() == VehicleType.NAH && !rtw) { - for (Vehicle vehicleA : vehicles) { - if (vehicleA.type() == VehicleType.RTW) { - rtw = true; - break; - } + } + + @Override + public void requestVehicles(long operationId, Set<Long> vehicleIds) + throws InvalidOperationException, InvalidVehicleException, ServiceException { + Set<Vehicle> vs = new HashSet<>(); + + try { + if (operationId <= 0) throw new InvalidOperationException("OperationId ist invalid"); + Operation o = operationDAO.get(operationId); + validateOperation(o); + + if (o.opCode().trim().isEmpty() + || extractSeverityFromOpCode(o.opCode()) != o.severity()) + throw new InvalidOperationException("Einsatzcode ist invalid"); + + if (o.status() != Status.ACTIVE) + throw new InvalidOperationException("Einsatz ist inaktiv"); + + if (o.created() == null) + throw new InvalidOperationException("Created darf nicht leer sein"); + + for (Long id : vehicleIds) { + if (id <= 0) throw new InvalidVehicleException("VehicleId ist invalid"); + + try { + Vehicle v = vehicleDAO.get(id); + VehicleServiceImpl.validateVehicle(v); + if (v.status() == Vehicle.Status.ABGEMELDET) + throw new InvalidVehicleException( + "Kann keine inaktiven Fahrzeuge anfordern"); + + vs.add(v); + } catch (ElementNotFoundException e) { + throw new InvalidVehicleException("VehicleId ist invalid"); } - if (!rtw) - throw new InvalidOperationException( - "Zu einem Fahrzeug des Typs NAH muss auch ein Fahrzeug des Typs RTW geschickt werden!"); - }*/ - } - String[] codeParts = operation.opCode().split("-"); - String severity = ""; - for (int i = 0; i < codeParts[1].length(); i++) { - if (((int) (codeParts[1].charAt(i)) >= 65 && (int) (codeParts[1].charAt(i)) <= 79) - || ((int) (codeParts[1].charAt(i)) >= 97 - && (int) (codeParts[1].charAt(i)) <= 111)) { - severity = "" + codeParts[1].charAt(i); - break; } + + 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) { + LOG.error("PersistenceException while requesting vehicles: {}", e); + throw new ServiceException(e); } + } + + @Override + public void complete(long operationId, Status status) + throws InvalidOperationException, ServiceException { try { - operation = operation.toBuilder().severity(Severity.valueOf(severity)).build(); - } catch (IllegalArgumentException e) { - throw new InvalidOperationException( - "Der Schweregrad des Einsatzes konnte nicht ausgelesen werden!"); + Operation o = operationDAO.get(operationId); + operationDAO.update(o.toBuilder().status(status).build()); + } catch (ElementNotFoundException e) { + throw new InvalidOperationException(e); + } catch (PersistenceException e) { + LOG.error("PersistenceException while completing operation: {}", e); + throw new ServiceException(e); + } + } + + @Override + public SortedSet<Vehicle> rankVehicles(String opCode) + throws InvalidOperationException, ServiceException { + Set<Vehicle> vehicles = + vehicleService.list(EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET))); + + List<Predicate<Vehicle>> priorities = new ArrayList<>(); + Predicate<Vehicle> ktw = v -> v.type() == VehicleType.KTW; + Predicate<Vehicle> rtwNoNEF = v -> v.type() == VehicleType.RTW && !v.hasNef(); + Predicate<Vehicle> rtwNEF = v -> v.type() == VehicleType.RTW && v.hasNef(); + Predicate<Vehicle> nef = v -> v.type() == VehicleType.NEF; + Predicate<Vehicle> 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; } - operation = operation.toBuilder().status(Status.ACTIVE).build(); - long operationId = -1; + Comparator<Vehicle> vehicleComparator = + (v1, v2) -> { + for (Predicate<Vehicle> priority : priorities) { + if (priority.test(v1)) { + return -1; + } + if (priority.test(v2)) { + return +1; + } + } + return 0; + }; + + Supplier<TreeSet<Vehicle>> supplier = () -> new TreeSet<>(vehicleComparator); + + return vehicles.stream().collect(Collectors.toCollection(supplier)); + } + + @Override + public Set<Operation> list(EnumSet<Status> statuses) throws ServiceException { try { - operationId = operationDAO.add(operation); + Set<Operation> operations = operationDAO.list(statuses); + for (Operation o : operations) validateOperation(o); + + return operations; } catch (PersistenceException e) { + LOG.error("PersistenceException while listing operations", e); throw new ServiceException(e); + } catch (InvalidOperationException e) { + // database returned invalid values + LOG.error("DB returned invalid operation: {}", e); + 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 vehicle : vehicles) { + for (Vehicle v : o.vehicles()) { try { - operationDAO.connectVehicleToOperation(vehicle.id(), operationId); - } catch (PersistenceException e) { - throw new ServiceException(e); + VehicleServiceImpl.validateVehicle(v); + } catch (InvalidVehicleException e) { + throw new InvalidOperationException("Fahrzeug " + v.name() + " ist invalid" + e); } - } - return operationId; - } + if (v.status() != Vehicle.Status.FREI_FUNK && v.status() != Vehicle.Status.FREI_WACHE) + throw new InvalidOperationException( + "Fahrzeug nicht verfügbar (" + v.status() + ")"); - private boolean faultyInput(String name) { - if (name == null) return true; - else if (name.isEmpty()) return true; - for (int i = 0; i < name.length(); i++) { - if (name.charAt(i) != ' ') return false; + // TODO: validate if NEF/RTW/NAH conditions? } - return true; + + Instant created = o.created(); + if (created != null && created.isAfter(Instant.now())) + throw new InvalidOperationException("Fahrzeug wurde in der Zukunft erstellt"); + + if (o.destination().trim().isEmpty()) + throw new InvalidOperationException("Adresse darf nicht leer sein"); } - @Override - public void requestVehicles(long operationId, List<Long> vehicleIds) - throws InvalidOperationException, InvalidVehicleException, ServiceException {} + private static final Pattern opCodePattern = + Pattern.compile("(?:\\w{1,3}-\\d{0,2})([ABCDEO])(?:.*)"); - @Override - public void complete(long operationId, Status status) - throws InvalidOperationException, ServiceException {} + private static Severity extractSeverityFromOpCode(String opCode) + throws InvalidOperationException { + Matcher m = opCodePattern.matcher(opCode); - @Override - public SortedList<Vehicle> rankVehicles(long operationId) - throws InvalidOperationException, ServiceException { - return null; - } + if (!m.matches()) throw new InvalidOperationException("Einsatzcode ist invalid"); - @Override - public List<Operation> list(EnumSet<Status> statuses) throws ServiceException { - return null; + 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 index c345a2b..b7d8eef 100644 --- 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 @@ -4,7 +4,7 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registratio 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.List; +import java.util.Set; public interface RegistrationService { @@ -18,7 +18,7 @@ public interface RegistrationService { * @throws InvalidRegistrationException if the registration is invalid * @throws ServiceException if the registration could not be persisted */ - List<Long> add(long vehicleId, List<Registration> registrations) + Set<Long> add(long vehicleId, Set<Registration> registrations) throws InvalidVehicleException, 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 index a267b6f..54d46e7 100644 --- 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 @@ -1,16 +1,16 @@ 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.einsatzverwaltung.dto.Vehicle.Status; +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.EnumSet; -import java.util.List; +import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -22,36 +22,31 @@ public class RegistrationServiceImpl implements RegistrationService { private static final Logger LOG = LoggerFactory.getLogger(RegistrationServiceImpl.class); private final RegistrationDAO registrationDAO; - private final VehicleService vehicleService; + private final VehicleDAO vehicleDAO; @Autowired - public RegistrationServiceImpl(RegistrationDAO registrationDAO, VehicleService vehicleService) { + public RegistrationServiceImpl(RegistrationDAO registrationDAO, VehicleDAO vehicleDAO) { this.registrationDAO = registrationDAO; - this.vehicleService = vehicleService; + this.vehicleDAO = vehicleDAO; } @Override - public List<Long> add(long vehicleId, List<Registration> registrations) + public Set<Long> add(long vehicleId, Set<Registration> registrations) throws InvalidVehicleException, InvalidRegistrationException, ServiceException { - Vehicle vehicle = - vehicleService - .list(EnumSet.of(Status.ABGEMELDET)) - .stream() - .filter(v -> v.id() == vehicleId) - .findFirst() - .orElse(null); + if (vehicleId <= 0) throw new InvalidVehicleException("VehicleId invalid"); - if (vehicle == null) { - throw new ServiceException("no vehicle with this id"); - } - - RegistrationValidator.validate(vehicle, registrations); try { + Vehicle vehicle = vehicleDAO.get(vehicleId); + + RegistrationValidator.validate(vehicle, registrations); + return registrationDAO.add(vehicle.id(), registrations); } catch (PersistenceException e) { LOG.warn("PersistenceException caught, throwing matching ServiceException"); throw new ServiceException(e); + } catch (ElementNotFoundException e) { + throw new InvalidVehicleException(e); } } 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 index 6a96bc5..fe09ca1 100644 --- 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 @@ -5,7 +5,7 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Sta 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.List; +import java.util.Set; public interface VehicleService { @@ -36,7 +36,7 @@ public interface VehicleService { * @return list containing all stored vehicles * @throws ServiceException if loading the stored vehicles failed */ - List<Vehicle> list(EnumSet<Status> statuses) throws ServiceException; + Set<Vehicle> list(EnumSet<Status> statuses) throws ServiceException; /** * Remove vehicle with the given id from the store. 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 index bbe668b..61a24e5 100644 --- 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 @@ -4,13 +4,15 @@ 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.List; +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 { @@ -22,7 +24,31 @@ public class VehicleServiceImpl implements VehicleService { } public long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException { + if (!CollectionUtils.isEmpty(vehicle.registrations())) + throw new InvalidVehicleException("Vehicle can't be created with registrations"); + 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"); + } 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) { @@ -58,28 +84,17 @@ public class VehicleServiceImpl implements VehicleService { case BKTW: break; default: - throw new ServiceException("not a Valid type"); - } - try { - vehiclePersistence.add(vehicle); - } catch (PersistenceException e) { - throw new ServiceException(e); + throw new IllegalStateException("BUG: invalid vehicle type" + vehicle.type()); } - return 0; - } - - public Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException { - throw new UnsupportedOperationException(); } @Override - public List<Vehicle> list(EnumSet<Status> statuses) throws ServiceException { - + public Set<Vehicle> list(EnumSet<Status> statuses) throws ServiceException { if (statuses == null) { throw new ServiceException("statuses may not be null"); } - List<Vehicle> vehicles; + Set<Vehicle> vehicles; try { vehicles = vehiclePersistence.list(); @@ -89,7 +104,7 @@ public class VehicleServiceImpl implements VehicleService { return vehicles.stream() .filter(vehicle -> statuses.contains(vehicle.status())) - .collect(Collectors.toList()); + .collect(Collectors.toSet()); } @Override diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/userInterface/CreateOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/userInterface/CreateOperationController.java deleted file mode 100644 index 5b645f3..0000000 --- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/userInterface/CreateOperationController.java +++ /dev/null @@ -1,227 +0,0 @@ -package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.userInterface; - -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.DBOperationDAO; -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.service.OperationService; -import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.OperationServiceImpl; -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.ServiceException; -import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; -import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.time.Instant; -import java.util.EnumSet; -import java.util.LinkedList; -import java.util.List; -import javafx.collections.FXCollections; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.Parent; -import javafx.scene.Scene; -import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.Button; -import javafx.scene.control.Label; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; -import javafx.scene.control.TextField; -import javafx.scene.layout.AnchorPane; -import javafx.stage.Stage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Controller; - -@Controller -public class CreateOperationController { - - private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - public AnchorPane apCreateOperation; - public TextField txtCode; - public TextField txtAddress; - public TextField txtNote; - public Button btnCreateOperation; - public ListView<Vehicle> lvVehicles; - public ListView lvActiveOperations; - public Label lblChosenVehicles; - public LinkedList<Vehicle> chosenVehicles = new LinkedList<>(); - - // TODO: Anders? - OperationService operationService = - new OperationServiceImpl(new DBOperationDAO(new JDBCConnectionManager())); - private final VehicleService vehicleService; - private final SpringFXMLLoader fxmlLoader; - - public CreateOperationController(VehicleService vehicleService, SpringFXMLLoader fxmlLoader) { - this.vehicleService = vehicleService; - this.fxmlLoader = fxmlLoader; - } - - @FXML - public void initialize() { - lblChosenVehicles.setText("keine ausgewählt"); - lvVehicles.setCellFactory( - param -> - new ListCell<Vehicle>() { - @Override - protected void updateItem(Vehicle item, boolean empty) { - super.updateItem(item, empty); - - if (empty || item == null || item.name() == null) { - setText(null); - } else { - setText(item.name()); - } - } - }); - - lvVehicles.setOnMouseClicked( - event -> { - if (event.getClickCount() == 2) { - boolean remove = false; - if (lvVehicles.getSelectionModel().getSelectedItem() == null) { - return; - } - for (Vehicle vehicle : chosenVehicles) { - if (lvVehicles.getSelectionModel().getSelectedItem().equals(vehicle)) { - remove = true; - break; - } - } - if (!remove) { - chosenVehicles.add(lvVehicles.getSelectionModel().getSelectedItem()); - - } else { - chosenVehicles.remove(lvVehicles.getSelectionModel().getSelectedItem()); - } - 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()); - } - } - }); - } - - public void updateList() { - try { - this.lvVehicles.setItems( - FXCollections.observableArrayList( - vehicleService.list( - EnumSet.of( - Vehicle.Status.FREI_FUNK, Vehicle.Status.FREI_WACHE)))); - } catch (ServiceException e) { - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setTitle("Fehler"); - alert.setHeaderText("Fehler!"); - alert.setContentText(e.getMessage()); - alert.showAndWait(); - } - } - - /*private LinkedList<Vehicle> mylist() { - Vehicle vehicle = - Vehicle.builder() - .name("Test-KTW") - .constructionType(ConstructionType.HOCHDACH) - .type(VehicleType.KTW) - .status(Vehicle.Status.FREI_WACHE) - .hasNef(true) - .build(); - - Vehicle vehicle1 = - Vehicle.builder() - .name("Test-NEF") - .constructionType(ConstructionType.NORMAL) - .type(VehicleType.NEF) - .status(Vehicle.Status.FREI_FUNK) - .hasNef(true) - .build(); - LinkedList<Vehicle> list = new LinkedList<>(); - list.add(vehicle); - list.add(vehicle1); - // this.lvVehicles.setItems(FXCollections.observableArrayList(list)); - return list; - }*/ - - @FXML - protected void createOperationClicked() { - 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()) - .created(Instant.now()) - .opCode(txtCode.getText()) - .status(Status.ACTIVE) - .vehicles(List.of(vehicles)) - .severity(Severity.A) - .build(); - try { - operationService.add(operation); - } catch (ServiceException | InvalidOperationException e) { - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setTitle("Fehler"); - alert.setHeaderText("Fehler!"); - alert.setContentText(e.getMessage()); - alert.showAndWait(); - return; - } - Alert alert = new Alert(AlertType.CONFIRMATION); - alert.setTitle("Erfolg"); - alert.setHeaderText("Erfolgreich gespeichert"); - alert.setContentText("Der Einsatz wurde erfolgreich gespeichert."); - alert.showAndWait(); - updateList(); - } - - public void onRegistrationLinkClicked(ActionEvent actionEvent) { - openNewWindow("RegistrationWindow.fxml"); - } - - public void onEmployeeLinkClicked(ActionEvent actionEvent) { - openNewWindow("createNewEmployee.fxml"); - } - - public void onVehicleLinkClicked(ActionEvent actionEvent) { - openNewWindow("createCar.fxml"); - } - - private void openNewWindow(String fxmlFileName) { - - Stage stage = new Stage(); - try { - stage.setScene( - new Scene( - (Parent) - fxmlLoader.load( - getClass() - .getResourceAsStream( - "/fxml/" + fxmlFileName)))); - } catch (IOException e) { - LOG.error("Could not open new window: {}", e); - } - - stage.setTitle("Einsatz erstellen"); - stage.centerOnScreen(); - stage.showAndWait(); // important to call wait so that updateList is executed afterwards - - updateList(); - } -} |