Skip to content

Commit

Permalink
initial queryables implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
david-blasby committed Oct 1, 2024
1 parent dad79a6 commit 51fbde4
Show file tree
Hide file tree
Showing 5 changed files with 488 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.fao.geonet.ogcapi.records.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.fao.geonet.ogcapi.records.model.JsonSchema;
import org.fao.geonet.ogcapi.records.service.QueryablesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import springfox.documentation.annotations.ApiIgnore;

/**
* See https://docs.ogc.org/is/19-079r2/19-079r2.html#rc_queryables and
* https://docs.ogc.org/DRAFTS/20-004.html#_queryables_link
*/
@Api(tags = "OGC API Records")
@Controller
@Slf4j(topic = "org.fao.geonet.ogcapi")
public class QueryableApiController {

@Autowired
QueryablesService queryablesService;

/**
* Describe queryables for a collection.
*/
@io.swagger.v3.oas.annotations.Operation(
summary = "Describes queryables for a collection.",
description = "Queryables resource for discovering a list of resource properties with their "
+ "types and constraints that may be used to construct filter expressions"
+ " on a collection of resources.")
@GetMapping(value = "/collections/{collectionId}/queryables",
produces = {MediaType.APPLICATION_JSON_VALUE,
})
@ResponseStatus(HttpStatus.OK)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Describe queryables for a collection.")
})
@ResponseBody
public ResponseEntity<JsonSchema> queryablesForCollection(
@ApiParam(value = "Identifier (name) of a specific collection", required = true)
@PathVariable("collectionId") String collectionId,
@ApiIgnore HttpServletRequest request,
@ApiIgnore HttpServletResponse response,
@ApiIgnore Model model) throws Exception {

var jsonSchema = queryablesService.buildQueryables(collectionId);

return ResponseEntity.ok(jsonSchema);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.fao.geonet.ogcapi.records.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;

/**
* THIS IS SIMPLIFIED - SEE FULL SPECIFICATION.
*
* <p>See the JSON Schema specification.
*/
public class JsonItem {

@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "type")
@XmlElement(name = "type")
public String type;

//---------------------------------------------


public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.fao.geonet.ogcapi.records.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;

/**
* This is for Queryables. Its a json schema. cf https://json-schema.org/draft/2020-12/schema
*
* <p>https://json-schema.org/learn/miscellaneous-examples
*
* <p>example: https://demo.pycsw.org/gisdata/collections/metadata:main/queryables?f=json
*
* <p>THIS IS SIMPLIFIED - SEE FULL SPECIFICATION and JsonItem
*/
public class JsonProperty {

public static final String TypeString = "string";

//----------------------

/**
* https://json-schema.org/draft/2020-12/schema.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "title")
@XmlElement(name = "title")
public String title;

/**
* https://json-schema.org/draft/2020-12/schema.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "type")
@XmlElement(name = "type")
public String type;

/**
* https://json-schema.org/draft/2020-12/schema.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "description")
@XmlElement(name = "description")
public String description;

/**
* cf. https://docs.ogc.org/is/19-079r2/19-079r2.html.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "format")
@XmlElement(name = "format")
public String format;

/**
* cf. https://docs.ogc.org/is/19-079r2/19-079r2.html.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "enum")
@XmlElement(name = "enum")
@com.fasterxml.jackson.annotation.JsonProperty("enum")
public List<String> enumeration;

/**
* cf. https://docs.ogc.org/is/19-079r2/19-079r2.html.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "x-ogc-role")
@XmlElement(name = "x-ogc-role")
@com.fasterxml.jackson.annotation.JsonProperty("x-ogc-role")
public String xxOgcRole;

/**
* cf. https://docs.ogc.org/is/19-079r2/19-079r2.html.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "items")
@XmlElement(name = "items")
public JsonItem items;

//----------------------------------

/**
* builds a minimal JsonProperty (part of json schema).
*
* @param type type of the property
* @param title title of the property
* @param description description of the property
*/
public JsonProperty(String type, String title, String description) {
this.type = type;
this.title = title;
this.description = description;
}

//----------------------------------


public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getFormat() {
return format;
}

public void setFormat(String format) {
this.format = format;
}

public List<String> getEnum() {
return enumeration;
}

public void setEnum(List<String> enumeration) {
this.enumeration = enumeration;
}

public String getxOgcRole() {
return xxOgcRole;
}

public void setxOgcRole(String xxOgcRole) {
this.xxOgcRole = xxOgcRole;
}

public JsonItem getItems() {
return items;
}

public void setItems(JsonItem items) {
this.items = items;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package org.fao.geonet.ogcapi.records.model;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.util.Map;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;

/**
* This is for Queryables. Its a json schema. cf https://json-schema.org/draft/2020-12/schema
*
* <p>example: https://demo.pycsw.org/gisdata/collections/metadata:main/queryables?f=json
*/
public class JsonSchema {

/**
* The property $schema is https://json-schema.org/draft/2020-12/schema.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "$schema")
@XmlElement(name = "$schema")
@com.fasterxml.jackson.annotation.JsonProperty("$schema")
public String schema = "https://json-schema.org/draft/2020-12/schema";

/**
* The type is object and each property is a queryable.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "type")
@XmlElement(name = "type")
public String type = "object";

/**
* The property $id is the URI of the resource without query parameters.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "id")
@XmlElement(name = "id")
public String id;

/**
* The property $id is the URI of the resource without query parameters.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "title")
@XmlElement(name = "title")
public String title = "Queryables for GeoNetwork Collection";

/**
* https://json-schema.org/draft/2020-12/schema.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "description")
@XmlElement(name = "description")
public String description;


/**
* The properties for this schema.
*/
@JsonInclude(Include.NON_EMPTY)
@XmlElementWrapper(name = "properties")
@XmlElement(name = "properties")
public Map<String, JsonProperty> properties;

//----------------------------------------------


public String getSchema() {
return schema;
}

public void setSchema(String schema) {
this.schema = schema;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public Map<String, JsonProperty> getProperties() {
return properties;
}

public void setProperties(Map<String, JsonProperty> properties) {
this.properties = properties;
}
}
Loading

0 comments on commit 51fbde4

Please sign in to comment.