From 2aa4b4c5636953ff43bb0d99c8b2831769061f59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Slov=C3=ADk?= <xslovik@fi.muni.cz>
Date: Sat, 6 May 2023 13:19:52 +0200
Subject: [PATCH] Change GpsLocation to GpsLocationValidator

---
 .../exceptions/InvalidGpsLocationAdvice.java  | 27 +++++++++++++++++++
 .../facade/airport/AirportFacadeImpl.java     | 16 +++++++----
 .../pa165/core/mapper/GpsLocationMapper.java  | 11 --------
 .../GpsLocationValidator.java}                | 21 ++++-----------
 .../pa165/core/mapper/AirportMapperTest.java  |  8 +++---
 5 files changed, 47 insertions(+), 36 deletions(-)
 create mode 100644 core/src/main/java/cz/muni/fi/pa165/core/exceptions/InvalidGpsLocationAdvice.java
 delete mode 100644 core/src/main/java/cz/muni/fi/pa165/core/mapper/GpsLocationMapper.java
 rename core/src/main/java/cz/muni/fi/pa165/core/{data/domain/GpsLocation.java => validation/GpsLocationValidator.java} (79%)

diff --git a/core/src/main/java/cz/muni/fi/pa165/core/exceptions/InvalidGpsLocationAdvice.java b/core/src/main/java/cz/muni/fi/pa165/core/exceptions/InvalidGpsLocationAdvice.java
new file mode 100644
index 0000000..3c80af9
--- /dev/null
+++ b/core/src/main/java/cz/muni/fi/pa165/core/exceptions/InvalidGpsLocationAdvice.java
@@ -0,0 +1,27 @@
+package cz.muni.fi.pa165.core.exceptions;
+
+import cz.muni.fi.pa165.core.model.ErrorMessage;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import java.time.OffsetDateTime;
+
+@ControllerAdvice
+public class InvalidGpsLocationAdvice {
+
+    @ExceptionHandler(InvalidGpsLocationException.class)
+    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
+    ResponseEntity<ErrorMessage> handleInvalidGpsLocationException(InvalidGpsLocationException ex) {
+        var errorMessage = new ErrorMessage();
+        errorMessage.setTimestamp(OffsetDateTime.now());
+        errorMessage.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value());
+        errorMessage.setError(HttpStatus.UNPROCESSABLE_ENTITY.getReasonPhrase());
+        errorMessage.setMessage(ex.getMessage());
+        errorMessage.setPath(ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString());
+        return new ResponseEntity<>(errorMessage, HttpStatus.UNPROCESSABLE_ENTITY);
+    }
+}
diff --git a/core/src/main/java/cz/muni/fi/pa165/core/facade/airport/AirportFacadeImpl.java b/core/src/main/java/cz/muni/fi/pa165/core/facade/airport/AirportFacadeImpl.java
index 63f1d9c..323ce75 100644
--- a/core/src/main/java/cz/muni/fi/pa165/core/facade/airport/AirportFacadeImpl.java
+++ b/core/src/main/java/cz/muni/fi/pa165/core/facade/airport/AirportFacadeImpl.java
@@ -10,6 +10,7 @@ import cz.muni.fi.pa165.core.model.NewAirportDtoRequest;
 import cz.muni.fi.pa165.core.service.airport.AirportService;
 import cz.muni.fi.pa165.core.service.city.CityService;
 import cz.muni.fi.pa165.core.service.flight.FlightService;
+import cz.muni.fi.pa165.core.validation.GpsLocationValidator;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -23,21 +24,23 @@ public class AirportFacadeImpl implements AirportFacade<Long> {
     private final FlightService flightService;
     private final CityService cityService;
     private final AirportMapper airportMapper;
+    private final GpsLocationValidator gpsLocationValidator;
 
     @Autowired
-    public AirportFacadeImpl(AirportService airportService,
-                             FlightService flightService,
-                             CityService cityService,
-                             AirportMapper airportMapper
-    ) {
+    public AirportFacadeImpl(AirportService airportService, FlightService flightService, CityService cityService,
+                             AirportMapper airportMapper, GpsLocationValidator gpsLocationValidator) {
         this.airportService = airportService;
         this.flightService = flightService;
         this.cityService = cityService;
         this.airportMapper = airportMapper;
+        this.gpsLocationValidator = gpsLocationValidator;
     }
 
     @Override
     public AirportDto save(NewAirportDtoRequest newAirportDtoRequest) {
+        gpsLocationValidator.validate(newAirportDtoRequest.getLocation().getLatitude(),
+                newAirportDtoRequest.getLocation().getLongitude());
+
         Airport entityToSave = airportMapper.toEntityFromNewRequest(newAirportDtoRequest);
         Airport savedEntity = airportService.save(entityToSave);
         return airportMapper.toDto(savedEntity);
@@ -70,6 +73,9 @@ public class AirportFacadeImpl implements AirportFacade<Long> {
 
     @Override
     public AirportDto update(Long id, NewAirportDtoRequest newAirportDtoRequest) {
+        gpsLocationValidator.validate(newAirportDtoRequest.getLocation().getLatitude(),
+                newAirportDtoRequest.getLocation().getLongitude());
+
         if (!airportService.existsById(id)) {
             throw new ResourceNotFoundException();
         }
diff --git a/core/src/main/java/cz/muni/fi/pa165/core/mapper/GpsLocationMapper.java b/core/src/main/java/cz/muni/fi/pa165/core/mapper/GpsLocationMapper.java
deleted file mode 100644
index 9317502..0000000
--- a/core/src/main/java/cz/muni/fi/pa165/core/mapper/GpsLocationMapper.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cz.muni.fi.pa165.core.mapper;
-
-import cz.muni.fi.pa165.core.data.domain.GpsLocation;
-import cz.muni.fi.pa165.core.model.GPSLocationDto;
-import org.mapstruct.Mapper;
-
-@Mapper(componentModel = "spring")
-public interface GpsLocationMapper {
-
-    GPSLocationDto toDto(GpsLocation gpsLocation);
-}
diff --git a/core/src/main/java/cz/muni/fi/pa165/core/data/domain/GpsLocation.java b/core/src/main/java/cz/muni/fi/pa165/core/validation/GpsLocationValidator.java
similarity index 79%
rename from core/src/main/java/cz/muni/fi/pa165/core/data/domain/GpsLocation.java
rename to core/src/main/java/cz/muni/fi/pa165/core/validation/GpsLocationValidator.java
index b39dee5..fd944f9 100644
--- a/core/src/main/java/cz/muni/fi/pa165/core/data/domain/GpsLocation.java
+++ b/core/src/main/java/cz/muni/fi/pa165/core/validation/GpsLocationValidator.java
@@ -1,25 +1,17 @@
-package cz.muni.fi.pa165.core.data.domain;
+package cz.muni.fi.pa165.core.validation;
 
 import cz.muni.fi.pa165.core.exceptions.InvalidGpsLocationException;
-import lombok.Getter;
-import lombok.ToString;
+import org.springframework.stereotype.Component;
 
-/**
- * Representation of GPS location.
- */
-@Getter
-@ToString
-public class GpsLocation {
-
-    private final double latitude;
-    private final double longitude;
+@Component
+public class GpsLocationValidator {
 
     private static final double MIN_LATITUDE = -90.0;
     private static final double MAX_LATITUDE = 90.0;
     private static final double MIN_LONGITUDE = -180.0;
     private static final double MAX_LONGITUDE = 180.0;
 
-    public GpsLocation(double latitude, double longitude) {
+    public void validate(double latitude, double longitude) {
         if (!validLatitude(latitude)) {
             throw new InvalidGpsLocationException(
                     formatExceptionMessage("latitude", MIN_LATITUDE, MAX_LATITUDE, latitude)
@@ -30,9 +22,6 @@ public class GpsLocation {
                     formatExceptionMessage("longitude", MIN_LONGITUDE, MAX_LONGITUDE, longitude)
             );
         }
-
-        this.latitude = latitude;
-        this.longitude = longitude;
     }
 
     private static boolean validLatitude(double latitude) {
diff --git a/core/src/test/java/cz/muni/fi/pa165/core/mapper/AirportMapperTest.java b/core/src/test/java/cz/muni/fi/pa165/core/mapper/AirportMapperTest.java
index 7eae640..393692f 100644
--- a/core/src/test/java/cz/muni/fi/pa165/core/mapper/AirportMapperTest.java
+++ b/core/src/test/java/cz/muni/fi/pa165/core/mapper/AirportMapperTest.java
@@ -3,7 +3,6 @@ package cz.muni.fi.pa165.core.mapper;
 import cz.muni.fi.pa165.core.data.domain.Airport;
 import cz.muni.fi.pa165.core.data.domain.City;
 import cz.muni.fi.pa165.core.data.domain.Flight;
-import cz.muni.fi.pa165.core.data.domain.GpsLocation;
 import cz.muni.fi.pa165.core.model.AirportDto;
 import cz.muni.fi.pa165.core.model.GPSLocationDto;
 import cz.muni.fi.pa165.core.model.NewAirportDtoRequest;
@@ -53,9 +52,10 @@ class AirportMapperTest {
         atlanta.setId(2023L);
         atlanta.setName("Atlanta");
         jacksonAtlantaAirport.setCity(atlanta);
-        var jacksonAtlantaAirportGpsLocation = new GpsLocation(33.64, -84.41);
-        jacksonAtlantaAirport.setLatitude(jacksonAtlantaAirportGpsLocation.getLatitude());
-        jacksonAtlantaAirport.setLongitude(jacksonAtlantaAirportGpsLocation.getLongitude());
+        var jacksonAtlantaAirportLatitude = 33.64;
+        var jacksonAtlantaAirportLongitude = -84.41;
+        jacksonAtlantaAirport.setLatitude(jacksonAtlantaAirportLatitude);
+        jacksonAtlantaAirport.setLongitude(jacksonAtlantaAirportLongitude);
         jacksonAtlantaAirport.setArrivingFlights(createArrivingFlights());
         jacksonAtlantaAirport.setDepartingFlights(createDepartingFlights());
 
-- 
GitLab