Skip to content

Commit f83cf58

Browse files
Refactor function
1 parent a530442 commit f83cf58

2 files changed

Lines changed: 105 additions & 92 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package au.org.aodn.ogcapi.server.core.service.geoserver;
2+
3+
import au.org.aodn.ogcapi.server.core.model.ogc.wfs.WfsField;
4+
import au.org.aodn.ogcapi.server.core.model.ogc.wfs.WfsFields;
5+
import au.org.aodn.ogcapi.server.core.service.geoserver.wfs.WfsServer;
6+
import au.org.aodn.ogcapi.server.core.util.DatetimeUtils;
7+
import au.org.aodn.ogcapi.server.core.util.GeometryUtils;
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.Optional;
13+
14+
@Slf4j
15+
public abstract class Server {
16+
protected WfsServer wfsServer;
17+
18+
public Server(WfsServer wfsServer) {
19+
this.wfsServer = wfsServer;
20+
}
21+
/**
22+
* Build CQL filter for temporal and spatial constraints
23+
*/
24+
protected String buildCqlFilter(String wfsServerUrl, String uuid, String layerName, String sd, String ed, Object multiPolygon) {
25+
26+
WfsFields wfsFieldModel = wfsServer.getDownloadableFields(
27+
uuid,
28+
WfsServer.WfsFeatureRequest.builder()
29+
.layerName(layerName)
30+
.server(wfsServerUrl)
31+
.build()
32+
);
33+
log.debug("WFSFieldModel by wfs typename: {}", wfsFieldModel);
34+
35+
// Validate start and end dates
36+
final String startDate = DatetimeUtils.validateAndFormatDate(sd, true);
37+
final String endDate = DatetimeUtils.validateAndFormatDate(ed, false);
38+
39+
StringBuilder cqlFilter = new StringBuilder();
40+
41+
if (wfsFieldModel == null || wfsFieldModel.getFields() == null) {
42+
return cqlFilter.toString();
43+
}
44+
45+
List<WfsField> fields = wfsFieldModel.getFields();
46+
47+
// Possible to have multiple days, better to consider all
48+
List<WfsField> temporalField = fields.stream()
49+
.filter(field -> "dateTime".equals(field.getType()) || "date".equals(field.getType()))
50+
.toList();
51+
52+
// Add temporal filter only if both dates are specified
53+
if (!temporalField.isEmpty() && startDate != null && !startDate.isEmpty() && endDate != null && !endDate.isEmpty()) {
54+
List<String> cqls = new ArrayList<>();
55+
temporalField.forEach(temp ->
56+
cqls.add(String.format("(%s DURING %sT00:00:00Z/%sT23:59:59Z)", temp.getName(), startDate, endDate))
57+
);
58+
cqlFilter.append("(").append(String.join(" OR ", cqls)).append(")");
59+
}
60+
61+
// Find geometry field
62+
Optional<WfsField> geometryField = fields.stream()
63+
.filter(field -> "geometrypropertytype".equalsIgnoreCase(field.getType()))
64+
.findFirst();
65+
66+
// Add spatial filter
67+
if (geometryField.isPresent() && multiPolygon != null) {
68+
String fieldName = geometryField.get().getName();
69+
70+
String wkt = GeometryUtils.convertToWkt(multiPolygon);
71+
72+
if ((wkt != null) && !cqlFilter.isEmpty()) {
73+
cqlFilter.append(" AND ");
74+
}
75+
76+
if (wkt != null) {
77+
cqlFilter.append("INTERSECTS(")
78+
.append(fieldName)
79+
.append(",")
80+
.append(wkt)
81+
.append(")");
82+
}
83+
}
84+
85+
return cqlFilter.toString();
86+
}
87+
}

server/src/main/java/au/org/aodn/ogcapi/server/core/service/geoserver/wfs/DownloadWfsDataService.java

Lines changed: 18 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package au.org.aodn.ogcapi.server.core.service.geoserver.wfs;
22

33
import au.org.aodn.ogcapi.server.core.model.ogc.FeatureRequest;
4-
import au.org.aodn.ogcapi.server.core.model.ogc.wfs.WfsField;
5-
import au.org.aodn.ogcapi.server.core.model.ogc.wfs.WfsFields;
6-
import au.org.aodn.ogcapi.server.core.util.DatetimeUtils;
7-
import au.org.aodn.ogcapi.server.core.util.GeometryUtils;
4+
import au.org.aodn.ogcapi.server.core.service.geoserver.Server;
85
import lombok.extern.slf4j.Slf4j;
96
import org.springframework.beans.factory.annotation.Qualifier;
107
import org.springframework.beans.factory.annotation.Value;
@@ -21,8 +18,7 @@
2118

2219
@Slf4j
2320
@Service
24-
public class DownloadWfsDataService {
25-
private final WfsServer wfsServer;
21+
public class DownloadWfsDataService extends Server {
2622
private final RestTemplate restTemplate;
2723
private final HttpEntity<?> pretendUserEntity;
2824
private final int chunkSize;
@@ -33,65 +29,11 @@ public DownloadWfsDataService(
3329
@Qualifier("pretendUserEntity") HttpEntity<?> pretendUserEntity,
3430
@Value("${app.sse.chunkSize:16384}") int chunkSize
3531
) {
36-
this.wfsServer = wfsServer;
32+
super(wfsServer);
3733
this.restTemplate = restTemplate;
3834
this.pretendUserEntity = pretendUserEntity;
3935
this.chunkSize = chunkSize;
4036
}
41-
42-
/**
43-
* Build CQL filter for temporal and spatial constraints
44-
*/
45-
protected String buildCqlFilter(String startDate, String endDate, Object multiPolygon, WfsFields wfsFieldModel) {
46-
StringBuilder cqlFilter = new StringBuilder();
47-
48-
if (wfsFieldModel == null || wfsFieldModel.getFields() == null) {
49-
return cqlFilter.toString();
50-
}
51-
52-
List<WfsField> fields = wfsFieldModel.getFields();
53-
54-
// Possible to have multiple days, better to consider all
55-
List<WfsField> temporalField = fields.stream()
56-
.filter(field -> "dateTime".equals(field.getType()) || "date".equals(field.getType()))
57-
.toList();
58-
59-
// Add temporal filter only if both dates are specified
60-
if (!temporalField.isEmpty() && startDate != null && !startDate.isEmpty() && endDate != null && !endDate.isEmpty()) {
61-
List<String> cqls = new ArrayList<>();
62-
temporalField.forEach(temp ->
63-
cqls.add(String.format("(%s DURING %sT00:00:00Z/%sT23:59:59Z)", temp.getName(), startDate, endDate))
64-
);
65-
cqlFilter.append("(").append(String.join(" OR ", cqls)).append(")");
66-
}
67-
68-
// Find geometry field
69-
Optional<WfsField> geometryField = fields.stream()
70-
.filter(field -> "geometrypropertytype".equalsIgnoreCase(field.getType()))
71-
.findFirst();
72-
73-
// Add spatial filter
74-
if (geometryField.isPresent() && multiPolygon != null) {
75-
String fieldName = geometryField.get().getName();
76-
77-
String wkt = GeometryUtils.convertToWkt(multiPolygon);
78-
79-
if ((wkt != null) && !cqlFilter.isEmpty()) {
80-
cqlFilter.append(" AND ");
81-
}
82-
83-
if (wkt != null) {
84-
cqlFilter.append("INTERSECTS(")
85-
.append(fieldName)
86-
.append(",")
87-
.append(wkt)
88-
.append(")");
89-
}
90-
}
91-
92-
return cqlFilter.toString();
93-
}
94-
9537
/**
9638
* Does collection lookup, WFS validation, field retrieval, and URL building
9739
*/
@@ -104,46 +46,30 @@ public String prepareWfsRequestUrl(
10446
String layerName,
10547
String outputFormat) {
10648

107-
String wfsServerUrl;
108-
String wfsTypeName;
109-
WfsFields wfsFieldModel;
11049

11150
// Get WFS server URL and field model for the given UUID and layer name
11251
Optional<String> featureServerUrl = wfsServer.getFeatureServerUrl(uuid, layerName);
11352

11453
// Get the wfs fields to build the CQL filter
11554
if (featureServerUrl.isPresent()) {
116-
wfsServerUrl = featureServerUrl.get();
117-
wfsTypeName = layerName;
118-
wfsFieldModel = wfsServer.getDownloadableFields(
119-
uuid,
120-
WfsServer.WfsFeatureRequest.builder()
121-
.layerName(wfsTypeName)
122-
.server(wfsServerUrl)
123-
.build()
124-
);
125-
log.debug("WFSFieldModel by wfs typename: {}", wfsFieldModel);
126-
} else {
127-
throw new IllegalArgumentException("No WFS server URL found for the given UUID and layer name");
128-
}
129-
130-
// Validate start and end dates
131-
String validStartDate = DatetimeUtils.validateAndFormatDate(startDate, true);
132-
String validEndDate = DatetimeUtils.validateAndFormatDate(endDate, false);
55+
String wfsServerUrl = featureServerUrl.get();
13356

134-
// Build CQL filter
135-
String cqlFilter = buildCqlFilter(validStartDate, validEndDate, multiPolygon, wfsFieldModel);
57+
// Build CQL filter
58+
String cqlFilter = buildCqlFilter(wfsServerUrl, uuid, layerName, startDate, endDate, multiPolygon);
13659

137-
// Build final WFS request URL
138-
String wfsRequestUrl = wfsServer.createWfsRequestUrl(
139-
wfsServerUrl,
140-
wfsTypeName,
141-
fields,
142-
cqlFilter,
143-
outputFormat);
60+
// Build final WFS request URL
61+
String wfsRequestUrl = wfsServer.createWfsRequestUrl(
62+
wfsServerUrl,
63+
layerName,
64+
fields,
65+
cqlFilter,
66+
outputFormat);
14467

145-
log.info("Prepared WFS request URL: {}", wfsRequestUrl);
146-
return wfsRequestUrl;
68+
log.info("Prepared WFS request URL: {}", wfsRequestUrl);
69+
return wfsRequestUrl;
70+
} else {
71+
throw new IllegalArgumentException("No WFS server URL found for the given UUID and layer name");
72+
}
14773
}
14874

14975
/**

0 commit comments

Comments
 (0)