diff options
Diffstat (limited to 'src/main/java')
28 files changed, 1483 insertions, 332 deletions
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..e88e640 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,10 +35,14 @@ 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; @@ -62,6 +71,7 @@ public class CreateCarController {                                  .map(Enum::toString)                                  .collect(Collectors.toList())));          cmb_typ.setValue(VehicleType.BKTW.toString()); +        vehicleListFP();      }      @FXML @@ -71,27 +81,64 @@ public class CreateCarController {      @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; + +        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..99614d0 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,37 +5,49 @@ 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; @@ -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(); +        if (consumerCancelClicked != null) { +            consumerCancelClicked.run(); +        }      }      @FXML      public 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/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..0d2f894 --- /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 +    public void onAddEmployeeClicked() { +        if (consumerAddEmployeeClicked != null) { +            consumerAddEmployeeClicked.run(); +        } +    } + +    @FXML +    public 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..038b14c --- /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 +    public 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/RegistrationWindowController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java index bf413bb..9ed6147 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; @@ -78,7 +80,7 @@ public class RegistrationWindowController {      public 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 +94,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) { @@ -147,7 +149,7 @@ public class RegistrationWindowController {      public void create() {          LOG.debug("Create Button clicked"); -        List<Registration> registrations = new LinkedList<>(); +        Set<Registration> registrations = new HashSet<>();          for (Employee employee : chosenEmployees) {              registrations.add( 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 index 672424a..773ccb6 100644 --- 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 @@ -1,23 +1,68 @@  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.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.Registration; +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.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.lang.invoke.MethodHandles; +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.LinkedList;  import java.util.List; +import java.util.Objects; +import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; +@Repository  public class DBOperationDAO implements OperationDAO {      private JDBCConnectionManager jdbcConnectionManager; +    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());      public DBOperationDAO(JDBCConnectionManager j) {          jdbcConnectionManager = j; +        try { + +            getVehicleId = jdbcConnectionManager.getConnection().prepareStatement(GET_VEHICLE_ID); + +            getVehicle = jdbcConnectionManager.getConnection().prepareStatement(GET_VEHICLE); + +            getVehicleVersion = +                    jdbcConnectionManager.getConnection().prepareStatement(GET_VEHICLE_VERSION); + +            getRegistrations = +                    jdbcConnectionManager.getConnection().prepareStatement(GET_REGISTRATIONS); + +            getEmployee = jdbcConnectionManager.getConnection().prepareStatement(GET_EMPLOYEE); + +            getEmployeeVersion = +                    jdbcConnectionManager.getConnection().prepareStatement(GET_EMPLOYEE_VERSION); + +        } catch (SQLException e) { + +            LOG.error( +                    "SQLException occurred while preparing Statements. Error message: {} ", +                    e.getMessage()); + +            // TODO: nothing should be thrown here +            throw new IllegalStateException("TODO: fix me"); +            // throw new PersistenceException(e); +        }      }      @Override @@ -66,7 +111,7 @@ public class DBOperationDAO implements OperationDAO {              }*/              pstmt.setString(2, operation.severity().name());              if (operation.created() != null) { -                pstmt.setTimestamp(3, Timestamp.from(operation.created())); +                pstmt.setTimestamp(3, Timestamp.from(Objects.requireNonNull(operation.created())));              } else {                  throw new PersistenceException("Zeitpunkt der Erstellung darf nicht null sein!");              } @@ -110,7 +155,49 @@ public class DBOperationDAO implements OperationDAO {      }      @Override -    public void update(Operation operation) throws ElementNotFoundException, PersistenceException {} +    public void update(Operation o) throws ElementNotFoundException, PersistenceException { +        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: " + pstmt); +            } + +            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 { @@ -118,8 +205,189 @@ public class DBOperationDAO implements OperationDAO {      }      @Override -    public List<Operation> list(EnumSet<Status> statuses) throws PersistenceException { -        return null; +    public Set<Operation> list(EnumSet<Status> statuses) throws PersistenceException { +        String sql = "SELECT * FROM Operation WHERE status IN (?)"; +        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("INTEGER", 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 { +        return Operation.builder() +                .id(rs.getLong("id")) +                .opCode(rs.getString("opCode")) +                .severity(Severity.valueOf(rs.getString("severity"))) +                .status(Status.valueOf(rs.getString("status"))) +                .vehicles(getVehiclesFromOperationId(rs.getLong("id"))) +                .created(rs.getTimestamp("created").toInstant()) +                .destination(rs.getString("destination")) +                .additionalInfo(rs.getString("additionalInfo")) +                .build(); +    } + +    private static String GET_VEHICLE_ID = +            "SELECT vehicleId FROM VehicleOperation WHERE operationId = ? ;"; + +    private final PreparedStatement getVehicleId; + +    private Set<Vehicle> getVehiclesFromOperationId(long operationId) throws PersistenceException { +        Set<Vehicle> vehicles = new HashSet<>(); +        try { +            getVehicleId.setLong(1, operationId); +            try (ResultSet resultSet = getVehicleId.executeQuery()) { +                while (resultSet.next()) { +                    vehicles.add(getVehicle(resultSet.getLong("vehicleId"))); +                } +            } +        } catch (SQLException e) { +            LOG.error( +                    "SQLException occurred while getting VehicleId from OperationId. Error message: {}", +                    e.getMessage()); +            throw new PersistenceException(e); +        } +        return vehicles; +    } + +    private static String GET_VEHICLE = "SELECT * FROM Vehicle WHERE id = ? ;"; + +    private final PreparedStatement getVehicle; + +    private Vehicle getVehicle(long vehicleId) throws PersistenceException { +        try { +            getVehicle.setLong(1, vehicleId); +            try (ResultSet resultSet = getVehicle.executeQuery()) { +                resultSet.next(); +                return getVehicleVersion( +                        resultSet.getLong("id"), +                        resultSet.getLong("version"), +                        resultSet.getString("status")); +            } +        } catch (SQLException e) { +            LOG.error( +                    "SQLException occurred while getting Vehicle by id. Error message: {}", +                    e.getMessage()); +            throw new PersistenceException(e); +        } +    } + +    private static String GET_VEHICLE_VERSION = "SELECT * FROM VehicleVersion WHERE id = ? ;"; + +    private final PreparedStatement getVehicleVersion; + +    private Vehicle getVehicleVersion(long vehicleId, long versionId, String status) +            throws PersistenceException { +        try { +            getVehicleVersion.setLong(1, versionId); +            try (ResultSet resultSet = getVehicleVersion.executeQuery()) { +                resultSet.next(); +                return Vehicle.builder() +                        .id(vehicleId) +                        .name(resultSet.getString("name")) +                        .constructionType( +                                ConstructionType.valueOf(resultSet.getString("constructionType"))) +                        .type(VehicleType.valueOf(resultSet.getString("type"))) +                        .status(Vehicle.Status.valueOf(status)) +                        .hasNef(resultSet.getBoolean("hasNef")) +                        .registrations(getRegistrations(vehicleId)) +                        .build(); +            } +        } catch (SQLException e) { +            LOG.error( +                    "SQLException occurred while getting VehicleVersion. Error message: {}", +                    e.getMessage()); +            throw new PersistenceException(e); +        } +    } + +    private static String GET_REGISTRATIONS = "SELECT * FROM Registration WHERE id = ? ;"; + +    private final PreparedStatement getRegistrations; + +    private List<Registration> getRegistrations(long vehicleId) throws PersistenceException { +        List<Registration> registrations = new LinkedList<>(); +        try { +            getRegistrations.setLong(1, vehicleId); +            try (ResultSet resultSet = getRegistrations.executeQuery()) { +                while (resultSet.next()) { +                    long registrationId = resultSet.getLong("id"); +                    registrations.add( +                            Registration.builder() +                                    .id(registrationId) +                                    .start(resultSet.getTimestamp("start").toInstant()) +                                    .end(resultSet.getTimestamp("end").toInstant()) +                                    .employee(getEmployee(resultSet.getLong("employeeId"))) +                                    .build()); +                } +            } +        } catch (SQLException e) { +            LOG.error( +                    "SQLException occurred while getting Registration. Error message: {}", +                    e.getMessage()); +            throw new PersistenceException(e); +        } +        return registrations; +    } + +    private static String GET_EMPLOYEE = "SELECT version FROM Employee WHERE id = ? ;"; + +    private final PreparedStatement getEmployee; + +    private Employee getEmployee(long employeeId) throws PersistenceException { +        try { +            getEmployee.setLong(1, employeeId); +            try (ResultSet resultSet = getEmployee.executeQuery()) { +                resultSet.next(); +                return getEmployeeVersion(employeeId, resultSet.getLong("version")); +            } +        } catch (SQLException e) { +            LOG.error( +                    "SQLException occurred while getting Employee. Error message: {}", +                    e.getMessage()); +            throw new PersistenceException(e); +        } +    } + +    private static String GET_EMPLOYEE_VERSION = "SELECT * FROM EmployeeVersion WHERE id = ? ;"; + +    private final PreparedStatement getEmployeeVersion; + +    private Employee getEmployeeVersion(long employeeId, long versionId) +            throws PersistenceException { +        try { +            getEmployeeVersion.setLong(1, versionId); +            try (ResultSet resultSet = getEmployeeVersion.executeQuery()) { +                resultSet.next(); +                return Employee.builder() +                        .id(employeeId) +                        .name(resultSet.getString("name")) +                        .birthday(resultSet.getDate("birthday").toLocalDate()) +                        .educationLevel( +                                EducationLevel.valueOf(resultSet.getString("educationLevel"))) +                        .isDriver(resultSet.getBoolean("isDriver")) +                        .isPilot(resultSet.getBoolean("isPilot")) +                        .build(); +            } +        } catch (SQLException e) { +            LOG.error( +                    "SQLException occurred while getting EmployeeVersion. Error message: {}", +                    e.getMessage()); +            throw new PersistenceException(e); +        }      }      @Override @@ -136,13 +404,6 @@ public class DBOperationDAO implements OperationDAO {              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 { @@ -155,7 +416,6 @@ public class DBOperationDAO implements OperationDAO {                  }              }          } -          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 index 3e4ba12..40a9134 100644 --- 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 @@ -6,13 +6,15 @@ import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundExceptio  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.ArrayList; -import java.util.List; +import java.util.HashSet; +import java.util.Set;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.stereotype.Repository; @@ -29,15 +31,21 @@ public class EmployeeDatabaseDao implements EmployeeDAO {              "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; +    private final PreparedStatement insertEmployeeVersion, +            insertEmployee, +            listEmployee, +            updateEmployee; + +    private final Connection connection;      public EmployeeDatabaseDao(JDBCConnectionManager connectionManager)              throws PersistenceException {          try { -            final var connection = connectionManager.getConnection(); +            connection = connectionManager.getConnection();              insertEmployeeVersion =                      connection.prepareStatement(                              INSERT_EMPLOYEE_VERSION, Statement.RETURN_GENERATED_KEYS); @@ -46,6 +54,8 @@ public class EmployeeDatabaseDao implements EmployeeDAO {              listEmployee = connection.prepareStatement(LIST_EMPLOYEE); +            updateEmployee = connection.prepareStatement(UPDATE_EMPLOYEE); +          } catch (SQLException e) {              throw new PersistenceException(e);          } @@ -55,7 +65,10 @@ public class EmployeeDatabaseDao implements EmployeeDAO {      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())); @@ -72,29 +85,88 @@ public class EmployeeDatabaseDao implements EmployeeDAO {                  ResultSet resultSetEmployee = insertEmployee.getGeneratedKeys();                  if (resultSetEmployee.next()) { +                    connection.commit();                      return resultSetEmployee.getLong(1);                  }              } -            throw new PersistenceException("Employee was not created"); +            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 { -        throw new UnsupportedOperationException(); + +        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(); +            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 List<Employee> list() throws PersistenceException { +    public Set<Employee> list() throws PersistenceException {          try {              ResultSet rs = listEmployee.executeQuery(); -            List<Employee> employees = new ArrayList<>(); +            Set<Employee> employees = new HashSet<>();              while (rs.next()) {                  Employee employee = 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..da90cc8 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,7 @@ 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; +    Set<Operation> list(EnumSet<Status> statuses) throws PersistenceException;      int connectVehicleToOperation(long vehicleID, long operationID) throws PersistenceException;  } 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..13aeffc 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 @@ -10,8 +10,8 @@ import java.sql.ResultSet;  import java.sql.SQLException;  import java.sql.Statement;  import java.sql.Timestamp; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; +import java.util.Set;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; @@ -47,9 +47,9 @@ 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) { 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 index ca1d45c..796dd7b 100644 --- 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 @@ -7,11 +7,13 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Veh  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.util.LinkedList; -import java.util.List; +import java.sql.Statement; +import java.util.HashSet; +import java.util.Set;  import org.springframework.stereotype.Repository;  @Repository @@ -27,121 +29,181 @@ public class VehicleDatabaseDao implements VehicleDAO {          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 { +            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(); -            ResultSet keyResultSet = p1.getGeneratedKeys(); +                p1.executeUpdate(); + +                try (ResultSet keyResultSet = p1.getGeneratedKeys()) { + +                    if (keyResultSet.next()) { +                        id = keyResultSet.getInt(1); +                    } +                } -            if (keyResultSet.next()) { -                id = keyResultSet.getInt(1); +                name = vehicle.type().name() + "-" + id;              } -            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, id); +                p3.executeUpdate(); +            } -        } catch (SQLException e) { -            throw new PersistenceException("SQL Excpetion : " + e.toString()); -        } finally { -            try { -                p1.close(); +            try (PreparedStatement p2 = connection.prepareStatement(query2)) { -            } catch (SQLException e) { -                throw new PersistenceException("SQL Excpetion : " + e.toString()); +                p2.setInt(1, id); +                p2.setString(2, status); +                p2.executeUpdate();              } -        } -        try { -            query1 = "UPDATE VehicleVersion SET name=? WHERE id=?"; -            p3 = jdbcConnectionManager.getConnection().prepareStatement(query1); -            p3.setString(1, name); -            p3.setInt(2, id); -            p3.executeUpdate(); +            connection.commit(); +            connection.setAutoCommit(true);          } catch (SQLException e) { -            throw new PersistenceException("SQL Excpetion : " + e.toString()); -        } finally { -            try { -                p3.close(); -            } catch (SQLException e) { -                throw new PersistenceException("SQL Excpetion : " + e.toString()); -            } +            throw new PersistenceException(e);          } +        return id; +    } + +    @Override +    public void update(Vehicle vehicle) throws ElementNotFoundException, PersistenceException { +        String query = "SELECT id FROM vehicle WHERE version=?"; + +        long vehicleID = -1; +        long vehicleVersion = -1;          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()); +            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(1); +                    } +                } +            } +            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() + "-" + vehicleVersion; + +            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);          } -        return id;      }      @Override -    public void update(Vehicle vehicle) throws ElementNotFoundException, PersistenceException {} +    public Set<Vehicle> list() throws PersistenceException { +        Set<Vehicle> result = new HashSet<>(); -    @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"); +        String sql = +                "Select * from VehicleVersion, Vehicle where VehicleVersion.id=Vehicle.version"; + +        try (PreparedStatement pstmt = +                jdbcConnectionManager.getConnection().prepareStatement(sql)) {              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); +            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); -        } 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 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); +                    ResultSet rs = pstmt.executeQuery()) { +                pstmt.setLong(1, id); + +                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 { +        return Vehicle.builder() +                .id(rs.getLong("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")) +                .build(); +    }  } 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..7d91c88 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 @@ -30,13 +30,14 @@ public abstract class Operation {      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 +54,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..98a2068 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;      /** @@ -56,7 +56,7 @@ public interface OperationService {       * @throws InvalidOperationException if the operationId is invalid or does not exist       * @throws ServiceException if loading the stored vehicles failed       */ -    SortedList<Vehicle> rankVehicles(long operationId) +    SortedSet<Vehicle> rankVehicles(long operationId)              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 ce5613e..74d6457 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,6 +1,7 @@  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; @@ -10,22 +11,35 @@ 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.PersistenceException;  import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.lang.invoke.MethodHandles; +import java.time.Instant;  import java.util.EnumSet; -import java.util.List; -import javafx.collections.transformation.SortedList; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +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 VehicleDAO vehicleDAO; + +    public OperationServiceImpl(OperationDAO operationDAO, VehicleDAO vehicleDAO) { +        this.operationDAO = operationDAO; +        this.vehicleDAO = vehicleDAO;      }      @Override      public long add(Operation operation) throws InvalidOperationException, ServiceException { -        List<Vehicle> vehicles = operation.vehicles(); +        Set<Vehicle> vehicles = operation.vehicles();          boolean rtw = false;          if (faultyInput(operation.opCode())) {              throw new InvalidOperationException("Code ist ungültig!"); @@ -84,7 +98,7 @@ public class OperationServiceImpl implements OperationService {          }          operation = operation.toBuilder().status(Status.ACTIVE).build(); -        long operationId = -1; +        long operationId;          try {              operationId = operationDAO.add(operation);          } catch (PersistenceException e) { @@ -112,8 +126,72 @@ public class OperationServiceImpl implements OperationService {      }      @Override -    public void requestVehicles(long operationId, List<Long> vehicleIds) -            throws InvalidOperationException, InvalidVehicleException, ServiceException {} +    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 is invalid"); +            Operation o = operationDAO.get(operationId); +            validateOperation(o); + +            if (o.status() != Status.ACTIVE) +                throw new InvalidOperationException( +                        "Can't request vehicles for a nonactive operation"); + +            if (!o.status().equals(Status.ACTIVE)) +                throw new InvalidOperationException("Can't add vehicles to a nonactive operation"); + +            for (Long id : vehicleIds) { +                if (id <= 0) throw new InvalidVehicleException("VehicleId is invalid"); + +                try { +                    Vehicle v = vehicleDAO.get(id); +                    if (v.status() == Vehicle.Status.ABGEMELDET) +                        throw new InvalidVehicleException("Can't request nonactive vehicles"); + +                    vs.add(v); +                } catch (ElementNotFoundException e) { +                    throw new InvalidVehicleException("VehicleId does not exist"); +                } +            } + +            vs.addAll(o.vehicles()); +            if (vs.equals(o.vehicles())) return; + +            operationDAO.update(o.toBuilder().vehicles(vs).build()); +        } catch (ElementNotFoundException e) { +            throw new InvalidOperationException("No such operationId exists"); +        } catch (PersistenceException e) { +            throw new ServiceException(e); +        } +    } + +    private static final Pattern opCodePattern = Pattern.compile("(?:\\w{1,3}-\\d{0,2})(.)(?:.*)"); + +    private void validateOperation(Operation o) throws InvalidOperationException { +        if (o.id() <= 0) throw new InvalidOperationException("Id is invalid"); + +        if (o.opCode().trim().isEmpty()) throw new InvalidOperationException("opCode is invalid"); + +        Matcher m = opCodePattern.matcher(o.opCode()); +        if (!m.matches()) throw new InvalidOperationException("opCode is invalid"); + +        if (!m.group(1).equals(o.severity().toString())) +            throw new InvalidOperationException("Severity is invalid"); + +        if (o.vehicles().isEmpty()) +            throw new InvalidOperationException("No vehicles assigned to operation"); + +        Instant created = o.created(); +        if (created == null) throw new InvalidOperationException("Created can't be empty"); + +        if (created.isAfter(Instant.now())) +            throw new InvalidOperationException("Vehicle was created in the future"); + +        if (o.destination().trim().isEmpty()) +            throw new InvalidOperationException("Destination can't be empty"); +    }      @Override      public void complete(long operationId, Status status) @@ -137,13 +215,20 @@ public class OperationServiceImpl implements OperationService {      }      @Override -    public SortedList<Vehicle> rankVehicles(long operationId) +    public SortedSet<Vehicle> rankVehicles(long operationId)              throws InvalidOperationException, ServiceException {          return null;      }      @Override -    public List<Operation> list(EnumSet<Status> statuses) throws ServiceException { -        return null; +    public Set<Operation> list(EnumSet<Status> statuses) throws ServiceException { +        try { +            return operationDAO.list(statuses); +        } catch (PersistenceException e) { +            LOG.debug( +                    "Caught PersistenceException. Throwing ServiceException. Message: {}", +                    e.getMessage()); +            throw new ServiceException(e); +        }      }  } 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..47a2520 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,11 +4,12 @@ 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; @@ -69,17 +70,60 @@ public class VehicleServiceImpl implements VehicleService {      }      public Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException { -        throw new UnsupportedOperationException(); +        switch (vehicle.type()) { +            case RTW: +                if (vehicle.constructionType() == ConstructionType.NORMAL) { +                    throw new InvalidVehicleException("RTW darf kein Normales Dach haben"); +                } else if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { +                    throw new InvalidVehicleException("RTW darf kein Mittelhochdach haben"); +                } +                break; +            case KTW: +                if (vehicle.constructionType() == ConstructionType.NORMAL) { +                    throw new InvalidVehicleException("KTW darf kein Normales Dach haben"); +                } +                break; +            case KTW_B: +                if (vehicle.constructionType() == ConstructionType.NORMAL) { +                    throw new InvalidVehicleException("KTW-B darf kein Normales Dach haben"); +                } +                break; +            case NEF: +                if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { +                    throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben"); +                } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) { +                    throw new InvalidVehicleException("NEF darf kein Hochdach haben"); +                } +                break; +            case NAH: +                if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) { +                    throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben"); +                } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) { +                    throw new InvalidVehicleException("NEF darf kein Hochdach haben"); +                } +                break; +            case BKTW: +                break; +            default: +                throw new ServiceException("not a Valid type"); +        } +        try { +            vehiclePersistence.update(vehicle); +        } catch (ElementNotFoundException e) { +            throw new ServiceException("Element not found"); +        } catch (PersistenceException e) { +            throw new ServiceException(e); +        } +        return vehicle;      }      @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 +133,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/ui/vehiclepane/VehiclePaneController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/ui/vehiclepane/VehiclePaneController.java index 2db6f37..405eee3 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/ui/vehiclepane/VehiclePaneController.java @@ -5,7 +5,6 @@ import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registratio  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,17 +61,17 @@ 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; @@ -80,5 +89,14 @@ 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, shadowed"); +        else rootElement.getStyleClass().add("bg-white, shadowed");      }  } diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/userInterface/ArchiveOperationController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/userInterface/ArchiveOperationController.java new file mode 100644 index 0000000..7b69402 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/userInterface/ArchiveOperationController.java @@ -0,0 +1,127 @@ +package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.userInterface; + +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.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 { + +    public AnchorPane apDetails; +    public Label lblCodeHeader; +    public Hyperlink hypBack; +    public Label lblOpCode; +    public Label lblVehicles; +    public Label lblDate; +    public Label lblAddress; +    public FlowPane fpVehicles; +    private OperationService operationService; +    public FlowPane archiveOperationFlowPane; +    private LinkedList<Operation> list = new LinkedList<>(); + +    public ArchiveOperationController() {} + +    void setServices(OperationService operationService) { +        this.operationService = operationService; +    } + +    void fillList() { +        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() { +        setDetailsVisible(false); +    } +} 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 index ea21691..44e28d8 100644 --- 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 @@ -1,39 +1,46 @@  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.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.OperationServiceImpl;  import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.VehicleService; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.ui.vehiclepane.VehiclePaneController;  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.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.time.temporal.ChronoUnit; +import java.util.ArrayList;  import java.util.EnumSet;  import java.util.LinkedList;  import java.util.List; -import javafx.collections.FXCollections; +import java.util.Set;  import javafx.event.ActionEvent;  import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader;  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.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.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Controller;  @Controller @@ -52,10 +59,11 @@ public class CreateOperationController {      public LinkedList<Vehicle> chosenVehicles = new LinkedList<>();      public AnchorPane apInvisible;      @FXML private OperationDetailsController operationDetailsController; +    public FlowPane fpVehicles; -    // TODO: Anders? -    OperationService operationService = -            new OperationServiceImpl(new DBOperationDAO(new JDBCConnectionManager())); +    private LinkedList<Vehicle> chosenVehicles = new LinkedList<>(); + +    @Autowired private OperationService operationService;      private final VehicleService vehicleService;      private final SpringFXMLLoader fxmlLoader; @@ -67,88 +75,59 @@ public class CreateOperationController {      @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()); -                                } -                            } -                        }); -        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()); -                                } -                            } -                        }); - -        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()); -                        } -                    } -                }); -        lvActiveOperations.setOnMouseClicked( -                event -> { -                    if (event.getClickCount() == 2) { -                        if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { -                            return; -                        } -                        openDetailsWindow(lvActiveOperations.getSelectionModel().getSelectedItem()); -                    } -                });      }      public void updateList() {          try { -            this.lvVehicles.setItems( -                    FXCollections.observableArrayList( -                            vehicleService.list( -                                    EnumSet.of( -                                            Vehicle.Status.FREI_FUNK, Vehicle.Status.FREI_WACHE)))); -        } catch (ServiceException e) { +            fpVehicles.getChildren().clear(); +            Set<Vehicle> vehicles = vehicleService.list(EnumSet.allOf(Vehicle.Status.class)); + +            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 e) { +            LOG.error("Error while updating list.", e); +              Alert alert = new Alert(Alert.AlertType.ERROR);              alert.setTitle("Fehler");              alert.setHeaderText("Fehler!"); @@ -168,30 +147,72 @@ public class CreateOperationController {          }      } -    /*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; -    }*/ +    private static 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()); +                        } 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).build()); +                    } 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() { @@ -206,7 +227,7 @@ public class CreateOperationController {                          .created(Instant.now())                          .opCode(txtCode.getText())                          .status(Status.ACTIVE) -                        .vehicles(List.of(vehicles)) +                        .vehicles(Set.of(vehicles))                          .severity(Severity.A)                          .build();          try { @@ -232,13 +253,36 @@ public class CreateOperationController {      }      public void onEmployeeLinkClicked(ActionEvent actionEvent) { -        openNewWindow("createNewEmployee.fxml"); +        openNewWindow("listEmployees.fxml");      }      public void onVehicleLinkClicked(ActionEvent actionEvent) {          openNewWindow("createCar.fxml");      } +    public void onArchivLinkClicked() { +        openNewArchivWindow(); +    } + +    private void openNewArchivWindow() { +        Stage stage = new Stage(); +        try { +            FXMLLoader fxmlLoader = +                    new FXMLLoader(getClass().getResource("/fxml/ArchiveOperation.fxml")); +            Parent node = fxmlLoader.load(); +            ArchiveOperationController archiveOperationController = fxmlLoader.getController(); +            archiveOperationController.setServices(operationService); +            archiveOperationController.fillList(); +            stage.setScene(new Scene(node)); +        } 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(); @@ -261,13 +305,13 @@ public class CreateOperationController {          updateList();      } +    public void setVisible(boolean b) { +        apInvisible.setVisible(!b); +    } +      private void openDetailsWindow(Operation operation) {          operationDetailsController.setControllers(this, operationService, vehicleService);          apInvisible.setVisible(true);          operationDetailsController.initOperation(operation);      } - -    void setVisible(boolean b) { -        apInvisible.setVisible(!b); -    }  }  | 
