diff --git a/mvnw b/mvnw old mode 100644 new mode 100755 diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/FeatureId.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/FeatureId.java index 75ed6fa2..650c59b6 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/FeatureId.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/model/enumeration/FeatureId.java @@ -2,8 +2,9 @@ public enum FeatureId { summary("summary"), - first_data_available("first_data_available"), - timeseries("timeseries"), + wave_buoy_first_data_available("wave_buoy_first_data_available"), + wave_buoy_latest_date("wave_buoy_latest_date"), + wave_buoy_timeseries("wave_buoy_timeseries"), wfs_downloadable_fields("wfs_downloadable_fields"), // Query field based on pure wfs and given layer wms_downloadable_fields("wms_downloadable_fields"), // Query field based on value from wms describe layer query wms_map_tile("wms_map_tile"), diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/DasService.java b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/DasService.java index 0645e83c..314587cf 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/core/service/DasService.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/core/service/DasService.java @@ -1,7 +1,5 @@ package au.org.aodn.ogcapi.server.core.service; -import au.org.aodn.ogcapi.features.model.FeatureCollectionGeoJSON; -import au.org.aodn.ogcapi.features.model.FeatureGeoJSON; import au.org.aodn.ogcapi.server.core.configuration.DASConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; @@ -12,6 +10,8 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import jakarta.annotation.PostConstruct; + import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; @@ -25,12 +25,17 @@ public class DasService { @Autowired protected RestTemplate httpClient; - public byte[] getWaveBuoys(String from, String to){ + private HttpEntity httpEntity; + + @PostConstruct + public void init() { HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); headers.set("X-API-KEY", dasConfig.secret); - HttpEntity entity = new HttpEntity<>(headers); + httpEntity = new HttpEntity<>(headers); + } + public byte[] getWaveBuoys(String from, String to){ String waveBuoysUrlTemplate = UriComponentsBuilder.fromUriString(dasConfig.host + "/api/v1/das/data/feature-collection/wave-buoy") .queryParam("start_date","{start_date}") .queryParam("end_date","{end_date}") @@ -40,17 +45,20 @@ public byte[] getWaveBuoys(String from, String to){ params.put("start_date", from); params.put("end_date",to); - return httpClient.exchange(waveBuoysUrlTemplate, HttpMethod.GET,entity,byte[].class,params).getBody(); + return httpClient.exchange(waveBuoysUrlTemplate, HttpMethod.GET,httpEntity,byte[].class,params).getBody(); + } + + public byte[] getWaveBuoysLatestDate(){ + String waveBuoysUrlTemplate = UriComponentsBuilder.fromUriString(dasConfig.host + "/api/v1/das/data/feature-collection/wave-buoy/latest") + .encode() + .toUriString(); + + return httpClient.exchange(waveBuoysUrlTemplate, HttpMethod.GET,httpEntity,byte[].class).getBody(); } public byte[] getWaveBuoyData(String from, String to, String buoy){ String encodedBuoy = URLEncoder.encode(buoy, java.nio.charset.StandardCharsets.UTF_8); - HttpHeaders headers = new HttpHeaders(); - headers.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE); - headers.set("X-API-KEY", dasConfig.secret); - HttpEntity entity = new HttpEntity<>(headers); - String waveBuoyDataUrlTemplate = UriComponentsBuilder.fromUriString(dasConfig.host + "/api/v1/das/data/feature-collection/wave-buoy/" + encodedBuoy) .queryParam("start_date","{start_date}") .queryParam("end_date","{end_date}") @@ -60,7 +68,7 @@ public byte[] getWaveBuoyData(String from, String to, String buoy){ params.put("start_date", from); params.put("end_date",to); - return httpClient.exchange(waveBuoyDataUrlTemplate, HttpMethod.GET,entity,byte[].class,params).getBody(); + return httpClient.exchange(waveBuoyDataUrlTemplate, HttpMethod.GET,httpEntity,byte[].class,params).getBody(); } public boolean isCollectionSupported(String collectionId){ diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/features/RestApi.java b/server/src/main/java/au/org/aodn/ogcapi/server/features/RestApi.java index d2c106c8..9137160b 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/features/RestApi.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/features/RestApi.java @@ -115,10 +115,13 @@ public ResponseEntity getFeature( return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } - case first_data_available -> { + case wave_buoy_first_data_available -> { return featuresService.getWaveBuoys(collectionId, request.getDatetime()); } - case timeseries -> { + case wave_buoy_latest_date -> { + return featuresService.getWaveBuoysLatestDate(collectionId); + } + case wave_buoy_timeseries -> { return featuresService.getWaveBuoyData(collectionId, request.getDatetime(), request.getWaveBuoy()); } case wfs_downloadable_fields -> { diff --git a/server/src/main/java/au/org/aodn/ogcapi/server/features/RestServices.java b/server/src/main/java/au/org/aodn/ogcapi/server/features/RestServices.java index 422b8b1d..e577067d 100644 --- a/server/src/main/java/au/org/aodn/ogcapi/server/features/RestServices.java +++ b/server/src/main/java/au/org/aodn/ogcapi/server/features/RestServices.java @@ -194,6 +194,23 @@ public ResponseEntity getWaveBuoys(String collectionID, String from) { } } + public ResponseEntity getWaveBuoysLatestDate(String collectionID) { + if (!dasService.isCollectionSupported(collectionID)) { + return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); + } + + try { + return ResponseEntity + .ok() + .header("Content-Type", MediaType.APPLICATION_JSON_VALUE) + .body(dasService.getWaveBuoysLatestDate()); + + } catch (Exception e) { + log.error("Error fetching wave buoys latest date: {}", e.getMessage()); + return ResponseEntity.internalServerError().build(); + } + } + public ResponseEntity getWaveBuoyData(String collectionID, String datetime, String buoy) { if (!dasService.isCollectionSupported(collectionID)) { return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); diff --git a/server/src/test/java/au/org/aodn/ogcapi/server/features/RestServicesTest.java b/server/src/test/java/au/org/aodn/ogcapi/server/features/RestServicesTest.java new file mode 100644 index 00000000..63500c64 --- /dev/null +++ b/server/src/test/java/au/org/aodn/ogcapi/server/features/RestServicesTest.java @@ -0,0 +1,68 @@ +package au.org.aodn.ogcapi.server.features; + +import au.org.aodn.ogcapi.server.core.service.DasService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +public class RestServicesTest { + + @Mock + private DasService dasService; + + @InjectMocks + private RestServices restServices; + + private AutoCloseable closeableMock; + + private static final String SUPPORTED_COLLECTION_ID = "b299cdcd-3dee-48aa-abdd-e0fcdbb9cadc"; + + @BeforeEach + public void setUp() { + closeableMock = MockitoAnnotations.openMocks(this); + } + + @AfterEach + void cleanUp() throws Exception { + closeableMock.close(); + } + + @Test + public void testGetWaveBuoysLatestDateSuccess() { + byte[] mockResponse = "{\"latest_date\":\"2024-01-01\"}".getBytes(); + when(dasService.isCollectionSupported(SUPPORTED_COLLECTION_ID)).thenReturn(true); + when(dasService.getWaveBuoysLatestDate()).thenReturn(mockResponse); + + ResponseEntity response = restServices.getWaveBuoysLatestDate(SUPPORTED_COLLECTION_ID); + + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertEquals(mockResponse, response.getBody()); + } + + @Test + public void testGetWaveBuoysLatestDateUnsupportedCollection() { + when(dasService.isCollectionSupported("unsupported-id")).thenReturn(false); + + ResponseEntity response = restServices.getWaveBuoysLatestDate("unsupported-id"); + + assertEquals(HttpStatus.NOT_IMPLEMENTED, response.getStatusCode()); + } + + @Test + public void testGetWaveBuoysLatestDateServiceError() { + when(dasService.isCollectionSupported(SUPPORTED_COLLECTION_ID)).thenReturn(true); + when(dasService.getWaveBuoysLatestDate()).thenThrow(new RuntimeException("Connection refused")); + + ResponseEntity response = restServices.getWaveBuoysLatestDate(SUPPORTED_COLLECTION_ID); + + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode()); + } +}