summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java202
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDao.java36
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAO.java106
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java194
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java7
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationService.java7
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImpl.java45
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java29
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/util/JDBCConnectionManager.java11
-rw-r--r--src/main/resources/fxml/RegistrationWindow.fxml76
-rw-r--r--src/main/resources/sql/H2RegistrationDAOTest_depopulate.sql5
-rw-r--r--src/main/resources/sql/H2RegistrationDAOTest_populate.sql10
-rw-r--r--src/main/resources/sql/database.sql17
-rw-r--r--src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowApplication.java53
-rw-r--r--src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAOTest.java162
-rw-r--r--src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImplTest.java122
-rw-r--r--src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeePersistenceTest.java155
-rw-r--r--src/test/resources/employeeServiceTestData.xml12
18 files changed, 1229 insertions, 20 deletions
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
new file mode 100644
index 0000000..0683c77
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowController.java
@@ -0,0 +1,202 @@
+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.dto.Registration;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.RegistrationService;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.VehicleService;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.util.EnumSet;
+import java.util.LinkedList;
+import java.util.List;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import javafx.fxml.FXML;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Alert.AlertType;
+import javafx.scene.control.ChoiceBox;
+import javafx.scene.control.Label;
+import javafx.scene.control.TableColumn;
+import javafx.scene.control.TableView;
+import javafx.scene.control.TextField;
+import javafx.stage.Stage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+@Controller
+public class RegistrationWindowController {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RegistrationWindowController.class);
+
+ private EmployeeService employeeService;
+
+ private VehicleService vehicleService;
+
+ private RegistrationService registrationService;
+
+ @Autowired
+ public void setEmployeeService(EmployeeService employeeService) {
+ this.employeeService = employeeService;
+ }
+
+ @Autowired
+ public void setVehicleService(VehicleService vehicleService) {
+ this.vehicleService = vehicleService;
+ }
+
+ @Autowired
+ public void setRegistrationService(RegistrationService registrationService) {
+ this.registrationService = registrationService;
+ }
+
+ @FXML public ChoiceBox<Integer> cbStart;
+ @FXML public ChoiceBox<Integer> cbEnd;
+ @FXML public Label lVehicles;
+ @FXML public Label lEmployees;
+ @FXML public TextField tfVehicleSearch;
+ @FXML public TextField tfEmployeeSearch;
+ @FXML public TableView<Vehicle> tvVehicles;
+ @FXML public TableView<Employee> tvEmployees;
+ @FXML public TableColumn<Vehicle, String> tcVehicles;
+ @FXML public TableColumn<Employee, String> tcEmployees;
+
+ private Vehicle chosenVehicle;
+ private List<Employee> chosenEmployees = new LinkedList<>();
+
+ @FXML
+ public void initialize() {
+ // will have to be replaced for FlowPane
+ try {
+ List<Vehicle> vehicles = vehicleService.list(EnumSet.of(Status.ABGEMELDET));
+ tcVehicles.setCellValueFactory(x -> new SimpleStringProperty(x.getValue().name()));
+ tvVehicles.setItems(FXCollections.observableArrayList(vehicles));
+ } catch (ServiceException e) {
+ LOG.warn(
+ "Caught ServiceException while getting vehicles. Showing it to user. Error message: {}",
+ e.getMessage());
+ Alert alert = new Alert(AlertType.ERROR);
+ alert.setTitle("Fahrzeuge - Fehler!");
+ alert.setHeaderText("Beim Auflisten der Fahrzeug ist ein Fehler aufgetreten.");
+ alert.setContentText(e.getMessage());
+ alert.show();
+ }
+ try {
+ List<Employee> employees = employeeService.list();
+ tcEmployees.setCellValueFactory(x -> new SimpleStringProperty(x.getValue().name()));
+ tvEmployees.setItems(FXCollections.observableArrayList(employees));
+ } catch (ServiceException e) {
+ LOG.warn(
+ "Caught ServiceException while getting employees. Showing it to user. Error message: {}",
+ e.getMessage());
+ Alert alert = new Alert(AlertType.ERROR);
+ alert.setTitle("Personal - Fehler!");
+ alert.setHeaderText("Beim Auflisten des Personals ist ein Fehler aufgetreten.");
+ alert.setContentText(e.getMessage());
+ alert.show();
+ }
+ tvVehicles.setOnMousePressed(
+ mouseEvent -> {
+ if (mouseEvent.isPrimaryButtonDown() && mouseEvent.getClickCount() == 2) {
+ chosenVehicle = tvVehicles.getSelectionModel().getSelectedItem();
+ if (chosenVehicle == null) {
+ return;
+ }
+ lVehicles.setText(chosenVehicle.name());
+ }
+ });
+ tvEmployees.setOnMousePressed(
+ mouseEvent -> {
+ if (mouseEvent.isPrimaryButtonDown() && mouseEvent.getClickCount() == 2) {
+ chosenEmployees.add(tvEmployees.getSelectionModel().getSelectedItem());
+ if (chosenEmployees == null) {
+ return;
+ }
+ StringBuilder text = new StringBuilder();
+ for (Employee employee : chosenEmployees) {
+ text.append(employee.name()).append("\n");
+ }
+ lEmployees.setText(text.toString());
+ }
+ });
+ ObservableList<Integer> hours =
+ FXCollections.observableArrayList(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23);
+ cbStart.setItems(hours);
+ cbEnd.setItems(hours);
+ }
+
+ public void cancel() {
+ LOG.debug("Cancel Button clicked");
+ ((Stage) lVehicles.getScene().getWindow()).close();
+ }
+
+ public void create() {
+ LOG.debug("Create Button clicked");
+
+ List<Registration> registrations = new LinkedList<>();
+
+ for (Employee employee : chosenEmployees) {
+ registrations.add(
+ Registration.builder()
+ .id(chosenVehicle.id())
+ .employee(employee)
+ .start(
+ LocalDateTime.of(
+ LocalDate.now(),
+ LocalTime.of(cbStart.getValue(), 0))
+ .toInstant(OffsetDateTime.now().getOffset()))
+ .end(
+ LocalDateTime.of(
+ LocalDate.now(),
+ LocalTime.of(cbEnd.getValue(), 0))
+ .toInstant(OffsetDateTime.now().getOffset()))
+ .build());
+ }
+ try {
+ registrationService.add(chosenVehicle, registrations);
+ ((Stage) lVehicles.getScene().getWindow()).close();
+ } catch (InvalidVehicleException e) {
+ // NOT THROWN ANYWHERE RIGHT NOW
+ LOG.info(
+ "Caught InvalidVehicleException. Showing it to user. Error message: {}",
+ e.getClass().toString(),
+ e.getMessage());
+ Alert alert = new Alert(AlertType.WARNING);
+ alert.setTitle("Ungültiges Fahrzeug");
+ alert.setHeaderText("Das spezifizierte Fahrzeug ist nicht gültig.");
+ alert.setContentText(e.getMessage());
+ alert.show();
+ } catch (ServiceException e) {
+ LOG.warn(
+ "Caught ServiceException while getting vehicles. Showing it to user. Error message: {}",
+ e.getMessage());
+ Alert alert = new Alert(AlertType.ERROR);
+ alert.setTitle("Anmeldung - Fehler!");
+ alert.setHeaderText("Beim Erstellen der Anmeldung ist ein Fehler aufgetreten.");
+ alert.setContentText(e.getMessage());
+ alert.show();
+ } catch (InvalidRegistrationException e) {
+ LOG.info(
+ "Caught InvalidRegistrationException. Showing it to user. Error message: {}",
+ e.getMessage());
+ Alert alert = new Alert(AlertType.WARNING);
+ alert.setTitle("Ungültige Eingabe");
+ alert.setHeaderText(
+ "Die gewählte Kombination von Fahrzeug und Personal ist nicht gültig!");
+ alert.setContentText(e.getMessage());
+ alert.show();
+ }
+ }
+}
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 900fd0e..3e4ba12 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
@@ -1,6 +1,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.einsatzverwaltung.dto.Employee.EducationLevel;
import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException;
import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException;
import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager;
@@ -10,6 +11,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
+import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -23,8 +25,12 @@ public class EmployeeDatabaseDao implements EmployeeDAO {
"INSERT INTO EmployeeVersion(name, birthday, educationLevel, isDriver, isPilot) "
+ "VALUES(?, ?, ?, ?, ?)";
private static final String INSERT_EMPLOYEE = "INSERT INTO Employee(version) VALUES(?)";
+ private static final String LIST_EMPLOYEE =
+ "SELECT emp.id, v.name, v.birthday, v.educationLevel, v.isDriver, v.isPilot "
+ + "FROM employee emp "
+ + "JOIN EmployeeVersion v ON v.id = emp.version";
- private final PreparedStatement insertEmployeeVersion, insertEmployee;
+ private final PreparedStatement insertEmployeeVersion, insertEmployee, listEmployee;
public EmployeeDatabaseDao(JDBCConnectionManager connectionManager)
throws PersistenceException {
@@ -38,6 +44,8 @@ public class EmployeeDatabaseDao implements EmployeeDAO {
insertEmployee =
connection.prepareStatement(INSERT_EMPLOYEE, Statement.RETURN_GENERATED_KEYS);
+ listEmployee = connection.prepareStatement(LIST_EMPLOYEE);
+
} catch (SQLException e) {
throw new PersistenceException(e);
}
@@ -82,7 +90,31 @@ public class EmployeeDatabaseDao implements EmployeeDAO {
@Override
public List<Employee> list() throws PersistenceException {
- throw new UnsupportedOperationException();
+
+ try {
+ ResultSet rs = listEmployee.executeQuery();
+
+ List<Employee> employees = new ArrayList<>();
+ while (rs.next()) {
+
+ Employee employee =
+ Employee.builder()
+ .id(rs.getLong(1))
+ .name(rs.getString(2))
+ .birthday(rs.getTimestamp(3).toLocalDateTime().toLocalDate())
+ .educationLevel(EducationLevel.valueOf(rs.getString(4)))
+ .isDriver(rs.getBoolean(5))
+ .isPilot(rs.getBoolean(6))
+ .build();
+
+ employees.add(employee);
+ }
+
+ return employees;
+
+ } catch (SQLException e) {
+ throw new PersistenceException(e);
+ }
}
@Override
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
new file mode 100644
index 0000000..e4bc0ab
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAO.java
@@ -0,0 +1,106 @@
+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 at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.LinkedList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class RegistrationDatabaseDAO implements RegistrationDAO {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RegistrationDatabaseDAO.class);
+
+ private static final String ADD_REGISTRATION =
+ "INSERT INTO Registration (vehicleId, employeeId, start, end, active) VALUES (?,?,?,?,?);";
+ private static final String UPDATE_VEHICLE =
+ "UPDATE Vehicle SET status = 'frei_wache' WHERE id = ?;";
+
+ private PreparedStatement addRegistration;
+ private PreparedStatement updateVehicle;
+
+ private Connection connection;
+
+ @Autowired
+ public RegistrationDatabaseDAO(JDBCConnectionManager connectionManager)
+ throws PersistenceException {
+ try {
+ connection = connectionManager.getConnection();
+ addRegistration =
+ connection.prepareStatement(ADD_REGISTRATION, Statement.RETURN_GENERATED_KEYS);
+ updateVehicle = connection.prepareStatement(UPDATE_VEHICLE);
+ } catch (SQLException e) {
+ LOG.error("Could not get connection or preparation of statement failed");
+ throw new PersistenceException(e);
+ }
+ }
+
+ @Override
+ public List<Long> add(long vehicleId, List<Registration> registrations)
+ throws PersistenceException {
+ List<Long> returnValues = new LinkedList<>();
+ try {
+ connection.setAutoCommit(false);
+ for (Registration registration : registrations) {
+ addRegistration.setLong(1, vehicleId);
+ addRegistration.setLong(2, registration.employee().id());
+ addRegistration.setTimestamp(3, Timestamp.from(registration.start()));
+ addRegistration.setObject(4, registration.end());
+ addRegistration.setBoolean(
+ 5, true); // ASSUMPTION: Registration gets created as active
+ addRegistration.executeUpdate();
+ try (ResultSet rs = addRegistration.getGeneratedKeys()) {
+ if (rs.next()) {
+ returnValues.add(rs.getLong(1));
+ } else {
+ LOG.error("No ResultSet was created while adding registration");
+ throw new PersistenceException(
+ "Anmeldung konnte nicht gespeichert werden.");
+ }
+ }
+ }
+
+ updateVehicle.setLong(1, vehicleId);
+ updateVehicle.executeUpdate();
+
+ connection.commit();
+ return returnValues;
+ } catch (SQLException e) {
+ LOG.error(
+ "An SQLException occurred while trying to save registrations to database. "
+ + "Attempting a rollback. Error message: {}",
+ e.getMessage());
+ try {
+ connection.rollback();
+ } catch (SQLException e1) {
+ LOG.error("Rollback failed :(");
+ }
+ throw new PersistenceException(e);
+ } finally {
+ try {
+ connection.setAutoCommit(true);
+ } catch (SQLException e) {
+ LOG.error(
+ "Setting back AutoCommit to false failed! Error message: {}",
+ e.getMessage());
+ // SonarLint insists on me not throwing anything here...
+ }
+ }
+ }
+
+ @Override
+ public void remove(long id) throws ElementNotFoundException, PersistenceException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java
new file mode 100644
index 0000000..295b615
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/RegistrationValidator.java
@@ -0,0 +1,194 @@
+package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto;
+
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.VehicleType;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RegistrationValidator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RegistrationValidator.class);
+
+ private RegistrationValidator() {}
+
+ public static void validate(Vehicle vehicle, List<Registration> registrations)
+ throws InvalidVehicleException, InvalidRegistrationException {
+ /*
+ Vehicles and Employees are assumed to be valid.
+ They have been checked at creation, and for them to be checked again, access to
+ VehicleValidator and EmployeeValidator are needed, which are not available at this time.
+ */
+ /*
+ The method used here goes as follows: All given employees are inspected in regards to their
+ qualifications, and added to the appropriate lists of the roles they could fill.
+ For example, an NFS, who is also a driver, would be added to the lists driverIds, nfsIds
+ and rsIds (because an NFS can always substitute an RS).
+ Afterwards, the number of people is checked according to the chosen vehicle type, and if
+ the number is okay, the program tries to find a valid combination of roles for the vehicle.
+ For example, for an RTW, first a driver is chosen, their ID marked as found in the aptly
+ titled HashMap, and then for the second RS, the list of RS is checked, excluding the chosen
+ driver. If no other valid RS is found, the next possible driver is chosen, and so on. If no
+ valid combination is found, an InvalidRegistrationException is thrown.
+ */
+ List<Long> pilotIds = new LinkedList<>();
+ List<Long> driverIds = new LinkedList<>();
+ List<Long> naIds = new LinkedList<>();
+ List<Long> nfsIds = new LinkedList<>();
+ List<Long> rsIds = new LinkedList<>();
+ HashMap<Long, Boolean> found =
+ new HashMap<>(); // needed later in DFS, checks that no person is chosen twice
+ int total = 0;
+ for (Registration registration : registrations) {
+ total++;
+ if (found.put(registration.employee().id(), false) != null) {
+ LOG.info("Employee with ID {} was added twice", registration.employee().id());
+ throw new InvalidRegistrationException(
+ "Person with the ID: "
+ + registration.employee().id()
+ + " was added more than once!");
+ }
+ if (registration.employee().isPilot()) {
+ pilotIds.add(registration.employee().id());
+ }
+ if (registration.employee().isDriver()) {
+ driverIds.add(registration.employee().id());
+ }
+ if (registration.employee().educationLevel() == EducationLevel.NA) {
+ naIds.add(registration.employee().id());
+ nfsIds.add(registration.employee().id());
+ rsIds.add(registration.employee().id());
+ } else if (isNFS(registration.employee())) {
+ nfsIds.add(registration.employee().id());
+ rsIds.add(registration.employee().id());
+ } else { // only RS left
+ rsIds.add(registration.employee().id());
+ }
+ }
+ if (total <= 0) {
+ LOG.info("No employees were added");
+ throw new InvalidRegistrationException("Kein Personal ausgewählt!");
+ }
+ if (vehicle.type() == VehicleType.NAH) {
+ /*
+ NAH
+ 1 Pilot
+ 1 NFS
+ 1 NA
+ 3-4 Personen
+ */
+ if (total < 3) {
+ LOG.info("Too few employees for NAH");
+ throw new InvalidRegistrationException("Zu wenig Personal für NAH!");
+ } else if (total > 4) {
+ LOG.info("Too many employees for NAH");
+ throw new InvalidRegistrationException("Zu viel Personal für NAH!");
+ }
+ for (long pilot_id : pilotIds) {
+ found.put(pilot_id, true);
+ for (long na_id : naIds) {
+ if (found.get(na_id)) continue;
+ found.put(na_id, true);
+ for (long nfs_id : nfsIds) {
+ if (found.get(nfs_id)) continue;
+ LOG.info("Valid combination found for NAH");
+ return;
+ }
+ found.put(na_id, false);
+ }
+ found.put(pilot_id, false);
+ }
+ LOG.info("No valid combination of employees found for NAH");
+ throw new InvalidRegistrationException(
+ "Keine gültige Kombination von Personen für NAH!");
+ } else if (vehicle.type() == VehicleType.NEF) {
+ /*
+ NEF
+ 1 Driver (has to be NFS)
+ 1 NA
+ */
+ if (total < 2) {
+ LOG.info("Too few employees for NEF");
+ throw new InvalidRegistrationException("Zu wenig Personal für NEF!");
+ } else if (total > 3) {
+ LOG.info("Too many employees for NEF");
+ throw new InvalidRegistrationException("Zu viel Personal für NEF!");
+ }
+ for (long driver_id : driverIds) {
+ if (!nfsIds.contains(driver_id))
+ continue; // if possible driver is not NFS, skip him
+ found.put(driver_id, true);
+ for (long na_id : naIds) {
+ if (found.get(na_id)) continue;
+ LOG.info("Valid combinaion found for NEF");
+ return;
+ }
+ found.put(driver_id, false);
+ }
+ LOG.info("No valid combination of employees found for NEF");
+ throw new InvalidRegistrationException(
+ "Keine gültige Kombination von Personen für NEF!");
+ } else if (vehicle.type() == VehicleType.BKTW) {
+ /*
+ BKTW
+ 1 Driver
+ */
+ if (total > 3) {
+ LOG.info("Too many employees for BKTW");
+ throw new InvalidRegistrationException("Zu viel Personal für BKTW!");
+ }
+ if (!driverIds.isEmpty()) {
+ LOG.info("Valid combination found for BKTW");
+ return;
+ }
+ LOG.info("No driver was found for BKTW");
+ throw new InvalidRegistrationException("Kein Fahrer gefunden für BKTW!");
+ } else { // KTW or RTW, both have the same requirements
+ /*
+ RTW/KTW
+ 1 Driver
+ 1 RS
+ */
+ if (total < 2) {
+ LOG.info("Too few employees for {}", vehicle.type().name());
+ throw new InvalidRegistrationException(
+ "Zu wenig Personal für " + vehicle.type().name() + "!");
+ } else if (total > 4) {
+ LOG.info("Too many employees for {}", vehicle.type().name());
+ throw new InvalidRegistrationException(
+ "Zu viel Persoanl für " + vehicle.type().name() + "!");
+ }
+ for (long driver_id : driverIds) { // driver includes rs
+ found.put(driver_id, true);
+ for (long rs_id : rsIds) {
+ if (found.get(rs_id)) continue;
+ LOG.info("Valid combination found for {}", vehicle.type().name());
+ return;
+ }
+ }
+ LOG.info("No valid combination of employees found for {}", vehicle.type().name());
+ throw new InvalidRegistrationException(
+ "Keine gültige Kombination von Personen für " + vehicle.type().name() + "!");
+ }
+ }
+
+ private static boolean isNFS(Employee employee) {
+ EducationLevel educationLevel = employee.educationLevel();
+ switch (educationLevel) {
+ case NFS:
+ return true;
+ case NKA:
+ return true;
+ case NKI:
+ return true;
+ case NKV:
+ return true;
+ default:
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java
index 144ccc6..ed0fb1c 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
@@ -36,7 +36,12 @@ public class EmployeeServiceImpl implements EmployeeService {
@Override
public List<Employee> list() throws ServiceException {
- return null;
+
+ try {
+ return employeePersistence.list();
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
}
@Override
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 801148c..c20ed3c 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
@@ -1,6 +1,7 @@
package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service;
import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle;
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;
@@ -11,14 +12,14 @@ public interface RegistrationService {
/**
* Register employee to a vehicle.
*
- * @param vehicleId the id of the target vehicle
+ * @param vehicle the target vehicle
* @param registrations that should be added to the vehicle
- * @return a list of the ids that were assigned
+ * @return the id that was assigned
* @throws InvalidVehicleException if the vehicleId is invalid or does not exist
* @throws InvalidRegistrationException if the registration is invalid
* @throws ServiceException if the registration could not be persisted
*/
- List<Long> add(long vehicleId, List<Registration> registrations)
+ List<Long> add(Vehicle vehicle, List<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
new file mode 100644
index 0000000..b0605f0
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImpl.java
@@ -0,0 +1,45 @@
+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.dto.Registration;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.RegistrationValidator;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.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.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RegistrationServiceImpl implements RegistrationService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RegistrationServiceImpl.class);
+
+ private final RegistrationDAO registrationDAO;
+
+ @Autowired
+ public RegistrationServiceImpl(RegistrationDAO registrationDAO) {
+ this.registrationDAO = registrationDAO;
+ }
+
+ @Override
+ public List<Long> add(Vehicle vehicle, List<Registration> registrations)
+ throws InvalidVehicleException, InvalidRegistrationException, ServiceException {
+ RegistrationValidator.validate(vehicle, registrations);
+ try {
+ return registrationDAO.add(vehicle.id(), registrations);
+ } catch (PersistenceException e) {
+ LOG.warn("PersistenceException caught, throwing matching ServiceException");
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public void remove(long registrationId) throws InvalidRegistrationException, ServiceException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/VehicleServiceImpl.java
index 4a11298..bbe668b 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
@@ -9,14 +9,16 @@ 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.stream.Collectors;
import org.springframework.stereotype.Service;
@Service
public class VehicleServiceImpl implements VehicleService {
- private VehicleDAO vehicleDAO;
- public VehicleServiceImpl(VehicleDAO vehicleDAO) {
- this.vehicleDAO = vehicleDAO;
+ private VehicleDAO vehiclePersistence;
+
+ public VehicleServiceImpl(VehicleDAO vehiclePersistence) {
+ this.vehiclePersistence = vehiclePersistence;
}
public long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException {
@@ -59,7 +61,7 @@ public class VehicleServiceImpl implements VehicleService {
throw new ServiceException("not a Valid type");
}
try {
- vehicleDAO.add(vehicle);
+ vehiclePersistence.add(vehicle);
} catch (PersistenceException e) {
throw new ServiceException(e);
}
@@ -70,10 +72,27 @@ public class VehicleServiceImpl implements VehicleService {
throw new UnsupportedOperationException();
}
+ @Override
public List<Vehicle> list(EnumSet<Status> statuses) throws ServiceException {
- throw new UnsupportedOperationException();
+
+ if (statuses == null) {
+ throw new ServiceException("statuses may not be null");
+ }
+
+ List<Vehicle> vehicles;
+
+ try {
+ vehicles = vehiclePersistence.list();
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+
+ return vehicles.stream()
+ .filter(vehicle -> statuses.contains(vehicle.status()))
+ .collect(Collectors.toList());
}
+ @Override
public void remove(long id) throws InvalidVehicleException, ServiceException {
throw new UnsupportedOperationException();
}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/util/JDBCConnectionManager.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/util/JDBCConnectionManager.java
index 5494471..6eb15ec 100644
--- a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/util/JDBCConnectionManager.java
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/util/JDBCConnectionManager.java
@@ -12,12 +12,17 @@ import org.springframework.stereotype.Component;
public class JDBCConnectionManager {
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private static final String CONNECTION_URL =
+ private static final String DEFAULT_CONNECTION_URL =
"jdbc:h2:~/sepm;INIT=RUNSCRIPT FROM 'classpath:sql/database.sql'";
-
+ private String connectionUrl;
private Connection connection;
public JDBCConnectionManager() {
+ this(DEFAULT_CONNECTION_URL);
+ }
+
+ public JDBCConnectionManager(String connectionUrl) {
+ this.connectionUrl = connectionUrl;
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
@@ -27,7 +32,7 @@ public class JDBCConnectionManager {
}
public Connection getConnection() throws SQLException {
- if (connection == null) connection = DriverManager.getConnection(CONNECTION_URL);
+ if (connection == null) connection = DriverManager.getConnection(connectionUrl);
return connection;
}
diff --git a/src/main/resources/fxml/RegistrationWindow.fxml b/src/main/resources/fxml/RegistrationWindow.fxml
new file mode 100644
index 0000000..0394ca7
--- /dev/null
+++ b/src/main/resources/fxml/RegistrationWindow.fxml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.control.ChoiceBox?>
+<?import javafx.scene.control.Label?>
+<?import javafx.scene.control.SplitPane?>
+<?import javafx.scene.control.TableColumn?>
+<?import javafx.scene.control.TableView?>
+<?import javafx.scene.control.TextField?>
+<?import javafx.scene.layout.AnchorPane?>
+<?import javafx.scene.layout.HBox?>
+<?import javafx.scene.layout.VBox?>
+
+<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.RegistrationWindowController">
+ <children>
+ <AnchorPane prefHeight="135.0" prefWidth="600.0">
+ <children>
+ <Label layoutX="14.0" layoutY="14.0" text="Neue Anmeldung" />
+ <Label layoutX="14.0" layoutY="44.0" text="von" />
+ <Label layoutX="133.0" layoutY="44.0" text="bis" />
+ <ChoiceBox fx:id="cbStart" layoutX="42.0" layoutY="40.0" prefWidth="80.0" />
+ <ChoiceBox fx:id="cbEnd" layoutX="159.0" layoutY="40.0" prefWidth="80.0" />
+ <Label layoutX="10.0" layoutY="82.0" text="Fahrzeug" />
+ <Label fx:id="lVehicles" layoutX="10.0" layoutY="108.0" text="Fahrzeugname" />
+ <Label layoutX="216.0" layoutY="82.0" text="Personen" />
+ <Label fx:id="lEmployees" layoutX="216.0" layoutY="108.0" text="Namen" />
+ </children>
+ </AnchorPane>
+ <SplitPane dividerPositions="0.35" prefWidth="200.0">
+ <items>
+ <VBox prefHeight="200.0" prefWidth="100.0">
+ <children>
+ <Label text="Fahrzeugsuche" />
+ <TextField fx:id="tfVehicleSearch" />
+ <TableView fx:id="tvVehicles" prefHeight="200.0" prefWidth="200.0">
+ <columns>
+ <TableColumn fx:id="tcVehicles" prefWidth="75.0" text="Fahrzeuge" />
+ </columns>
+ <columnResizePolicy>
+ <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
+ </columnResizePolicy>
+ </TableView>
+ </children>
+ </VBox>
+ <VBox prefHeight="200.0" prefWidth="100.0">
+ <children>
+ <Label text="Personensuche" />
+ <TextField fx:id="tfEmployeeSearch" />
+ <TableView fx:id="tvEmployees" prefHeight="200.0" prefWidth="200.0">
+ <columns>
+ <TableColumn fx:id="tcEmployees" prefWidth="75.0" text="Personen" />
+ </columns>
+ <columnResizePolicy>
+ <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
+ </columnResizePolicy>
+ </TableView>
+ </children>
+ </VBox>
+ </items>
+ </SplitPane>
+ <HBox alignment="CENTER" prefWidth="200.0">
+ <children>
+ <Button mnemonicParsing="false" onAction="#cancel" text="Abbrechen">
+ <HBox.margin>
+ <Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
+ </HBox.margin>
+ </Button>
+ <Button mnemonicParsing="false" onAction="#create" text="Erstellen">
+ <HBox.margin>
+ <Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
+ </HBox.margin>
+ </Button>
+ </children></HBox>
+ </children>
+</VBox>
diff --git a/src/main/resources/sql/H2RegistrationDAOTest_depopulate.sql b/src/main/resources/sql/H2RegistrationDAOTest_depopulate.sql
new file mode 100644
index 0000000..f43b641
--- /dev/null
+++ b/src/main/resources/sql/H2RegistrationDAOTest_depopulate.sql
@@ -0,0 +1,5 @@
+DELETE FROM Registration;
+DELETE FROM Vehicle;
+DELETE FROM VehicleVersion;
+DELETE FROM Employee;
+DELETE FROM EmployeeVersion; \ No newline at end of file
diff --git a/src/main/resources/sql/H2RegistrationDAOTest_populate.sql b/src/main/resources/sql/H2RegistrationDAOTest_populate.sql
new file mode 100644
index 0000000..b81eb78
--- /dev/null
+++ b/src/main/resources/sql/H2RegistrationDAOTest_populate.sql
@@ -0,0 +1,10 @@
+INSERT INTO EmployeeVersion (id, name, birthday, educationLevel, isDriver, isPilot) VALUES (1, 'John Doe', '2000-01-01', 'RS', TRUE, TRUE);
+INSERT INTO EmployeeVersion (id, name, birthday, educationLevel, isDriver, isPilot) VALUES (2, 'Nick "Kage" Verily', '1990-01-01', 'NKV', TRUE, FALSE);
+INSERT INTO EmployeeVersion (id, name, birthday, educationLevel, isDriver, isPilot) VALUES (3, 'Nicht Arzt', '1980-01-01', 'NA', FALSE, FALSE);
+INSERT INTO Employee (id, version) VALUES (1, 1);
+INSERT INTO Employee (id, version) VALUES (2, 2);
+INSERT INTO Employee (id, version) VALUES (3, 3);
+INSERT INTO VehicleVersion (id, name, hasNef, constructionType, type) VALUES (1, 'RTW-1', TRUE, 'Hochdach', 'RTW');
+INSERT INTO VehicleVersion (id, name, hasNef, constructionType, type) VALUES (2, 'NEF-1', FALSE, 'Normal', 'NEF');
+INSERT INTO Vehicle (id, version, status) VALUES (1, 1, 'abgemeldet');
+INSERT INTO Vehicle (id, version, status) VALUES (2, 2, 'abgemeldet'); \ No newline at end of file
diff --git a/src/main/resources/sql/database.sql b/src/main/resources/sql/database.sql
index bb23c91..e775550 100644
--- a/src/main/resources/sql/database.sql
+++ b/src/main/resources/sql/database.sql
@@ -1,26 +1,30 @@
CREATE TABLE IF NOT EXISTS VehicleVersion (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
- constructionType ENUM('Normal', 'Hochdach', 'Mittelhochdach') NOT NULL,
- type ENUM('BKTW', 'KTW-B', 'KTW', 'RTW', 'NEF', 'NAH') NOT NULL,
+ constructionType VARCHAR NOT NULL,
+ type VARCHAR NOT NULL,
hasNef BOOLEAN NOT NULL,
+ CHECK constructionType IN ('Normal', 'Hochdach', 'Mittelhochdach'),
+ CHECK type IN ('BKTW', 'KTW-B', 'KTW', 'RTW', 'NEF', 'NAH')
);
CREATE TABLE IF NOT EXISTS Vehicle (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
version BIGINT NOT NULL,
- status ENUM('abgemeldet', 'frei_wache', 'zum_berufungsort', 'am_berufungsort', 'zum_zielort',
- 'am_zielort', 'frei_funk', 'deleted') NOT NULL,
+ status VARCHAR NOT NULL,
FOREIGN KEY (version) REFERENCES VehicleVersion(id),
+ CHECK status IN ('abgemeldet', 'frei_wache', 'zum_berufungsort', 'am_berufungsort', 'zum_zielort',
+ 'am_zielort', 'frei_funk', 'deleted')
);
CREATE TABLE IF NOT EXISTS EmployeeVersion (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
birthday DATE NOT NULL,
- educationLevel ENUM('RS', 'NFS', 'NKV', 'NKA', 'NKI', 'NA') NOT NULL,
+ educationLevel VARCHAR NOT NULL,
isDriver BOOLEAN NOT NULL,
isPilot BOOLEAN NOT NULL,
+ CHECK educationLevel IN ('RS', 'NFS', 'NKV', 'NKA', 'NKI', 'NA')
);
CREATE TABLE IF NOT EXISTS Employee (
@@ -43,10 +47,11 @@ CREATE TABLE IF NOT EXISTS Registration (
CREATE TABLE IF NOT EXISTS Operation (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
opCode VARCHAR(20) NOT NULL,
- severity ENUM('A', 'B', 'C', 'D', 'E', 'O') NOT NULL,
+ severity VARCHAR NOT NULL,
created TIMESTAMP NOT NULL,
destination VARCHAR(100) NOT NULL,
additionalInfo VARCHAR(100),
+ CHECK severity IN ('A', 'B', 'C', 'D', 'E', 'O')
);
CREATE TABLE IF NOT EXISTS VehicleOperation (
diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowApplication.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowApplication.java
new file mode 100644
index 0000000..3293ae9
--- /dev/null
+++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/RegistrationWindowApplication.java
@@ -0,0 +1,53 @@
+package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller;
+
+import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader;
+import java.lang.invoke.MethodHandles;
+import javafx.application.Application;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.stereotype.Component;
+
+@Component
+@ComponentScan("at.ac.tuwien.sepm.assignment.groupphase")
+public class RegistrationWindowApplication extends Application {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ public static AnnotationConfigApplicationContext context;
+
+ @Override
+ public void start(Stage primaryStage) throws Exception {
+ // setup application
+ primaryStage.setTitle("Person anlegen");
+ // primaryStage.setWidth(1366);
+ // primaryStage.setHeight(768);
+ primaryStage.centerOnScreen();
+ primaryStage.setOnCloseRequest(event -> LOG.debug("Application shutdown initiated"));
+
+ context = new AnnotationConfigApplicationContext(RegistrationWindowApplication.class);
+ final var fxmlLoader = context.getBean(SpringFXMLLoader.class);
+ primaryStage.setScene(
+ new Scene(
+ (Parent)
+ fxmlLoader.load(
+ getClass()
+ .getResourceAsStream(
+ "/fxml/RegistrationWindow.fxml"))));
+
+ // show application
+ primaryStage.show();
+ primaryStage.toFront();
+ LOG.debug("Application startup complete");
+ }
+
+ @Override
+ public void stop() {
+ LOG.debug("Stopping application");
+ context.close();
+ }
+}
diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAOTest.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAOTest.java
new file mode 100644
index 0000000..980c429
--- /dev/null
+++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/RegistrationDatabaseDAOTest.java
@@ -0,0 +1,162 @@
+package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao;
+
+import static org.junit.Assert.*;
+
+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.Registration;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException;
+import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager;
+import java.nio.charset.Charset;
+import java.sql.SQLException;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.util.LinkedList;
+import java.util.List;
+import org.h2.tools.RunScript;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class RegistrationDatabaseDAOTest {
+
+ // Base taken from EmployeePersistenceTest
+
+ private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
+ private static final String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
+ private static final String USER = "";
+ private static final String PASSWORD = "";
+
+ private RegistrationDAO registrationDAO;
+
+ public RegistrationDatabaseDAOTest() throws PersistenceException {
+ this.registrationDAO = new RegistrationDatabaseDAO(new JDBCConnectionManager(JDBC_URL));
+ }
+
+ @BeforeClass
+ public static void setupDatabase() throws SQLException {
+ RunScript.execute(
+ JDBC_URL,
+ USER,
+ PASSWORD,
+ "classpath:sql/database.sql",
+ Charset.forName("UTF8"),
+ false);
+ }
+
+ @Before
+ public void setUp() throws SQLException {
+ RunScript.execute(
+ JDBC_URL,
+ USER,
+ PASSWORD,
+ "classpath:sql/H2RegistrationDAOTest_populate.sql",
+ Charset.forName("UTF8"),
+ false);
+ }
+
+ @After
+ public void tearDown() throws SQLException {
+ RunScript.execute(
+ JDBC_URL,
+ USER,
+ PASSWORD,
+ "classpath:sql/H2RegistrationDAOTest_depopulate.sql",
+ Charset.forName("UTF8"),
+ false);
+ }
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void addRegistrationsShouldSucceed() throws PersistenceException {
+ List<Registration> registrations = new LinkedList<>();
+ /*
+ Vehicle vehicle = Vehicle.builder()
+ .id(1)
+ .name("RTW-1")
+ .constructionType(ConstructionType.HOCHDACH)
+ .type(VehicleType.RTW)
+ .status(Status.ABGEMELDET)
+ .hasNef(true)
+ .build();
+ */
+ Employee employee1 =
+ Employee.builder()
+ .id(1)
+ .name("John Doe")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.RS)
+ .isDriver(true)
+ .isPilot(true)
+ .build();
+ Employee employee2 =
+ Employee.builder()
+ .id(2)
+ .name("Nick \"Kage\" Verily")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.NKV)
+ .isDriver(true)
+ .isPilot(false)
+ .build();
+ Employee employee3 =
+ Employee.builder()
+ .id(3)
+ .name("Nicht Arzt")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.NA)
+ .isDriver(false)
+ .isPilot(false)
+ .build();
+ Registration registration1 =
+ Registration.builder()
+ .start(Instant.now()) // incorrect, but should be irrelevant to outcome
+ .end(Instant.now()) // same
+ .employee(employee1)
+ .build();
+ Registration registration2 =
+ Registration.builder()
+ .start(Instant.now()) // incorrect, but should be irrelevant to outcome
+ .end(Instant.now()) // same
+ .employee(employee2)
+ .build();
+ Registration registration3 =
+ Registration.builder()
+ .start(Instant.now()) // incorrect, but should be irrelevant to outcome
+ .end(Instant.now()) // same
+ .employee(employee3)
+ .build();
+ registrations.add(registration1);
+ registrations.add(registration2);
+ registrations.add(registration3);
+
+ List<Long> returnvalues = registrationDAO.add(1, registrations);
+ assertFalse(returnvalues.isEmpty()); // can be improved...
+ }
+
+ @Test
+ public void addRegistrationToInexistentVehicleShouldFail() throws PersistenceException {
+ thrown.expect(PersistenceException.class);
+ List<Registration> registrations = new LinkedList<>();
+ Employee employee =
+ Employee.builder()
+ .id(1)
+ .name("John Doe")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.RS)
+ .isDriver(true)
+ .isPilot(true)
+ .build();
+ Registration registration =
+ Registration.builder()
+ .start(Instant.MIN)
+ .end(Instant.MAX)
+ .employee(employee)
+ .build();
+ registrations.add(registration);
+ registrationDAO.add(200, registrations);
+ }
+}
diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImplTest.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImplTest.java
new file mode 100644
index 0000000..7171f83
--- /dev/null
+++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/RegistrationServiceImplTest.java
@@ -0,0 +1,122 @@
+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.dto.Employee;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Registration;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.ConstructionType;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.Status;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Vehicle.VehicleType;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.LinkedList;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class RegistrationServiceImplTest {
+
+ @Mock RegistrationDAO daoMock;
+
+ @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void addValidRegistrationsShouldSucceed()
+ throws InvalidRegistrationException, ServiceException, InvalidVehicleException {
+ RegistrationService registrationService = new RegistrationServiceImpl(daoMock);
+ List<Registration> registrations = new LinkedList<>();
+ Vehicle vehicle =
+ Vehicle.builder()
+ .id(1)
+ .name("RTW-1")
+ .constructionType(ConstructionType.HOCHDACH)
+ .type(VehicleType.RTW)
+ .status(Status.ABGEMELDET)
+ .hasNef(true)
+ .build();
+ Employee employee1 =
+ Employee.builder()
+ .id(1)
+ .name("John Doe")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.RS)
+ .isDriver(true)
+ .isPilot(true)
+ .build();
+ Employee employee2 =
+ Employee.builder()
+ .id(2)
+ .name("Nick \"Kage\" Verily")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.NKV)
+ .isDriver(true)
+ .isPilot(false)
+ .build();
+ Employee employee3 =
+ Employee.builder()
+ .id(3)
+ .name("Nicht Arzt")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.NA)
+ .isDriver(false)
+ .isPilot(false)
+ .build();
+ Instant start = Instant.now();
+ Instant end = start.plus(8, ChronoUnit.HOURS);
+ Registration registration1 =
+ Registration.builder().start(start).end(end).employee(employee1).build();
+ Registration registration2 =
+ Registration.builder().start(start).end(end).employee(employee2).build();
+ Registration registration3 =
+ Registration.builder().start(start).end(end).employee(employee3).build();
+ registrations.add(registration1);
+ registrations.add(registration2);
+ registrations.add(registration3);
+ registrationService.add(vehicle, registrations);
+ }
+
+ @Test
+ public void addOnlyOnePersonToRTWShouldFail()
+ throws InvalidRegistrationException, ServiceException, InvalidVehicleException {
+ thrown.expect(InvalidRegistrationException.class);
+ RegistrationService registrationService = new RegistrationServiceImpl(daoMock);
+ List<Registration> registrations = new LinkedList<>();
+ Vehicle vehicle =
+ Vehicle.builder()
+ .id(1)
+ .name("RTW-1")
+ .constructionType(ConstructionType.HOCHDACH)
+ .type(VehicleType.RTW)
+ .status(Status.ABGEMELDET)
+ .hasNef(true)
+ .build();
+ Employee employee =
+ Employee.builder()
+ .id(1)
+ .name("John Doe")
+ .birthday(LocalDate.now()) // incorrect, but should be irrelevant
+ .educationLevel(EducationLevel.RS)
+ .isDriver(true)
+ .isPilot(true)
+ .build();
+ Registration registration =
+ Registration.builder()
+ .start(Instant.MIN)
+ .end(Instant.MAX)
+ .employee(employee)
+ .build();
+ registrations.add(registration);
+ registrationService.add(vehicle, registrations);
+ }
+}
diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeePersistenceTest.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeePersistenceTest.java
new file mode 100644
index 0000000..f8fe0f3
--- /dev/null
+++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeePersistenceTest.java
@@ -0,0 +1,155 @@
+package at.ac.tuwien.sepm.assignment.groupphase.employee;
+
+import static junit.framework.TestCase.fail;
+
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.EmployeeDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.EmployeeDatabaseDao;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee;
+import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException;
+import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager;
+import java.nio.charset.Charset;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.JdbcDatabaseTester;
+import org.dbunit.dataset.DataSetException;
+import org.dbunit.dataset.IDataSet;
+import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
+import org.dbunit.operation.DatabaseOperation;
+import org.h2.tools.RunScript;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class EmployeePersistenceTest {
+
+ private static final String JDBC_DRIVER = org.h2.Driver.class.getName();
+ private static final String JDBC_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1";
+ private static final String USER = "";
+ private static final String PASSWORD = "";
+
+ private EmployeeDAO employeePersistence;
+
+ public EmployeePersistenceTest() throws PersistenceException {
+ employeePersistence = new EmployeeDatabaseDao(new JDBCConnectionManager(JDBC_URL));
+ }
+
+ @BeforeClass
+ public static void createSchema() throws SQLException {
+ RunScript.execute(
+ JDBC_URL,
+ USER,
+ PASSWORD,
+ "classpath:sql/database.sql",
+ Charset.forName("UTF8"),
+ false);
+ }
+
+ @Before
+ public void importDataSet() throws Exception {
+ IDataSet dataSet = readDataSet();
+ cleanlyInsert(dataSet);
+ }
+
+ private IDataSet readDataSet() throws DataSetException {
+ return new FlatXmlDataSetBuilder()
+ .build(
+ getClass()
+ .getClassLoader()
+ .getResourceAsStream("employeeServiceTestData.xml"));
+ }
+
+ private void cleanlyInsert(IDataSet dataSet) throws Exception {
+ IDatabaseTester databaseTester =
+ new JdbcDatabaseTester(JDBC_DRIVER, JDBC_URL, USER, PASSWORD);
+
+ databaseTester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);
+ databaseTester.setDataSet(dataSet);
+ databaseTester.onSetup();
+ }
+
+ @Test
+ public void testListEmployees() {
+
+ try {
+ List<Employee> employees = employeePersistence.list();
+
+ Employee empOne =
+ Employee.builder()
+ .id(1)
+ .name("Adam")
+ .birthday(
+ LocalDate.parse(
+ "10.10.2010",
+ DateTimeFormatter.ofPattern("dd.MM.yyyy")))
+ .educationLevel(EducationLevel.RS)
+ .isDriver(true)
+ .isPilot(false)
+ .build();
+
+ Employee empTwo =
+ Employee.builder()
+ .id(2)
+ .name("Max")
+ .birthday(
+ LocalDate.parse(
+ "11.11.1990",
+ DateTimeFormatter.ofPattern("dd.MM.yyyy")))
+ .educationLevel(EducationLevel.NFS)
+ .isDriver(false)
+ .isPilot(false)
+ .build();
+
+ Employee empThree =
+ Employee.builder()
+ .id(3)
+ .name("Lisa")
+ .birthday(
+ LocalDate.parse(
+ "16.10.1999",
+ DateTimeFormatter.ofPattern("dd.MM.yyyy")))
+ .educationLevel(EducationLevel.NKI)
+ .isDriver(true)
+ .isPilot(false)
+ .build();
+
+ Assert.assertTrue(employees.contains(empOne));
+ Assert.assertTrue(employees.contains(empTwo));
+ Assert.assertTrue(employees.contains(empThree));
+ Assert.assertEquals(3, employees.size());
+
+ } catch (PersistenceException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testEmployeeListNoElement() {
+
+ try {
+ List<Employee> employees = employeePersistence.list();
+
+ Employee empOne =
+ Employee.builder()
+ .id(10)
+ .name("Adam")
+ .birthday(
+ LocalDate.parse(
+ "10.10.2010",
+ DateTimeFormatter.ofPattern("dd.MM.yyyy")))
+ .educationLevel(EducationLevel.RS)
+ .isDriver(true)
+ .isPilot(false)
+ .build();
+
+ Assert.assertFalse(employees.contains(empOne));
+
+ } catch (PersistenceException e) {
+ fail();
+ }
+ }
+}
diff --git a/src/test/resources/employeeServiceTestData.xml b/src/test/resources/employeeServiceTestData.xml
new file mode 100644
index 0000000..c21fde6
--- /dev/null
+++ b/src/test/resources/employeeServiceTestData.xml
@@ -0,0 +1,12 @@
+<dataset>
+ <EmployeeVersion id="10" name="Adam" birthday="2010-10-10" educationlevel="RS" isDriver="true"
+ isPilot="false"/>
+ <EmployeeVersion id="20" name="Max" birthday="1990-11-11" educationlevel="NFS" isDriver="false"
+ isPilot="false"/>
+ <EmployeeVersion id="30" name="Lisa" birthday="1999-10-16" educationlevel="NKI" isDriver="true"
+ isPilot="false"/>
+
+ <Employee id="1" version="10" />
+ <Employee id="2" version="20" />
+ <Employee id="3" version="30" />
+</dataset> \ No newline at end of file