aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service
diff options
context:
space:
mode:
authorTharre <tharre3@gmail.com>2018-06-20 22:07:36 +0200
committerTharre <tharre3@gmail.com>2018-06-20 22:07:36 +0200
commit0c995a05985da749d93aa56eba976c7fc621a4fa (patch)
tree5b80394920705aae5e2b6004c3dfbd839c8b8fa3 /src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service
parentf5bc7925a8fbbe247972a6f0e0571cc7e92fbefa (diff)
parente21feb3ac772a5394dc5381b58142c3c061de716 (diff)
downloadsepm-groupproject-master.tar.gz
sepm-groupproject-master.tar.xz
sepm-groupproject-master.zip
Merge branch 'develop'HEADv3.0master
Diffstat (limited to 'src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service')
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java46
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java59
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java70
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java286
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java32
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java60
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java49
-rw-r--r--src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java116
8 files changed, 718 insertions, 0 deletions
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java
new file mode 100644
index 0000000..5beabaa
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeService.java
@@ -0,0 +1,46 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee;
+import java.util.Set;
+
+public interface EmployeeService {
+
+ /**
+ * Add given employee to the store.
+ *
+ * @param employee that should be added to the store
+ * @return the id that was assigned
+ * @throws InvalidEmployeeException if the employee is invalid
+ * @throws ServiceException if the employee could not be persisted
+ */
+ long add(Employee employee) throws InvalidEmployeeException, ServiceException;
+
+ /**
+ * Update the given employee.
+ *
+ * @param employee that should be updated
+ * @return the updated employee
+ * @throws InvalidEmployeeException if the employee is invalid
+ * @throws ServiceException if the updated employee could not be persisted
+ */
+ Employee update(Employee employee) throws InvalidEmployeeException, ServiceException;
+
+ /**
+ * Get all stored employees.
+ *
+ * @return list containing all stored employees
+ * @throws ServiceException if loading the stored employees failed
+ */
+ Set<Employee> list() throws ServiceException;
+
+ /**
+ * Remove employee with the given id from the store.
+ *
+ * @param id of the employee that should be removed
+ * @throws InvalidEmployeeException if given employee id is invalid or does not exist
+ * @throws ServiceException if the employee could not be removed from the store
+ */
+ void remove(long id) throws InvalidEmployeeException, ServiceException;
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java
new file mode 100644
index 0000000..a08b03e
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/EmployeeServiceImpl.java
@@ -0,0 +1,59 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.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 at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.EmployeeDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Employee;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.EmployeeValidator;
+import java.util.Set;
+import org.springframework.stereotype.Service;
+
+@Service
+public class EmployeeServiceImpl implements EmployeeService {
+
+ private final EmployeeDAO employeePersistence;
+
+ public EmployeeServiceImpl(EmployeeDAO employeePersistence) {
+ this.employeePersistence = employeePersistence;
+ }
+
+ @Override
+ public long add(Employee employee) throws InvalidEmployeeException, ServiceException {
+
+ EmployeeValidator.validate(employee);
+ try {
+ return employeePersistence.add(employee);
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public Employee update(Employee employee) throws InvalidEmployeeException, ServiceException {
+
+ EmployeeValidator.validate(employee);
+ try {
+ employeePersistence.update(employee);
+ return employee;
+ } catch (ElementNotFoundException | PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public Set<Employee> list() throws ServiceException {
+
+ try {
+ return employeePersistence.list();
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public void remove(long id) throws InvalidEmployeeException, ServiceException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java
new file mode 100644
index 0000000..42b23bb
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationService.java
@@ -0,0 +1,70 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.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.missioncontrol.dto.Operation;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.SortedSet;
+
+public interface OperationService {
+
+ /**
+ * Add given operation to the store.
+ *
+ * @param operation that should be added to the store
+ * @return the id that was assigned
+ * @throws InvalidOperationException if the operation is invalid
+ * @throws ServiceException if the operation could not be persisted
+ */
+ long add(Operation operation) throws InvalidOperationException, ServiceException;
+
+ /**
+ * Request new vehicles to the given operation.
+ *
+ * @param operationId id of the operation that the vehicles should be send to
+ * @param vehicleIds the ids of the vehicles that should be send to the given operation
+ * @throws InvalidOperationException if the operationId is invalid or does not exist
+ * @throws InvalidVehicleException if one of the vehicle ids is invalid or does not exist
+ * @throws ServiceException if the vehicles could not be loaded or the operation could not be
+ * persisted
+ */
+ void requestVehicles(long operationId, Set<Long> vehicleIds)
+ throws InvalidOperationException, InvalidVehicleException, ServiceException;
+
+ /**
+ * Completes the given operation with the specified status.
+ *
+ * @param operationId id of the operation that should be completed
+ * @param status of the completed operation, either {@link Status#COMPLETED} or {@link
+ * Status#CANCELLED}
+ * @throws InvalidOperationException if the operationId is invalid or does not exist
+ * @throws ServiceException if the operation could not be persisted
+ */
+ void complete(long operationId, Status status)
+ throws InvalidOperationException, ServiceException;
+
+ /**
+ * Get all available vehicles, sorted by how well they fit to the given opCode, starting with
+ * the best fitting.
+ *
+ * @param opCode the operation code that is used to determine the ranking
+ * @return a sorted list containing all available vehicles
+ * @throws InvalidOperationException if the opCode is invalid
+ * @throws ServiceException if loading the stored vehicles failed
+ */
+ SortedSet<Vehicle> rankVehicles(String opCode)
+ throws InvalidOperationException, ServiceException;
+
+ /**
+ * Get all stored operations with matching status.
+ *
+ * @param statuses set containing all statuses that should be matched
+ * @return list containing all matched operations
+ * @throws ServiceException if loading the stored operations failed
+ */
+ Set<Operation> list(EnumSet<Status> statuses) throws ServiceException;
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java
new file mode 100644
index 0000000..0c350fe
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/OperationServiceImpl.java
@@ -0,0 +1,286 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.OperationDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.VehicleDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Severity;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.VehicleType;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OperationServiceImpl implements OperationService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OperationServiceImpl.class);
+
+ private final OperationDAO operationDAO;
+ private final VehicleDAO vehicleDAO;
+ private final VehicleService vehicleService;
+
+ public OperationServiceImpl(
+ OperationDAO operationDAO, VehicleDAO vehicleDAO, VehicleService vehicleService) {
+ this.operationDAO = operationDAO;
+ this.vehicleDAO = vehicleDAO;
+ this.vehicleService = vehicleService;
+ }
+
+ @Override
+ public long add(Operation o) throws InvalidOperationException, ServiceException {
+ if (o.created() != null) {
+ throw new InvalidOperationException("Erstellungszeitpunkt darf nicht gesetzt sein");
+ }
+
+ if (o.severity() != null) {
+ throw new InvalidOperationException("Der Schweregrad darf nicht gesetzt sein");
+ }
+
+ if (o.id() != 0) {
+ throw new InvalidOperationException("Einsatz-ID muss 0 sein");
+ }
+
+ if (o.status() != Status.ACTIVE)
+ LOG.info("Status was set but will be overridden"); // TODO: nullable instead??
+
+ try {
+ for (long id : (Iterable<Long>) o.vehicles().stream().map(Vehicle::id)::iterator) {
+ Vehicle v = vehicleDAO.get(id);
+ VehicleServiceImpl.validateVehicle(v);
+
+ if (v.status() != Vehicle.Status.FREI_FUNK
+ && v.status() != Vehicle.Status.FREI_WACHE)
+ throw new InvalidOperationException("Fahrzeug nicht verfügbar: " + v.status());
+ }
+
+ validateOperation(o);
+
+ return operationDAO.add(
+ o.toBuilder()
+ .created(Instant.now())
+ .severity(extractSeverityFromOpCode(o.opCode()))
+ .status(Status.ACTIVE)
+ .build());
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ } catch (InvalidVehicleException e) {
+ // already logged as invalid vehicle
+ throw new InvalidOperationException("Enthaltenes Fahrzeug ist ungültig", e);
+ } catch (ElementNotFoundException e) {
+ throw new InvalidOperationException("Enthaltenes Fahrzeug existiert nicht", e);
+ }
+ }
+
+ @Override
+ public void requestVehicles(long operationId, Set<Long> vehicleIds)
+ throws InvalidOperationException, InvalidVehicleException, ServiceException {
+ Set<Vehicle> vs = new HashSet<>();
+
+ try {
+ if (operationId <= 0) {
+ throw new InvalidOperationException("Einsatz-ID ist ungültig");
+ }
+ Operation o = operationDAO.get(operationId);
+ validateOperation(o);
+
+ if (o.opCode().trim().isEmpty()
+ || extractSeverityFromOpCode(o.opCode()) != o.severity()) {
+ throw new InvalidOperationException("Einsatzcode ist ungültig");
+ }
+
+ if (o.status() != Status.ACTIVE) {
+ throw new InvalidOperationException("Einsatz ist ungültig");
+ }
+
+ if (o.created() == null) {
+ throw new InvalidOperationException("Erstellungszeitpunkt darf nicht leer sein");
+ }
+
+ for (Long id : vehicleIds) {
+ if (id <= 0) {
+ throw new InvalidVehicleException("Fahrzeug-ID ist ungültig");
+ }
+
+ try {
+ Vehicle v = vehicleDAO.get(id);
+ VehicleServiceImpl.validateVehicle(v);
+ if (v.status() != Vehicle.Status.FREI_FUNK
+ && v.status() != Vehicle.Status.FREI_WACHE)
+ throw new InvalidOperationException(
+ "Fahrzeug nicht verfügbar: " + v.status());
+
+ vs.add(v);
+ } catch (ElementNotFoundException e) {
+ throw new InvalidVehicleException("VehicleId ist invalid");
+ }
+ }
+
+ vs.addAll(o.vehicles());
+ if (vs.equals(o.vehicles())) return;
+
+ operationDAO.update(o.toBuilder().vehicles(vs).build());
+ } catch (ElementNotFoundException e) {
+ throw new InvalidOperationException("Kein Einsatz mit dieser ID existiert");
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public void complete(long operationId, Status status)
+ throws InvalidOperationException, ServiceException {
+ try {
+ Operation o = operationDAO.get(operationId);
+ operationDAO.update(o.toBuilder().status(status).build());
+ } catch (ElementNotFoundException e) {
+ throw new InvalidOperationException(e);
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public SortedSet<Vehicle> rankVehicles(String opCode)
+ throws InvalidOperationException, ServiceException {
+ Set<Vehicle> vehicles =
+ vehicleService.list(EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET)));
+
+ List<Predicate<Vehicle>> priorities = new ArrayList<>();
+ Predicate<Vehicle> ktw = v -> v.type() == VehicleType.KTW;
+ Predicate<Vehicle> rtwNoNEF = v -> v.type() == VehicleType.RTW && !v.hasNef();
+ Predicate<Vehicle> rtwNEF = v -> v.type() == VehicleType.RTW && v.hasNef();
+ Predicate<Vehicle> nef = v -> v.type() == VehicleType.NEF;
+ Predicate<Vehicle> nah = v -> v.type() == VehicleType.NAH;
+
+ switch (extractSeverityFromOpCode(opCode)) {
+ case A:
+ // fallthrough
+ case B:
+ // fallthrough
+ case O:
+ priorities.add(ktw);
+ priorities.add(rtwNoNEF);
+ priorities.add(rtwNEF);
+ break;
+ case C:
+ priorities.add(rtwNEF);
+ priorities.add(rtwNoNEF);
+ priorities.add(ktw);
+ break;
+ case D:
+ priorities.add(rtwNEF);
+ priorities.add(nef);
+ priorities.add(nah);
+ priorities.add(rtwNoNEF);
+ priorities.add(ktw);
+ break;
+ case E:
+ priorities.add(nah);
+ priorities.add(nef);
+ priorities.add(rtwNEF);
+ priorities.add(rtwNoNEF);
+ priorities.add(ktw);
+ break;
+ }
+
+ Comparator<Vehicle> vehicleComparator =
+ (v1, v2) -> {
+ for (Predicate<Vehicle> priority : priorities) {
+ if (priority.test(v1)) {
+ return -1;
+ }
+ if (priority.test(v2)) {
+ return +1;
+ }
+ }
+ return 0;
+ };
+
+ Supplier<TreeSet<Vehicle>> supplier = () -> new TreeSet<>(vehicleComparator);
+
+ return vehicles.stream().collect(Collectors.toCollection(supplier));
+ }
+
+ @Override
+ public Set<Operation> list(EnumSet<Status> statuses) throws ServiceException {
+ try {
+ Set<Operation> operations = operationDAO.list(statuses);
+ for (Operation o : operations) validateOperation(o);
+
+ return operations;
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ } catch (InvalidOperationException e) {
+ // database returned invalid values
+ throw new ServiceException("DB returned invalid operation", e);
+ }
+ }
+
+ private static void validateOperation(Operation o) throws InvalidOperationException {
+ if (o.vehicles().isEmpty()) {
+ throw new InvalidOperationException(
+ "Es muss mindestens ein Fahrzeug ausgewählt werden!");
+ }
+
+ for (Vehicle v : o.vehicles()) {
+ try {
+ VehicleServiceImpl.validateVehicle(v);
+ } catch (InvalidVehicleException e) {
+ throw new InvalidOperationException("Fahrzeug " + v.name() + " ist ungültig", e);
+ }
+
+ // TODO: validate if NEF/RTW/NAH conditions?
+ }
+
+ Instant created = o.created();
+ if (created != null && created.isAfter(Instant.now())) {
+ throw new InvalidOperationException("Einsatz wurde in der Zukunft erstellt");
+ }
+
+ if (o.destination() == null || o.destination().trim().isEmpty()) {
+ throw new InvalidOperationException("Adresse darf nicht leer sein");
+ }
+
+ if (o.destination().length() > 100) {
+ throw new InvalidOperationException("Adresse darf 100 Zeichen nicht überschreiten");
+ }
+
+ if (o.additionalInfo() != null && o.additionalInfo().length() > 100) {
+ throw new InvalidOperationException("Anmerkung darf 100 Zeichen nicht überschreiten");
+ }
+ }
+
+ private static final Pattern opCodePattern =
+ Pattern.compile("(?:\\w{1,3}-\\d{0,2})([ABCDEO])(?:.*)");
+
+ private static Severity extractSeverityFromOpCode(String opCode)
+ throws InvalidOperationException {
+ Matcher m = opCodePattern.matcher(opCode);
+
+ if (!m.matches()) {
+ throw new InvalidOperationException("Einsatzcode ist ungültig");
+ }
+
+ return Severity.valueOf(m.group(1));
+ }
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java
new file mode 100644
index 0000000..91577dc
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationService.java
@@ -0,0 +1,32 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration;
+import java.util.Set;
+
+public interface RegistrationService {
+
+ /**
+ * Register employee to a vehicle.
+ *
+ * @param vehicleId the id of the target vehicle
+ * @param registrations that should be added to the vehicle
+ * @return the list of ids that were assigned
+ * @throws InvalidVehicleException if the vehicleId is invalid or does not exist
+ * @throws InvalidRegistrationException if the registration is invalid
+ * @throws ServiceException if the registration could not be persisted
+ */
+ Set<Long> add(long vehicleId, Set<Registration> registrations)
+ throws InvalidVehicleException, InvalidRegistrationException, ServiceException;
+
+ /**
+ * Remove given registration from the store.
+ *
+ * @param registrationId the id of the registration that should be removed
+ * @throws InvalidRegistrationException if the registration is invalid or does not exist
+ * @throws ServiceException if the registration could not be removed from the store
+ */
+ void remove(long registrationId) throws InvalidRegistrationException, ServiceException;
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java
new file mode 100644
index 0000000..a6a1dfe
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/RegistrationServiceImpl.java
@@ -0,0 +1,60 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+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 at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.RegistrationDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.VehicleDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.RegistrationValidator;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RegistrationServiceImpl implements RegistrationService {
+
+ private final RegistrationDAO registrationDAO;
+ private final VehicleDAO vehicleDAO;
+
+ @Autowired
+ public RegistrationServiceImpl(RegistrationDAO registrationDAO, VehicleDAO vehicleDAO) {
+ this.registrationDAO = registrationDAO;
+ this.vehicleDAO = vehicleDAO;
+ }
+
+ @Override
+ public Set<Long> add(long vehicleId, Set<Registration> registrations)
+ throws InvalidVehicleException, InvalidRegistrationException, ServiceException {
+
+ if (vehicleId <= 0) throw new InvalidVehicleException("VehicleId invalid");
+
+ try {
+ Vehicle vehicle = vehicleDAO.get(vehicleId);
+
+ RegistrationValidator.validate(vehicle, registrations);
+
+ return registrationDAO.add(vehicle.id(), registrations);
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ } catch (ElementNotFoundException e) {
+ throw new InvalidVehicleException(e);
+ }
+ }
+
+ @Override
+ public void remove(long registrationId) throws InvalidRegistrationException, ServiceException {
+ if (registrationId <= 0) throw new InvalidRegistrationException("RegistrationId invalid");
+
+ try {
+ registrationDAO.remove(registrationId);
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ } catch (ElementNotFoundException e) {
+ throw new InvalidRegistrationException(e);
+ }
+ }
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java
new file mode 100644
index 0000000..f8e303d
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleService.java
@@ -0,0 +1,49 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException;
+import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status;
+import java.util.EnumSet;
+import java.util.Set;
+
+public interface VehicleService {
+
+ /**
+ * Add given vehicle to the store.
+ *
+ * @param vehicle that should be added to the store
+ * @return the id that was assigned
+ * @throws InvalidVehicleException if the vehicle is invalid
+ * @throws ServiceException if the vehicle could not be persisted
+ */
+ long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException;
+
+ /**
+ * Update the given vehicle.
+ *
+ * @param vehicle that should be updated
+ * @return the updated vehicle
+ * @throws InvalidVehicleException if the vehicle is invalid
+ * @throws ServiceException if the updated vehicle could not be persisted
+ */
+ Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException;
+
+ /**
+ * Get all stored vehicles with matching status.
+ *
+ * @param statuses set containing all statuses that should be matched
+ * @return list containing all stored vehicles
+ * @throws ServiceException if loading the stored vehicles failed
+ */
+ Set<Vehicle> list(EnumSet<Status> statuses) throws ServiceException;
+
+ /**
+ * Remove vehicle with the given id from the store.
+ *
+ * @param id of the vehicle that should be removed
+ * @throws InvalidVehicleException if given vehicle id is invalid or does not exist
+ * @throws ServiceException if the vehicle could not be removed from the store
+ */
+ void remove(long id) throws InvalidVehicleException, ServiceException;
+}
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java
new file mode 100644
index 0000000..a68720d
--- /dev/null
+++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/missioncontrol/service/VehicleServiceImpl.java
@@ -0,0 +1,116 @@
+package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service;
+
+import at.ac.tuwien.sepm.assignment.groupphase.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 at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dao.VehicleDAO;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.ConstructionType;
+import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle.Status;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+@Service
+public class VehicleServiceImpl implements VehicleService {
+
+ private VehicleDAO vehiclePersistence;
+
+ public VehicleServiceImpl(VehicleDAO vehiclePersistence) {
+ this.vehiclePersistence = vehiclePersistence;
+ }
+
+ public long add(Vehicle vehicle) throws InvalidVehicleException, ServiceException {
+ if (!CollectionUtils.isEmpty(vehicle.registrations())) {
+ throw new InvalidVehicleException(
+ "Fahrzeug kann nicht mit Anmeldungen erstellt werden");
+ }
+
+ validateVehicle(vehicle);
+ try {
+ vehiclePersistence.add(vehicle);
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ return 0;
+ }
+
+ public Vehicle update(Vehicle vehicle) throws InvalidVehicleException, ServiceException {
+ validateVehicle(vehicle);
+ try {
+ vehiclePersistence.update(vehicle);
+ } catch (ElementNotFoundException e) {
+ throw new ServiceException("Element not found", e);
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+ return vehicle;
+ }
+
+ protected static void validateVehicle(Vehicle vehicle) throws InvalidVehicleException {
+ switch (vehicle.type()) {
+ case RTW:
+ if (vehicle.constructionType() == ConstructionType.NORMAL) {
+ throw new InvalidVehicleException("RTW darf kein Normales Dach haben");
+ } else if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) {
+ throw new InvalidVehicleException("RTW darf kein Mittelhochdach haben");
+ }
+ break;
+ case KTW:
+ if (vehicle.constructionType() == ConstructionType.NORMAL) {
+ throw new InvalidVehicleException("KTW darf kein Normales Dach haben");
+ }
+ break;
+ case KTW_B:
+ if (vehicle.constructionType() == ConstructionType.NORMAL) {
+ throw new InvalidVehicleException("KTW-B darf kein Normales Dach haben");
+ }
+ break;
+ case NEF:
+ if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) {
+ throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben");
+ } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) {
+ throw new InvalidVehicleException("NEF darf kein Hochdach haben");
+ }
+ break;
+ case NAH:
+ if (vehicle.constructionType() == ConstructionType.MITTELHOCHDACH) {
+ throw new InvalidVehicleException("NEF darf kein Mittelhochdach haben");
+ } else if (vehicle.constructionType() == ConstructionType.HOCHDACH) {
+ throw new InvalidVehicleException("NEF darf kein Hochdach haben");
+ }
+ break;
+ case BKTW:
+ break;
+ default:
+ throw new IllegalStateException("BUG: invalid vehicle type" + vehicle.type());
+ }
+ }
+
+ @Override
+ public Set<Vehicle> list(EnumSet<Status> statuses) throws ServiceException {
+ if (statuses == null) {
+ throw new ServiceException("Statuses may not be null");
+ }
+
+ Set<Vehicle> vehicles;
+
+ try {
+ vehicles = vehiclePersistence.list();
+ } catch (PersistenceException e) {
+ throw new ServiceException(e);
+ }
+
+ return vehicles.stream()
+ .filter(vehicle -> statuses.contains(vehicle.status()))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public void remove(long id) throws InvalidVehicleException, ServiceException {
+ throw new UnsupportedOperationException();
+ }
+}