Skip to content
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package au.org.aodn.ogcapi.server.core.configuration;

import au.org.aodn.ogcapi.server.core.service.Search;
import au.org.aodn.ogcapi.server.core.service.wfs.DownloadableFieldsService;
import au.org.aodn.ogcapi.server.core.service.wfs.WfsDefaultParam;
import au.org.aodn.ogcapi.server.core.service.wfs.WfsServer;
import au.org.aodn.ogcapi.server.core.service.wms.WmsServer;
import au.org.aodn.ogcapi.server.core.util.RestTemplateUtils;
Expand All @@ -16,7 +16,7 @@
@Configuration
public class WfsWmsConfig {

@ConditionalOnMissingBean(name="pretendUserEntity")
@ConditionalOnMissingBean(name = "pretendUserEntity")
@Bean("pretendUserEntity")
public HttpEntity<?> createPretendUserEntity() {
// Some server do not allow program to scrap the content, so we need to pretend to be a client
Expand All @@ -28,11 +28,11 @@ public HttpEntity<?> createPretendUserEntity() {

@Bean
public WfsServer createWfsServer(Search search,
DownloadableFieldsService downloadableFieldsService,
RestTemplate restTemplate,
RestTemplateUtils restTemplateUtils,
@Qualifier("pretendUserEntity") HttpEntity<?> entity) {
return new WfsServer(search, downloadableFieldsService, restTemplate, restTemplateUtils, entity);
@Qualifier("pretendUserEntity") HttpEntity<?> entity,
WfsDefaultParam wfsDefaultParam) {
return new WfsServer(search, restTemplate, restTemplateUtils, entity, wfsDefaultParam);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class DownloadableFieldsNotFoundException extends RuntimeException {
public DownloadableFieldsNotFoundException(String message) {
public class GeoserverFieldsNotFoundException extends RuntimeException {
public GeoserverFieldsNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package au.org.aodn.ogcapi.server.core.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class GeoserverLayersNotFoundException extends RuntimeException {
public GeoserverLayersNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public ResponseEntity<ErrorResponse> handleCustomException(Exception ex, WebRequ
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(DownloadableFieldsNotFoundException.class)
public ResponseEntity<ErrorResponse> handleDownloadableFieldsNotFoundException(DownloadableFieldsNotFoundException ex, WebRequest request) {
@ExceptionHandler(GeoserverFieldsNotFoundException.class)
public ResponseEntity<ErrorResponse> handleDownloadableFieldsNotFoundException(GeoserverFieldsNotFoundException ex, WebRequest request) {
ErrorResponse errorResponse = ErrorResponse
.builder()
.timestamp(LocalDateTime.now())
Expand All @@ -64,7 +64,17 @@ public ResponseEntity<ErrorResponse> handleUnauthorizedServerException(Unauthori
return new ResponseEntity<>(errorResponse, HttpStatus.FORBIDDEN);
}

@ExceptionHandler(GeoserverLayersNotFoundException.class)
public ResponseEntity<ErrorResponse> handleGeoserverLayersNotFoundException(GeoserverLayersNotFoundException ex, WebRequest request) {
ErrorResponse errorResponse = ErrorResponse
.builder()
.timestamp(LocalDateTime.now())
.message(ex.getMessage())
.details(request.getDescription(false))
.build();

return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex, WebRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package au.org.aodn.ogcapi.server.core.exception.wfs;

import au.org.aodn.ogcapi.server.core.exception.DownloadableFieldsNotFoundException;
import au.org.aodn.ogcapi.server.core.exception.GeoserverFieldsNotFoundException;
import au.org.aodn.ogcapi.server.core.exception.UnauthorizedServerException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
Expand Down Expand Up @@ -120,7 +120,7 @@ private static ErrorType categorizeError(Exception e) {
}

// Downloadable fields not found error
if (e instanceof DownloadableFieldsNotFoundException) {
if (e instanceof GeoserverFieldsNotFoundException) {
return ErrorType.DOWNLOADABLE_FIELDS_ERROR;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

public enum FeatureId {
summary("summary"),
wfs_fields("wfs_fields"), // Query field based on pure wfs and given layer
wms_fields("wms_fields"), // Query field based on value from wms describe layer query
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"),
wms_map_feature("wms_map_feature"),
wms_layers("wms_layers"), // Get all available layers from WMS GetCapabilities
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package au.org.aodn.ogcapi.server.core.model.ogc.wfs;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
public class WFSFieldModel {

@JsonProperty("typename")
private String typename;

@JsonProperty("fields")
private List<Field> fields;

@Data
@Builder
public static class Field {
@JsonProperty("label")
private String label;

@JsonProperty("name")
private String name;

@JsonProperty("type")
private String type;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public class WfsDescribeFeatureTypeResponse {
@JacksonXmlElementWrapper(useWrapping = false)
private List<ComplexType> complexTypes;

// Top-level element like <xsd:element name="aatams_sattag_dm_profile_map" .../>
@JacksonXmlProperty(localName = "element")
@JacksonXmlElementWrapper(useWrapping = false)
private List<TopLevelElement> topLevelElements;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class ComplexType {
Expand Down Expand Up @@ -58,4 +63,18 @@ public static class Element {
@JacksonXmlProperty(isAttribute = true)
private String type;
}

// Top-level element: <xsd:element name="aatams_sattag_dm_profile_map" substitutionGroup="gml:AbstractFeature" type="imos:aatams_sattag_dm_profile_mapType"/>
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class TopLevelElement {
@JacksonXmlProperty(isAttribute = true)
private String name;

@JacksonXmlProperty(isAttribute = true)
private String type;

@JacksonXmlProperty(isAttribute = true)
private String substitutionGroup;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package au.org.aodn.ogcapi.server.core.service.wfs;

import au.org.aodn.ogcapi.server.core.model.ogc.FeatureRequest;
import au.org.aodn.ogcapi.server.core.model.ogc.wfs.DownloadableFieldModel;
import au.org.aodn.ogcapi.server.core.model.ogc.wfs.WFSFieldModel;
import au.org.aodn.ogcapi.server.core.model.ogc.wms.DescribeLayerResponse;
import au.org.aodn.ogcapi.server.core.service.wms.WmsServer;
import au.org.aodn.ogcapi.server.core.util.DatetimeUtils;
Expand Down Expand Up @@ -46,11 +46,17 @@ public DownloadWfsDataService(
/**
* Build CQL filter for temporal and spatial constraints
*/
private String buildCqlFilter(String startDate, String endDate, Object multiPolygon, List<DownloadableFieldModel> downloadableFields) {
private String buildCqlFilter(String startDate, String endDate, Object multiPolygon, WFSFieldModel wfsFieldModel) {
StringBuilder cqlFilter = new StringBuilder();

if (wfsFieldModel == null || wfsFieldModel.getFields() == null) {
return cqlFilter.toString();
}

List<WFSFieldModel.Field> fields = wfsFieldModel.getFields();

// Find temporal field
Optional<DownloadableFieldModel> temporalField = downloadableFields.stream()
Optional<WFSFieldModel.Field> temporalField = fields.stream()
.filter(field -> "dateTime".equals(field.getType()) || "date".equals(field.getType()))
.findFirst();

Expand All @@ -64,7 +70,7 @@ private String buildCqlFilter(String startDate, String endDate, Object multiPoly
}

// Find geometry field
Optional<DownloadableFieldModel> geometryField = downloadableFields.stream()
Optional<WFSFieldModel.Field> geometryField = fields.stream()
.filter(field -> "geometrypropertytype".equals(field.getType()))
.findFirst();

Expand Down Expand Up @@ -131,23 +137,23 @@ public String prepareWfsRequestUrl(

String wfsServerUrl;
String wfsTypeName;
List<DownloadableFieldModel> downloadableFields;
WFSFieldModel wfsFieldModel;

// Try to get WFS details from DescribeLayer first, then fallback to searching by layer name
if (describeLayerResponse != null && describeLayerResponse.getLayerDescription().getWfs() != null) {
wfsServerUrl = describeLayerResponse.getLayerDescription().getWfs();
wfsTypeName = describeLayerResponse.getLayerDescription().getQuery().getTypeName();

downloadableFields = wfsServer.getDownloadableFields(uuid, FeatureRequest.builder().layerName(wfsTypeName).build(), wfsServerUrl);
log.info("DownloadableFields by describeLayer: {}", downloadableFields);
wfsFieldModel = wfsServer.getDownloadableFields(uuid, FeatureRequest.builder().layerName(wfsTypeName).build(), wfsServerUrl);
log.info("WFSFieldModel by describeLayer: {}", wfsFieldModel);
} else {
Optional<String> featureServerUrl = wfsServer.getFeatureServerUrlByTitle(uuid, layerName);

if (featureServerUrl.isPresent()) {
wfsServerUrl = featureServerUrl.get();
wfsTypeName = layerName;
downloadableFields = wfsServer.getDownloadableFields(uuid, FeatureRequest.builder().layerName(wfsTypeName).build(), wfsServerUrl);
log.info("DownloadableFields by wfs typename: {}", downloadableFields);
wfsFieldModel = wfsServer.getDownloadableFields(uuid, FeatureRequest.builder().layerName(wfsTypeName).build(), wfsServerUrl);
log.info("WFSFieldModel by wfs typename: {}", wfsFieldModel);
} else {
throw new IllegalArgumentException("No WFS server URL found for the given UUID and layer name");
}
Expand All @@ -158,7 +164,7 @@ public String prepareWfsRequestUrl(
String validEndDate = DatetimeUtils.validateAndFormatDate(endDate, false);

// Build CQL filter
String cqlFilter = buildCqlFilter(validStartDate, validEndDate, multiPolygon, downloadableFields);
String cqlFilter = buildCqlFilter(validStartDate, validEndDate, multiPolygon, wfsFieldModel);

// Build final WFS request URL
String wfsRequestUrl = buildWfsRequestUrl(wfsServerUrl, wfsTypeName, cqlFilter);
Expand Down

This file was deleted.

Loading
Loading