Skip to content

Commit dd235b3

Browse files
authored
Merge pull request #118 from davidblasby/_ogcapi_records_geojson
OGCAPI - GeoJSON output improvements
2 parents 58dd370 + 8c7ee2b commit dd235b3

File tree

19 files changed

+522
-40
lines changed

19 files changed

+522
-40
lines changed

modules/library/common-index-model/src/main/java/org/fao/geonet/index/converter/DcatConverter.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ private Dataset getDataset(IndexRecord record, String uri, String resourceIdenti
316316
}
317317

318318
// <dct:spatial rdf:parseType="Resource">
319-
datasetBuilder.spatial(record.getGeometries().stream().map(g -> DctSpatial.builder()
319+
datasetBuilder.spatial(record.getGeometriesAsJsonString().stream().map(g -> DctSpatial.builder()
320320
.location(DctLocation.builder().geometry(g).build()).build()).collect(
321321
Collectors.toList()));
322322

@@ -470,7 +470,8 @@ private DataService getDataService(IndexRecord record, String uri, String resour
470470
.getProperties().get(CommonField.key));
471471
}
472472

473-
dataServiceBuilder.spatial(record.getGeometries().stream().map(g -> DctSpatial.builder()
473+
dataServiceBuilder.spatial(record.getGeometriesAsJsonString().stream()
474+
.map(g -> DctSpatial.builder()
474475
.location(DctLocation.builder().geometry(g).build()).build()).collect(
475476
Collectors.toList()));
476477

modules/library/common-index-model/src/main/java/org/fao/geonet/index/converter/GeoJsonConverter.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* Index document to GeoJSON mapping.
3030
*/
3131
@Component
32-
public class GeoJsonConverter {
32+
public class GeoJsonConverter implements IGeoJsonConverter {
3333

3434
@Autowired
3535
FormatterConfiguration formatterConfiguration;
@@ -50,7 +50,7 @@ public Record convert(IndexRecord record) {
5050
ObjectMapper objectMapper = JsonUtils.getObjectMapper();
5151

5252
recordBuilder.geometry(objectMapper.readValue(
53-
record.getGeometries().get(0),
53+
record.getGeometriesAsJsonString().get(0),
5454
Geometry.class));
5555
} catch (Exception ex) {
5656
// TODO: Process the exception
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.fao.geonet.index.converter;
2+
3+
import org.fao.geonet.index.model.gn.IndexRecord;
4+
5+
public interface IGeoJsonConverter {
6+
Object convert(IndexRecord record);
7+
}

modules/library/common-index-model/src/main/java/org/fao/geonet/index/converter/SchemaOrgConverter.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.HashMap;
1515
import java.util.Map;
1616
import java.util.stream.Collectors;
17+
import lombok.extern.slf4j.Slf4j;
1718
import org.apache.commons.lang.StringUtils;
1819
import org.fao.geonet.index.model.gn.Contact;
1920
import org.fao.geonet.index.model.gn.IndexRecord;
@@ -35,6 +36,7 @@
3536
*
3637
* <p>TODO: Add support to translation https://bib.schema.org/workTranslation
3738
*/
39+
@Slf4j(topic = "org.fao.geonet.ogcapi.records")
3840
public class SchemaOrgConverter {
3941

4042
public static Map<String, String> dateMapping = Map.ofEntries(
@@ -246,7 +248,7 @@ public static ObjectNode convert(IndexRecord record) {
246248
if (record.getGeometries().size() > 0) {
247249
ObjectNode spatialCoverage = root.putObject("spatialCoverage");
248250
ArrayNode geo = spatialCoverage.putArray("geo");
249-
record.getGeometries().forEach(g -> {
251+
record.getGeometriesAsJsonString().forEach(g -> {
250252
GeoJsonReader geoJsonReader = new GeoJsonReader();
251253
try {
252254
ObjectNode shape = createThing(null, Types.GeoShape, root);
@@ -259,7 +261,7 @@ public static ObjectNode convert(IndexRecord record) {
259261
envelope.getMaxY(), envelope.getMaxX()));
260262
geo.add(shape);
261263
} catch (ParseException e) {
262-
e.printStackTrace();
264+
log.debug(e.getMessage(),e);
263265
}
264266
});
265267
}

modules/library/common-index-model/src/main/java/org/fao/geonet/index/model/gn/IndexRecord.java

+38-8
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
import com.fasterxml.jackson.annotation.JsonIgnore;
1010
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
1111
import com.fasterxml.jackson.annotation.JsonProperty;
12+
import com.fasterxml.jackson.core.JsonProcessingException;
13+
import com.fasterxml.jackson.databind.ObjectMapper;
1214
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
1315
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
16+
import java.sql.Array;
1417
import java.util.ArrayList;
1518
import java.util.HashMap;
1619
import java.util.List;
@@ -151,14 +154,14 @@ public class IndexRecord extends IndexDocument {
151154
// TODO XML
152155
@XmlTransient
153156
@JsonProperty(IndexRecordFieldNames.geom)
154-
@JsonDeserialize(using = NodeTreeAsStringDeserializer.class)
155-
private List<String> geometries = new ArrayList<>();
157+
//@JsonDeserialize(using = NodeTreeAsStringDeserializer.class)
158+
private List<Object> geometries = new ArrayList<>();
156159

157160
@JsonProperty(IndexRecordFieldNames.specificationConformance)
158161
private List<SpecificationConformance> specificationConformance = new ArrayList();
159162

160163
// @JsonAnyGetter
161-
private Map<String, ArrayList<String>> otherProperties = new HashMap<>();
164+
private Map<String, Object> otherProperties = new HashMap<>();
162165

163166
private Map<String, ArrayList<Codelist>> codelists = new HashMap<>();
164167

@@ -202,6 +205,28 @@ public IndexRecord(AbstractMetadata r) {
202205
public IndexRecord() {
203206
}
204207

208+
/**
209+
* get the #geometries as a JSON string.
210+
*/
211+
public List<String> getGeometriesAsJsonString() {
212+
if (geometries == null || geometries.isEmpty()) {
213+
return null;
214+
}
215+
List<String> result = new ArrayList<>();
216+
217+
for (var g:geometries) {
218+
String s = null;
219+
try {
220+
s = (new ObjectMapper()).writeValueAsString(g);
221+
} catch (JsonProcessingException e) {
222+
continue;
223+
}
224+
result.add(s);
225+
}
226+
return result;
227+
228+
}
229+
205230
/**
206231
* Collect all other properties in a map.
207232
*/
@@ -222,13 +247,18 @@ public void ignored(String name, Object value) {
222247
new Codelist(c)).collect(Collectors.toList()));
223248
}
224249
} else {
225-
ArrayList<String> s = otherProperties.get(name);
250+
var s = otherProperties.get(name);
226251
if (s == null) {
227-
s = new ArrayList<>(1);
228-
s.add(value.toString());
229-
otherProperties.put(name, s);
252+
otherProperties.put(name, value);
230253
} else {
231-
s.add(value.toString());
254+
if (s instanceof List) {
255+
((List) s).add(value.toString());
256+
} else {
257+
var list = new ArrayList<Object>();
258+
list.add(s);
259+
list.add(value);
260+
otherProperties.put(name, list);
261+
}
232262
}
233263
}
234264
}

modules/library/common-index-model/src/main/java/org/fao/geonet/index/model/gn/LocationSerializer.java

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public void serialize(
2020
JsonGenerator gen,
2121
SerializerProvider serializers)
2222
throws IOException {
23+
gen.writeStartObject();
2324
gen.writeArrayFieldStart(IndexRecordFieldNames.location);
2425
coordinate.forEach(c -> {
2526
try {

modules/library/common-index-model/src/test/java/org/fao/geonet/index/model/gn/IndexRecordTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void testJsonToPojo() throws IOException {
9999

100100
Assert.assertEquals(
101101
"{\"type\":\"Polygon\",\"coordinates\":[[[-31.2684,27.6375],[-13.4198,27.6375],[-13.4198,66.5662],[-31.2684,66.5662],[-31.2684,27.6375]]]}",
102-
record.getGeometries().get(0));
102+
record.getGeometriesAsJsonString().get(0));
103103
} catch (JsonProcessingException e) {
104104
e.printStackTrace();
105105
Assert.fail();

modules/library/common-search/src/main/java/org/fao/geonet/common/search/processor/impl/GeoJsonResponseProcessorImpl.java

+18-7
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import com.fasterxml.jackson.databind.node.ObjectNode;
77
import java.io.InputStream;
88
import java.io.OutputStream;
9+
import java.time.Instant;
10+
import java.util.concurrent.atomic.AtomicInteger;
911
import javax.servlet.http.HttpSession;
1012
import lombok.extern.slf4j.Slf4j;
1113
import org.fao.geonet.common.search.domain.ReservedOperation;
1214
import org.fao.geonet.common.search.domain.UserInfo;
1315
import org.fao.geonet.index.JsonUtils;
14-
import org.fao.geonet.index.converter.GeoJsonConverter;
15-
import org.fao.geonet.index.model.geojson.Record;
16+
import org.fao.geonet.index.converter.IGeoJsonConverter;
1617
import org.fao.geonet.index.model.gn.IndexRecord;
1718
import org.fao.geonet.index.model.gn.IndexRecordFieldNames;
1819
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,7 +26,7 @@ public class GeoJsonResponseProcessorImpl
2526
extends JsonUserAndSelectionAwareResponseProcessorImpl {
2627

2728
@Autowired
28-
GeoJsonConverter geoJsonConverter;
29+
IGeoJsonConverter geoJsonConverter;
2930

3031
@Override
3132
public void processResponse(HttpSession httpSession,
@@ -37,13 +38,14 @@ public void processResponse(HttpSession httpSession,
3738
JsonGenerator generator = ResponseParser.jsonFactory.createGenerator(streamToClient);
3839

3940
try {
40-
ResponseParser responseParser = new ResponseParser();
41+
ResponseParser elasticJsonResponseParser = new ResponseParser();
4142
generator.writeStartObject();
4243

4344
generator.writeStringField("type", "FeatureCollection");
4445
generator.writeArrayFieldStart("features");
46+
AtomicInteger numbFeatures = new AtomicInteger(0);
4547
{
46-
responseParser.matchHits(parser, generator, doc -> {
48+
elasticJsonResponseParser.matchHits(parser, generator, doc -> {
4749

4850
// Remove fields with privileges info
4951
if (doc.has(IndexRecordFieldNames.source)) {
@@ -57,8 +59,9 @@ public void processResponse(HttpSession httpSession,
5759
doc.get(IndexRecordFieldNames.source).toPrettyString(),
5860
IndexRecord.class);
5961
try {
60-
Record geojsonRecord = geoJsonConverter.convert(indexRecord);
62+
Object geojsonRecord = geoJsonConverter.convert(indexRecord);
6163
generator.writeRawValue(objectMapper.writeValueAsString(geojsonRecord));
64+
numbFeatures.incrementAndGet();
6265
} catch (Exception ex) {
6366
log.error(String.format(
6467
"GeoJSON conversion returned null result for uuid %s. Check http://localhost:9901/collections/main/items/%s?f=geojson",
@@ -68,7 +71,15 @@ public void processResponse(HttpSession httpSession,
6871
}, false);
6972
}
7073
generator.writeEndArray();
71-
generator.writeNumberField("size", responseParser.total);
74+
generator.writeNumberField("numberMatched", elasticJsonResponseParser.total);
75+
generator.writeNumberField("numberReturned", numbFeatures.intValue());
76+
77+
generator.writeStringField("timeStamp", Instant.now().toString());
78+
79+
generator.writeArrayFieldStart("links");
80+
//TO DO ADD LINKS
81+
generator.writeEndArray();
82+
7283
generator.writeEndObject();
7384
generator.flush();
7485
} finally {

modules/services/ogc-api-records/src/main/java/org/fao/geonet/ogcapi/records/OgcApiRecordApp.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.fao.geonet.ogcapi.records;
77

8+
import org.fao.geonet.index.converter.GeoJsonConverter;
89
import org.fao.geonet.ogcapi.records.controller.CapabilitiesApiController;
910
import org.springframework.boot.SpringApplication;
1011
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -13,6 +14,7 @@
1314
import org.springframework.context.annotation.Bean;
1415
import org.springframework.context.annotation.ComponentScan;
1516
import org.springframework.context.annotation.Configuration;
17+
import org.springframework.context.annotation.FilterType;
1618
import org.springframework.context.annotation.Import;
1719
import org.springframework.web.servlet.config.annotation.CorsRegistry;
1820
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -21,7 +23,10 @@
2123
@SpringBootApplication
2224
@RefreshScope
2325
@Import({CapabilitiesApiController.class})
24-
@ComponentScan({"org.fao.geonet", "org.fao.geonet.domain"})
26+
@ComponentScan(
27+
value = {"org.fao.geonet", "org.fao.geonet.domain"}, excludeFilters =
28+
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = GeoJsonConverter.class)}
29+
)
2530
@Configuration
2631
@EnableCaching
2732
public class OgcApiRecordApp {
@@ -30,9 +35,9 @@ public static void main(String[] args) {
3035
SpringApplication.run(OgcApiRecordApp.class, args);
3136
}
3237

33-
3438
/**
3539
* Configure CORS to allow all connections.
40+
*
3641
* @return CORS configuration.
3742
*/
3843
@Bean

modules/services/ogc-api-records/src/main/java/org/fao/geonet/ogcapi/records/OgcApiRecordWebApp.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,33 @@
55

66
package org.fao.geonet.ogcapi.records;
77

8+
import org.fao.geonet.index.converter.GeoJsonConverter;
89
import org.fao.geonet.ogcapi.records.controller.CapabilitiesApiController;
910
import org.springframework.boot.autoconfigure.SpringBootApplication;
1011
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
1112
import org.springframework.cache.annotation.EnableCaching;
1213
import org.springframework.context.annotation.ComponentScan;
1314
import org.springframework.context.annotation.Configuration;
15+
import org.springframework.context.annotation.FilterType;
1416
import org.springframework.context.annotation.Import;
1517

18+
19+
/**
20+
* We remove the "GeoJsonConverter" from the scanned components so this will app will use the
21+
* "OgcApiGeoJsonConverter".
22+
*/
1623
@SpringBootApplication
1724
@Import({CapabilitiesApiController.class})
18-
@ComponentScan({"org.fao.geonet", "org.fao.geonet.domain"})
25+
@ComponentScan(
26+
value = {"org.fao.geonet", "org.fao.geonet.domain"}, excludeFilters =
27+
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = GeoJsonConverter.class)}
28+
)
29+
//@ComponentScan(
30+
// value = {"org.fao.geonet", "org.fao.geonet.domain"}
31+
//)
1932
@Configuration
2033
@EnableCaching
2134
public class OgcApiRecordWebApp extends SpringBootServletInitializer {
35+
36+
2237
}

modules/services/ogc-api-records/src/main/java/org/fao/geonet/ogcapi/records/controller/ItemApiController.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,11 @@ public ResponseEntity<Void> collectionsCollectionIdItemsGet(
288288

289289
boolean allSourceFields =
290290
mediaType.equals(GnMediaType.APPLICATION_DCAT2_XML)
291-
|| mediaType.equals(GnMediaType.APPLICATION_RDF_XML);
291+
|| mediaType.equals(GnMediaType.APPLICATION_RDF_XML)
292+
|| mediaType.equals(GnMediaType.APPLICATION_GEOJSON)
293+
|| mediaType.equals(GnMediaType.APPLICATION_JSON_LD)
294+
|| mediaType.equals(MediaType.APPLICATION_JSON)
295+
|| mediaType.equals(GnMediaType.APPLICATION_RDF_XML);
292296

293297
return collectionsCollectionIdItemsGetInternal(
294298
query,
@@ -496,7 +500,8 @@ private List<String> setDefaultRssSortBy(List<String> sortby, HttpServletRequest
496500

497501
private String search(
498502
Query requestQuery,
499-
HttpServletRequest request, boolean allSourceFields) {
503+
HttpServletRequest request,
504+
boolean allSourceFields) {
500505

501506
Source source = collectionService.retrieveSourceForCollection(requestQuery.getCollectionId());
502507

@@ -634,4 +639,4 @@ private String getResponseContentType(HttpServletRequest request) {
634639

635640
return mediaType;
636641
}
637-
}
642+
}

0 commit comments

Comments
 (0)