Skip to content

Commit

Permalink
problems with the content negotiation
Browse files Browse the repository at this point in the history
  • Loading branch information
david-blasby committed Oct 23, 2024
1 parent 2312ad6 commit db67b86
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 148 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@
@Slf4j(topic = "org.fao.geonet.searching")
public class ElasticSearchProxy {

/**
* ACCEPT_OVERRIDE_ATTRIBUTE.
*
* <p>request.setVariable(ACCEPT_OVERRIDE_ATTRIBUTE, "gnindex");
* This will force this to return the underlying gnindex json instead of the format in the
* request.
* This allows a GeoJSON to still get the underlying gnindex json.
*/
public static String ACCEPT_OVERRIDE_ATTRIBUTE = "accepts-override";
public static final String[] validContentTypes = {
"application/json", "text/plain", "application/rss+xml"
};
Expand Down Expand Up @@ -745,6 +754,9 @@ private void processResponse(

// TODO: Header can contain a list of ... So get the first which match a processor
String acceptHeader = getAcceptValue(request);
if (request.getAttribute(ACCEPT_OVERRIDE_ATTRIBUTE) != null) {
acceptHeader = request.getAttribute(ACCEPT_OVERRIDE_ATTRIBUTE).toString();
}

boolean isDcatOnItem =
request.getRequestURI().matches(".*/collections/.*/items/.*")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ gn:
responseProcessor: RssResponseProcessorImpl
operations:
- items
- name : gnindex-json
- name : gnindex
mimeType : application/gnindex+json
responseProcessor : JsonUserAndSelectionAwareResponseProcessorImpl
operations :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.fao.geonet.common.search.GnMediaType;
import org.fao.geonet.common.search.SearchConfiguration;
import org.fao.geonet.common.search.SearchConfiguration.Operations;
import org.fao.geonet.domain.Source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,30 @@ public ResponseEntity<Void> collectionsCollectionIdItemsRecordIdGet(
ListUtils.union(MediaTypeUtil.defaultSupportedMediaTypes,
MediaTypeUtil.ldSupportedMediaTypes);
allowedMediaTypes.add(GnMediaType.APPLICATION_GEOJSON);
allowedMediaTypes.add(GnMediaType.APPLICATION_ELASTICJSON);

MediaType mediaType =
mediaTypeUtil.calculatePriorityMediaTypeFromRequest(request, allowedMediaTypes);

if (mediaType.equals(MediaType.APPLICATION_JSON)
|| mediaType.equals(GnMediaType.APPLICATION_GEOJSON)) {
|| mediaType.equals(GnMediaType.APPLICATION_GEOJSON)
|| mediaType.equals(GnMediaType.APPLICATION_ELASTICJSON)) {
try {
String type = mediaType.equals(MediaType.APPLICATION_JSON) ? "json" : "geojson";
String type = null;
if (mediaType.equals(MediaType.APPLICATION_JSON)) {
type = "json";
} else {
if (mediaType.equals(GnMediaType.APPLICATION_GEOJSON)) {
type = "geojson";
} else {
if (mediaType.equals(GnMediaType.APPLICATION_ELASTICJSON)) {
type = "gnindex";
}
}
}

JsonNode recordAsJson = recordService.getRecordAsJson(collectionId, recordId,
request, source, type);
request, source, type);

streamResult(response,
recordAsJson.toPrettyString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public Query buildFromRequest(String collectionId,
*/
private void injectExtraFromRequest(String collectionId, Query result,
Map<String, String[]> parameterMap) {
var queryables = queryablesService.buildQueryables(collectionId)
var queryables = queryablesService.getFullQueryables(collectionId)
.getProperties();

result.setPropValues(new LinkedHashMap<>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void augmentWithQueryables(SearchSourceBuilder sourceBuilder,
}
var boolQuery = (BoolQueryBuilder) mainQuery;

var jsonSchema = queryablesService.buildQueryables(query.getCollectionId());
var jsonSchema = queryablesService.getFullQueryables(query.getCollectionId());

for (var prop : query.getPropValues().entrySet()) {
var jsonProp = jsonSchema.getProperties().get(prop.getKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,27 @@
@Slf4j(topic = "org.fao.geonet.ogcapi.records")
public class QueryablesService {

/**
* build a schema based on collection. It will be based on the underlying elastic index json.
*
* <p>NOTE: these are hard coded at the moment.
*
* @param collectionId which collection
* @return schema based on collection
*/
public JsonSchema buildQueryables(String collectionId) {
/** full schema from queryables.json*/
public static JsonSchema fullJsonSchema;

/** full schema from queryables.json with elastic removed*/
public static JsonSchema truncatedJsonSchema;

static {
fullJsonSchema= readQueryablesJsonSchema();

var js = readQueryablesJsonSchema();
if (js != null && js.getProperties() !=null) {
for (var prop : js.getProperties().values()) {
prop.setxGnElasticPath(null);
}
}
truncatedJsonSchema=js;
}

InputStream is = getClass().getClassLoader().getResourceAsStream("queryables/queryables.json");
public static JsonSchema readQueryablesJsonSchema() {
InputStream is = QueryablesService.class
.getClassLoader().getResourceAsStream("queryables/queryables.json");

try {
String text = new String(is.readAllBytes(), StandardCharsets.UTF_8);
Expand All @@ -52,138 +62,26 @@ public JsonSchema buildQueryables(String collectionId) {
}

/**
* cf. https://docs.ogc.org/DRAFTS/20-004.html
* build a schema based on collection. It will be based on the underlying elastic index json.
*
* <p>The only mandatory one is "id".
* <p>NOTE: these are hard coded at the moment.
*
* @param properties existing set of properties to add to.
* @param collectionId which collection
* @return schema based on collection (without elastic details)
*/
public void addStandardProperties(Map<String, JsonProperty> properties) {

JsonProperty p;
//table 8
p = new JsonProperty(JsonProperty.TypeString, "id",
"A unique record identifier assigned by the server.");
p.setxOgcRole("id");
p.getxGnElasticPath().add(new GnElasticInfo("uuid", ElasticColumnType.KEYWORD));
properties.put("id", p);

p = new JsonProperty(JsonProperty.TypeString, "created",
"The date this record was created in the server.");
p.getxGnElasticPath().add(
new GnElasticInfo("createdDate", ElasticColumnType.DATE, ElasticColumnFormat.NORMAL));
properties.put("created", p);

p = new JsonProperty(JsonProperty.TypeString, "updated",
"The most recent date on which the record was changed.");
p.getxGnElasticPath().add(
new GnElasticInfo("resourceDate.date", ElasticColumnType.DATE, ElasticColumnFormat.NORMAL));
properties.put("updated", p);

//conformsTo -- not in Elastic Index JSON

p = new JsonProperty(JsonProperty.TypeString, "language",
"The language used for textual values (i.e. titles, descriptions, etc.)"
+ " of this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("mainLanguage", ElasticColumnType.KEYWORD));
properties.put("language", p);

p = new JsonProperty(JsonProperty.TypeString, "languages",
"The list of other languages in which this record is available.");
p.getxGnElasticPath().add(
new GnElasticInfo("otherLanguage", ElasticColumnType.KEYWORD));
properties.put("languages", p);

//links -- not in Elastic Index JSON
//linkTemplates -- not in Elastic Index JSON

//table 9

//unclear what this maps to in elastic
p = new JsonProperty(JsonProperty.TypeString, "type",
"The nature or genre of the resource described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("resourceType", ElasticColumnType.KEYWORD));
properties.put("type", p);

p = new JsonProperty(JsonProperty.TypeString, "title",
"A human-readable name given to the resource described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("resourceTitleObject.default", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("resourceTitleObject.lang${lang3iso}", ElasticColumnType.TEXT));
properties.put("title", p);

p = new JsonProperty(JsonProperty.TypeString, "description",
"A free-text description of the resource described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("resourceAbstractObject.default", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("resourceAbstractObject.lang${lang3iso}", ElasticColumnType.TEXT));
properties.put("description", p);

p = new JsonProperty(JsonProperty.TypeString, "geometry",
"A spatial extent associated with the resource described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("geom", ElasticColumnType.GEO));
properties.put("geometry", p);

p = new JsonProperty(JsonProperty.TypeString, "time",
"A temporal extent associated with the resource described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("resourceTemporalDateRange", ElasticColumnType.DATERANGE));
properties.put("time", p);

p = new JsonProperty(JsonProperty.TypeString, "keywords",
"A list of free-form keywords or tags associated with the resource"
+ " described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("tag.default", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("tag.lang${lang3iso}", ElasticColumnType.TEXT));
properties.put("keywords", p);

p = new JsonProperty(JsonProperty.TypeString, "themes",
"A knowledge organization system used to classify the resource"
+ " described by this resource.");
// looks like this index is disabled
p.getxGnElasticPath().add(
new GnElasticInfo("allKeywords.*.keywords.default", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("allKeywords.*.keywords.lang${lang3iso}", ElasticColumnType.TEXT));
properties.put("themes", p);

p = new JsonProperty(JsonProperty.TypeString, "contacts",
"A list of contacts qualified by their role(s) in association to the record"
+ " or the resource described by this record.");
p.getxGnElasticPath().add(
new GnElasticInfo("contact.organisationObject.default", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.organisationObject.lang${lang3iso}", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.address", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.role", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.email", ElasticColumnType.KEYWORD));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.website", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.individual", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.position", ElasticColumnType.TEXT));
p.getxGnElasticPath().add(
new GnElasticInfo("contact.phone", ElasticColumnType.TEXT));
properties.put("contacts", p);

//resourceLanguages -- not in Elastic Index JSON
//externalIds -- not in Elastic Index JSON
//formats -- not in Elastic Index JSON
public JsonSchema buildQueryables(String collectionId) {
return truncatedJsonSchema;
}

//license isn't really easy to search since the iso and ogcapi define it differently

//rights -- not in Elastic Index JSON
/**
* Full version of the queryables - including the elastic details.
*
* @param collectionId which collection
* @return schema based on collection (WITH elastic details)
*/
public JsonSchema getFullQueryables(String collectionId) {
return fullJsonSchema;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package org.fao.geonet.ogcapi.records.service;

import static org.fao.geonet.common.search.ElasticSearchProxy.ACCEPT_OVERRIDE_ATTRIBUTE;
import static org.fao.geonet.common.search.GnMediaType.APPLICATION_ELASTICJSON;
import static org.fao.geonet.ogcapi.records.controller.ItemApiController.EXCEPTION_COLLECTION_ITEM_NOT_FOUND;

import com.fasterxml.jackson.core.JsonFactory;
Expand Down Expand Up @@ -112,7 +114,7 @@ public Map<String, Object> getLinkedServiceRecord(HttpServletRequest request,
try {
var info = getRecordAsJson(mainPortal.getUuid(),
uuid, request, mainPortal,
"json")
APPLICATION_ELASTICJSON.toString())
.get("_source");
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> result = mapper.convertValue(info,
Expand All @@ -135,7 +137,7 @@ public Map<String, Object> getLinkedServiceRecord(HttpServletRequest request,
*
* @param collectionId which collection is the record apart of
* @param recordId which uuid to get
* @param request incomming user request (for security)
* @param request incoming user request (for security)
* @param source from the GN DB "source" table for this collectionId
* @param type what type of record
* @return parsed as a JSON object
Expand All @@ -151,15 +153,28 @@ public JsonNode getRecordAsJson(
String collectionFilter = collectionService.retrieveCollectionFilter(source, true);
String query = recordsEsQueryBuilder.buildQuerySingleRecord(recordId, collectionFilter, null);

String queryResponse = proxy.searchAndGetResult(request.getSession(), request, query, null);
String queryResponse = null;
try {
var accepts = type;
request.setAttribute(ACCEPT_OVERRIDE_ATTRIBUTE,accepts);
queryResponse= proxy.searchAndGetResult(request.getSession(), request, query, null);
}
finally {
request.setAttribute(ACCEPT_OVERRIDE_ATTRIBUTE,null);


}

ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getFactory();
JsonParser parser = factory.createParser(queryResponse);
JsonNode actualObj = mapper.readTree(parser);

JsonNode totalValue =
"json".equals(type)
(APPLICATION_ELASTICJSON.toString().equals(type)
|| (APPLICATION_ELASTICJSON.getSubtype().equals(type))
|| (APPLICATION_ELASTICJSON.getSubtype()
.replace("+json","").equals(type)))
? actualObj.get("hits").get("total").get("value")
: actualObj.get("numberMatched");

Expand All @@ -170,7 +185,10 @@ public JsonNode getRecordAsJson(
request.getLocale()));
}

if ("json".equals(type)) {
if (APPLICATION_ELASTICJSON.toString().equals(type)
|| (APPLICATION_ELASTICJSON.getSubtype().equals(type))
|| (APPLICATION_ELASTICJSON.getSubtype()
.replace("+json","").equals(type))) {
return actualObj.get("hits").get("hits").get(0);
} else {
String elementName = "schema.org".equals(type) ? "dataFeedElement" : "features";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,15 @@ public QueryablesService initQueryablesService(String pname, JsonProperty proper
public JsonSchema buildQueryables(String collectionId) {
return queryables;
}

public JsonSchema getFullQueryables(String collectionId){
return queryables;
}
};




return queryablesService;
}

Expand Down

0 comments on commit db67b86

Please sign in to comment.