From f3d929f7d64fd6e5afab19d5ccb4a4e301067485 Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Thu, 20 Apr 2023 09:26:53 -0700 Subject: [PATCH 1/2] implement /product-properties endpoint --- model/swagger.yml | 26 ++++++++++-- .../registry/controller/GetIndexHandler.java | 42 +++++++++++++++++++ .../SwaggerJavaProductsTransmuter.java | 12 +++++- .../controller/SwaggerJavaTransmuter.java | 14 +++++-- 4 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java diff --git a/model/swagger.yml b/model/swagger.yml index 0ec4c347..cec1ccbc 100644 --- a/model/swagger.yml +++ b/model/swagger.yml @@ -10,13 +10,13 @@ info: license: name: Apache 2.0 url: 'http://www.apache.org/licenses/LICENSE-2.0.html' - + tags: - name: 1. all products description: search any classe of product and resolve product's identifiers - name: 2. product references description: explore the product hierarchy - - name: 3. by product classes + - name: 3. by product classes description: search by class of product, bundles, collections, ... - name: 4. deprecated description: end-points which should not be used anymore @@ -24,7 +24,7 @@ tags: externalDocs: description: User's Guide url: https://nasa-pds.github.io/pds-api/guides/search.html - + servers: - url: https://pds.nasa.gov/api/registry/1 description: production server @@ -311,6 +311,26 @@ paths: - $ref: "#/components/parameters/Sort" - $ref: "#/components/parameters/Start" + /product-properties: + get: + tags: + - 1. all products + summary: | + return a list of all possible searchable metadata fields for products published in the registry + operationId: product-properties-list + responses: + '200': + $ref: "#/components/responses/Plural" + '400': + $ref: "#/components/responses/Error" + '404': + $ref: "#/components/responses/Error" + '500': + $ref: "#/components/responses/Error" + '501': + $ref: "#/components/responses/Error" + parameters: [] + /products/{identifier}: get: tags: diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java b/service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java new file mode 100644 index 00000000..ba120eb8 --- /dev/null +++ b/service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java @@ -0,0 +1,42 @@ +package gov.nasa.pds.api.registry.controller; + +import java.io.IOException; +import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set; + +import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature;import org.opensearch.client.RequestOptions;import org.opensearch.client.RestHighLevelClient;import org.opensearch.client.indices.GetIndexRequest; +import org.opensearch.client.indices.GetIndexResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import gov.nasa.pds.api.registry.ControlContext; +import gov.nasa.pds.api.registry.UserContext; + +class GetIndexHandler implements EndpointHandler { + private String indexName; + + public GetIndexHandler(String indexName) { + if (indexName == null || indexName.strip().equals("")) { + throw new IllegalArgumentException("Cannot initialize GetIndexHandler with null/empty index name"); + } + this.indexName = indexName; + } + + @Override + public ResponseEntity transmute(ControlContext control, UserContext _ignored) + throws IOException { + + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); + + GetIndexRequest req = new GetIndexRequest(indexName); + RestHighLevelClient client = control.getConnection().getRestHighLevelClient();; + GetIndexResponse response = client.indices().get(req, RequestOptions.DEFAULT); + JsonNode content = mapper.valueToTree(response.getMappings().get(indexName).getSourceAsMap()).get("properties"); + + String propertiesAsString = mapper.writeValueAsString(content); + + return new ResponseEntity<>(propertiesAsString, HttpStatus.OK); + } + +} diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java index 15d94bad..2679ef1b 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Optional; +import gov.nasa.pds.api.base.ProductPropertiesApi; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import org.springframework.http.ResponseEntity; @@ -12,7 +13,7 @@ import gov.nasa.pds.api.registry.model.ProductVersionSelector; abstract class SwaggerJavaProductsTransmuter extends SwaggerJavaClassesTransmuter - implements ControlContext, ProductsApi, ClassesApi { + implements ControlContext, ProductsApi, ClassesApi, ProductPropertiesApi { public Optional getRequest() { return Optional.empty(); @@ -112,4 +113,13 @@ public ResponseEntity selectByLidvidLatest(String identifier, return this.processs(new Standard(), this.uriParametersBuilder.setIdentifier(identifier) .setFields(fields).setVersion(ProductVersionSelector.LATEST).build()); } + + @Override + public ResponseEntity productPropertiesList() { + + String registryIndexName = this.getConnection().getRegistryIndex(); + EndpointHandler handler = new GetIndexHandler(registryIndexName); + URIParameters uriParameters = this.uriParametersBuilder.build(); + return this.processs(handler, uriParameters); + } } diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java index 5a44bc7b..d1fe8c06 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.util.List; +import gov.nasa.pds.api.base.ProductPropertiesApi; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import org.antlr.v4.runtime.NoViableAltException; @@ -31,7 +32,7 @@ @Controller public class SwaggerJavaTransmuter extends SwaggerJavaDeprecatedTransmuter - implements ControlContext, BundlesApi, CollectionsApi, ClassesApi, ProductsApi { + implements ControlContext, BundlesApi, CollectionsApi, ClassesApi, ProductsApi, ProductPropertiesApi { private static final Logger log = LoggerFactory.getLogger(SwaggerJavaTransmuter.class); @@ -430,9 +431,16 @@ public ResponseEntity classMembersMembersVers(String propertyClass, Stri @Override public ResponseEntity classMembersVers(String propertyClass, String identifier, - String versions, @Valid List fields, @Min(0) @Valid Integer limit, - @Valid List sort, @Min(0) @Valid Integer start) { + String versions, @Valid List fields, @Min(0) @Valid Integer limit, + @Valid List sort, @Min(0) @Valid Integer start) { // TODO Auto-generated method stub return super.classMembersVers(propertyClass, identifier, versions, fields, limit, sort, start); } + + @Override + public ResponseEntity productPropertiesList() { + // TODO Auto-generated method stub + return super.productPropertiesList(); + } + } From 5120fad8d36fff4f06c125353893e2256f6ca1f1 Mon Sep 17 00:00:00 2001 From: Alex Dunn Date: Tue, 25 Apr 2023 17:19:52 -0700 Subject: [PATCH 2/2] rework properties endpoint significantly --- model/swagger.yml | 24 +++++- .../registry/controller/GetIndexHandler.java | 42 ----------- .../SwaggerJavaProductsTransmuter.java | 74 +++++++++++++++++-- .../controller/SwaggerJavaTransmuter.java | 8 +- 4 files changed, 92 insertions(+), 56 deletions(-) delete mode 100644 service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java diff --git a/model/swagger.yml b/model/swagger.yml index cec1ccbc..6e776d68 100644 --- a/model/swagger.yml +++ b/model/swagger.yml @@ -311,7 +311,7 @@ paths: - $ref: "#/components/parameters/Sort" - $ref: "#/components/parameters/Start" - /product-properties: + /properties: get: tags: - 1. all products @@ -320,7 +320,7 @@ paths: operationId: product-properties-list responses: '200': - $ref: "#/components/responses/Plural" + $ref: "#/components/responses/PropertiesList" '400': $ref: "#/components/responses/Error" '404': @@ -1304,6 +1304,26 @@ components: text/xml: schema: $ref: '#/components/schemas/pdsProducts' + PropertiesList: + description: An array of all searchable properties of products in the registry. + content: + "*": + schema: + type: array + items: + type: object + properties: + property: + type: string + type: + type: string + enum: + - "string" + - "integer" + - "float" + - "boolean" + - "timestamp" + - "unsupported" Singular: description: Successful request content: diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java b/service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java deleted file mode 100644 index ba120eb8..00000000 --- a/service/src/main/java/gov/nasa/pds/api/registry/controller/GetIndexHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -package gov.nasa.pds.api.registry.controller; - -import java.io.IOException; -import java.util.Arrays;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set; - -import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature;import org.opensearch.client.RequestOptions;import org.opensearch.client.RestHighLevelClient;import org.opensearch.client.indices.GetIndexRequest; -import org.opensearch.client.indices.GetIndexResponse; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import gov.nasa.pds.api.registry.ControlContext; -import gov.nasa.pds.api.registry.UserContext; - -class GetIndexHandler implements EndpointHandler { - private String indexName; - - public GetIndexHandler(String indexName) { - if (indexName == null || indexName.strip().equals("")) { - throw new IllegalArgumentException("Cannot initialize GetIndexHandler with null/empty index name"); - } - this.indexName = indexName; - } - - @Override - public ResponseEntity transmute(ControlContext control, UserContext _ignored) - throws IOException { - - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); - - GetIndexRequest req = new GetIndexRequest(indexName); - RestHighLevelClient client = control.getConnection().getRestHighLevelClient();; - GetIndexResponse response = client.indices().get(req, RequestOptions.DEFAULT); - JsonNode content = mapper.valueToTree(response.getMappings().get(indexName).getSourceAsMap()).get("properties"); - - String propertiesAsString = mapper.writeValueAsString(content); - - return new ResponseEntity<>(propertiesAsString, HttpStatus.OK); - } - -} diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java index 2679ef1b..1b8c3f45 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaProductsTransmuter.java @@ -1,10 +1,23 @@ package gov.nasa.pds.api.registry.controller; +import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; -import gov.nasa.pds.api.base.ProductPropertiesApi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import gov.nasa.pds.api.base.PropertiesApi; +import gov.nasa.pds.model.ProductPropertiesList200ResponseInner; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; +import org.opensearch.client.RequestOptions; +import org.opensearch.client.RestHighLevelClient; +import org.opensearch.client.indices.GetIndexRequest; +import org.opensearch.client.indices.GetIndexResponse; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.context.request.NativeWebRequest; import gov.nasa.pds.api.base.ClassesApi; @@ -13,7 +26,7 @@ import gov.nasa.pds.api.registry.model.ProductVersionSelector; abstract class SwaggerJavaProductsTransmuter extends SwaggerJavaClassesTransmuter - implements ControlContext, ProductsApi, ClassesApi, ProductPropertiesApi { + implements ControlContext, ProductsApi, ClassesApi, PropertiesApi { public Optional getRequest() { return Optional.empty(); @@ -115,11 +128,56 @@ public ResponseEntity selectByLidvidLatest(String identifier, } @Override - public ResponseEntity productPropertiesList() { - - String registryIndexName = this.getConnection().getRegistryIndex(); - EndpointHandler handler = new GetIndexHandler(registryIndexName); - URIParameters uriParameters = this.uriParametersBuilder.build(); - return this.processs(handler, uriParameters); + public ResponseEntity> productPropertiesList() { + + try { + String registryIndexName = this.getConnection().getRegistryIndex(); + + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); + + GetIndexRequest req = new GetIndexRequest(registryIndexName); + RestHighLevelClient client = this.getConnection().getRestHighLevelClient(); + GetIndexResponse response = client.indices().get(req, RequestOptions.DEFAULT); + + JsonNode content = + mapper + .valueToTree(response.getMappings().get(registryIndexName).getSourceAsMap()) + .get("properties"); + + Map displayTypesByDbType = + Map.of( + "keyword", "string", + "text", "string", + "date", "timestamp", + "integer", "integer", + "long", "integer", + "float", "float", + "double", "float"); + + List results = new ArrayList<>(); + content + .fieldNames() + .forEachRemaining( + (String propertyName) -> { + ProductPropertiesList200ResponseInner propertyElement = + new ProductPropertiesList200ResponseInner(); + + propertyElement.setProperty(propertyName); + + String rawType = content.get(propertyName).get("type").asText(); + String displayType = displayTypesByDbType.getOrDefault(rawType, "unsupported"); + ProductPropertiesList200ResponseInner.TypeEnum enumType = + ProductPropertiesList200ResponseInner.TypeEnum.fromValue(displayType); + propertyElement.setType(enumType); + + results.add(propertyElement); + }); + + return new ResponseEntity<>(results, HttpStatus.OK); + } catch (IOException err) { + log.error("SwaggerJavaProductsTransmuter.productPropertiesList() failed", err); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } } } diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java index d1fe8c06..b594478c 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/controller/SwaggerJavaTransmuter.java @@ -2,7 +2,8 @@ import java.io.IOException; import java.util.List; -import gov.nasa.pds.api.base.ProductPropertiesApi; +import gov.nasa.pds.api.base.PropertiesApi; +import gov.nasa.pds.model.ProductPropertiesList200ResponseInner; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import org.antlr.v4.runtime.NoViableAltException; @@ -27,12 +28,11 @@ import gov.nasa.pds.api.registry.exceptions.NothingFoundException; import gov.nasa.pds.api.registry.exceptions.UnknownGroupNameException; import gov.nasa.pds.api.registry.model.ErrorMessageFactory; -import gov.nasa.pds.model.ErrorMessage; import gov.nasa.pds.api.registry.model.identifiers.LidVidUtils; @Controller public class SwaggerJavaTransmuter extends SwaggerJavaDeprecatedTransmuter - implements ControlContext, BundlesApi, CollectionsApi, ClassesApi, ProductsApi, ProductPropertiesApi { + implements ControlContext, BundlesApi, CollectionsApi, ClassesApi, ProductsApi, PropertiesApi { private static final Logger log = LoggerFactory.getLogger(SwaggerJavaTransmuter.class); @@ -438,7 +438,7 @@ public ResponseEntity classMembersVers(String propertyClass, String iden } @Override - public ResponseEntity productPropertiesList() { + public ResponseEntity> productPropertiesList() { // TODO Auto-generated method stub return super.productPropertiesList(); }