Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OGCAPI - GeoJSON output improvements #118

Merged
merged 8 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ private Dataset getDataset(IndexRecord record, String uri, String resourceIdenti
}

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

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

dataServiceBuilder.spatial(record.getGeometries().stream().map(g -> DctSpatial.builder()
dataServiceBuilder.spatial(record.getGeometriesAsJsonString().stream()
.map(g -> DctSpatial.builder()
.location(DctLocation.builder().geometry(g).build()).build()).collect(
Collectors.toList()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
* Index document to GeoJSON mapping.
*/
@Component
public class GeoJsonConverter {
public class GeoJsonConverter implements IGeoJsonConverter {

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

recordBuilder.geometry(objectMapper.readValue(
record.getGeometries().get(0),
record.getGeometriesAsJsonString().get(0),
Geometry.class));
} catch (Exception ex) {
// TODO: Process the exception
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.fao.geonet.index.converter;

import org.fao.geonet.index.model.gn.IndexRecord;

public interface IGeoJsonConverter {
Object convert(IndexRecord record);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.fao.geonet.index.model.gn.Contact;
import org.fao.geonet.index.model.gn.IndexRecord;
Expand All @@ -35,6 +36,7 @@
*
* <p>TODO: Add support to translation https://bib.schema.org/workTranslation
*/
@Slf4j(topic = "org.fao.geonet.ogcapi.records")
public class SchemaOrgConverter {

public static Map<String, String> dateMapping = Map.ofEntries(
Expand Down Expand Up @@ -246,7 +248,7 @@ public static ObjectNode convert(IndexRecord record) {
if (record.getGeometries().size() > 0) {
ObjectNode spatialCoverage = root.putObject("spatialCoverage");
ArrayNode geo = spatialCoverage.putArray("geo");
record.getGeometries().forEach(g -> {
record.getGeometriesAsJsonString().forEach(g -> {
GeoJsonReader geoJsonReader = new GeoJsonReader();
try {
ObjectNode shape = createThing(null, Types.GeoShape, root);
Expand All @@ -259,7 +261,7 @@ public static ObjectNode convert(IndexRecord record) {
envelope.getMaxY(), envelope.getMaxX()));
geo.add(shape);
} catch (ParseException e) {
e.printStackTrace();
log.debug(e.getMessage(),e);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.sql.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -151,14 +154,14 @@ public class IndexRecord extends IndexDocument {
// TODO XML
@XmlTransient
@JsonProperty(IndexRecordFieldNames.geom)
@JsonDeserialize(using = NodeTreeAsStringDeserializer.class)
private List<String> geometries = new ArrayList<>();
//@JsonDeserialize(using = NodeTreeAsStringDeserializer.class)
private List<Object> geometries = new ArrayList<>();

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

// @JsonAnyGetter
private Map<String, ArrayList<String>> otherProperties = new HashMap<>();
private Map<String, Object> otherProperties = new HashMap<>();

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

Expand Down Expand Up @@ -202,6 +205,28 @@ public IndexRecord(AbstractMetadata r) {
public IndexRecord() {
}

/**
* get the #geometries as a JSON string.
*/
public List<String> getGeometriesAsJsonString() {
if (geometries == null || geometries.isEmpty()) {
return null;
}
List<String> result = new ArrayList<>();

for (var g:geometries) {
String s = null;
try {
s = (new ObjectMapper()).writeValueAsString(g);
} catch (JsonProcessingException e) {
continue;
}
result.add(s);
}
return result;

}

/**
* Collect all other properties in a map.
*/
Expand All @@ -222,13 +247,18 @@ public void ignored(String name, Object value) {
new Codelist(c)).collect(Collectors.toList()));
}
} else {
ArrayList<String> s = otherProperties.get(name);
var s = otherProperties.get(name);
if (s == null) {
s = new ArrayList<>(1);
s.add(value.toString());
otherProperties.put(name, s);
otherProperties.put(name, value);
} else {
s.add(value.toString());
if (s instanceof List) {
((List) s).add(value.toString());
} else {
var list = new ArrayList<Object>();
list.add(s);
list.add(value);
otherProperties.put(name, list);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public void serialize(
JsonGenerator gen,
SerializerProvider serializers)
throws IOException {
gen.writeStartObject();
gen.writeArrayFieldStart(IndexRecordFieldNames.location);
coordinate.forEach(c -> {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public void testJsonToPojo() throws IOException {

Assert.assertEquals(
"{\"type\":\"Polygon\",\"coordinates\":[[[-31.2684,27.6375],[-13.4198,27.6375],[-13.4198,66.5662],[-31.2684,66.5662],[-31.2684,27.6375]]]}",
record.getGeometries().get(0));
record.getGeometriesAsJsonString().get(0));
} catch (JsonProcessingException e) {
e.printStackTrace();
Assert.fail();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.fao.geonet.common.search.domain.ReservedOperation;
import org.fao.geonet.common.search.domain.UserInfo;
import org.fao.geonet.index.JsonUtils;
import org.fao.geonet.index.converter.GeoJsonConverter;
import org.fao.geonet.index.model.geojson.Record;
import org.fao.geonet.index.converter.IGeoJsonConverter;
import org.fao.geonet.index.model.gn.IndexRecord;
import org.fao.geonet.index.model.gn.IndexRecordFieldNames;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -25,7 +26,7 @@ public class GeoJsonResponseProcessorImpl
extends JsonUserAndSelectionAwareResponseProcessorImpl {

@Autowired
GeoJsonConverter geoJsonConverter;
IGeoJsonConverter geoJsonConverter;

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

try {
ResponseParser responseParser = new ResponseParser();
ResponseParser elasticJsonResponseParser = new ResponseParser();
generator.writeStartObject();

generator.writeStringField("type", "FeatureCollection");
generator.writeArrayFieldStart("features");
AtomicInteger numbFeatures = new AtomicInteger(0);
{
responseParser.matchHits(parser, generator, doc -> {
elasticJsonResponseParser.matchHits(parser, generator, doc -> {

// Remove fields with privileges info
if (doc.has(IndexRecordFieldNames.source)) {
Expand All @@ -57,8 +59,9 @@ public void processResponse(HttpSession httpSession,
doc.get(IndexRecordFieldNames.source).toPrettyString(),
IndexRecord.class);
try {
Record geojsonRecord = geoJsonConverter.convert(indexRecord);
Object geojsonRecord = geoJsonConverter.convert(indexRecord);
generator.writeRawValue(objectMapper.writeValueAsString(geojsonRecord));
numbFeatures.incrementAndGet();
} catch (Exception ex) {
log.error(String.format(
"GeoJSON conversion returned null result for uuid %s. Check http://localhost:9901/collections/main/items/%s?f=geojson",
Expand All @@ -68,7 +71,15 @@ public void processResponse(HttpSession httpSession,
}, false);
}
generator.writeEndArray();
generator.writeNumberField("size", responseParser.total);
generator.writeNumberField("numberMatched", elasticJsonResponseParser.total);
generator.writeNumberField("numberReturned", numbFeatures.intValue());

generator.writeStringField("timeStamp", Instant.now().toString());

generator.writeArrayFieldStart("links");
//TO DO ADD LINKS
generator.writeEndArray();

generator.writeEndObject();
generator.flush();
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package org.fao.geonet.ogcapi.records;

import org.fao.geonet.index.converter.GeoJsonConverter;
import org.fao.geonet.ogcapi.records.controller.CapabilitiesApiController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
Expand All @@ -13,6 +14,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
Expand All @@ -21,7 +23,10 @@
@SpringBootApplication
@RefreshScope
@Import({CapabilitiesApiController.class})
@ComponentScan({"org.fao.geonet", "org.fao.geonet.domain"})
@ComponentScan(
value = {"org.fao.geonet", "org.fao.geonet.domain"}, excludeFilters =
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = GeoJsonConverter.class)}
)
@Configuration
@EnableCaching
public class OgcApiRecordApp {
Expand All @@ -30,9 +35,9 @@ public static void main(String[] args) {
SpringApplication.run(OgcApiRecordApp.class, args);
}


/**
* Configure CORS to allow all connections.
*
* @return CORS configuration.
*/
@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,33 @@

package org.fao.geonet.ogcapi.records;

import org.fao.geonet.index.converter.GeoJsonConverter;
import org.fao.geonet.ogcapi.records.controller.CapabilitiesApiController;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;


/**
* We remove the "GeoJsonConverter" from the scanned components so this will app will use the
* "OgcApiGeoJsonConverter".
*/
@SpringBootApplication
@Import({CapabilitiesApiController.class})
@ComponentScan({"org.fao.geonet", "org.fao.geonet.domain"})
@ComponentScan(
value = {"org.fao.geonet", "org.fao.geonet.domain"}, excludeFilters =
{@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = GeoJsonConverter.class)}
)
//@ComponentScan(
// value = {"org.fao.geonet", "org.fao.geonet.domain"}
//)
@Configuration
@EnableCaching
public class OgcApiRecordWebApp extends SpringBootServletInitializer {


}
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ public ResponseEntity<Void> collectionsCollectionIdItemsGet(

boolean allSourceFields =
mediaType.equals(GnMediaType.APPLICATION_DCAT2_XML)
|| mediaType.equals(GnMediaType.APPLICATION_RDF_XML);
|| mediaType.equals(GnMediaType.APPLICATION_RDF_XML)
|| mediaType.equals(GnMediaType.APPLICATION_GEOJSON)
|| mediaType.equals(GnMediaType.APPLICATION_JSON_LD)
|| mediaType.equals(MediaType.APPLICATION_JSON)
|| mediaType.equals(GnMediaType.APPLICATION_RDF_XML);

return collectionsCollectionIdItemsGetInternal(
query,
Expand Down Expand Up @@ -496,7 +500,8 @@ private List<String> setDefaultRssSortBy(List<String> sortby, HttpServletRequest

private String search(
Query requestQuery,
HttpServletRequest request, boolean allSourceFields) {
HttpServletRequest request,
boolean allSourceFields) {

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

Expand Down Expand Up @@ -634,4 +639,4 @@ private String getResponseContentType(HttpServletRequest request) {

return mediaType;
}
}
}
Loading