From 1568eaa8a025c3eb07e254eb8fd7ad59e050f3ac Mon Sep 17 00:00:00 2001 From: tariqksoliman Date: Wed, 26 Jun 2024 17:24:02 -0700 Subject: [PATCH 1/6] #472 /products/{id}/tools Part 1 --- model/pom.xml | 173 +++---- model/swagger.yml | 451 +++++++++--------- service/cross-links.json | 21 + service/for | 0 service/pom.xml | 402 ++++++++-------- .../controllers/ProductsController.java | 40 +- .../api/registry/model/tools/CrossLinks.java | 198 ++++++++ .../model/tools/CrossLinksLoader.java | 34 ++ service/unittests.txt | 0 9 files changed, 810 insertions(+), 509 deletions(-) create mode 100644 service/cross-links.json create mode 100644 service/for create mode 100644 service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java create mode 100644 service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java create mode 100644 service/unittests.txt diff --git a/model/pom.xml b/model/pom.xml index 5ce908a2..cfd987a7 100644 --- a/model/pom.xml +++ b/model/pom.xml @@ -30,7 +30,9 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 gov.nasa.pds @@ -51,37 +53,37 @@ - - org.openapitools - openapi-generator-maven-plugin - - 6.3.0 - - - - generate - - - ${project.basedir}/swagger.yml - spring - true + + org.openapitools + openapi-generator-maven-plugin + + 6.3.0 + + + + generate + + + ${project.basedir}/swagger.yml + spring + true true - - src/main/java - joda - springdoc - apache-2 - gov.nasa.pds.model - gov.nasa.pds.api.base - false - false - true - true - - - - - + + src/main/java + joda + springdoc + apache-2 + gov.nasa.pds.model + gov.nasa.pds.api.base + false + false + true + true + + + + + @@ -101,17 +103,17 @@ true - + - - - + + + org.springframework.boot spring-boot-starter-web - - - + + + org.springframework.boot spring-boot-starter-thymeleaf @@ -121,40 +123,40 @@ org.springframework.boot spring-boot-starter-test - + org.springframework.boot spring-boot-autoconfigure - + junit junit - - - jakarta.servlet - jakarta.servlet-api - 6.0.0 - provided - + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided + - - - jakarta.annotation - jakarta.annotation-api - 2.1.1 - + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + - - - jakarta.validation - jakarta.validation-api - 3.0.2 - + + + jakarta.validation + jakarta.validation-api + 3.0.2 + @@ -191,10 +193,10 @@ - org.openapitools - jackson-databind-nullable - 0.2.4 - + org.openapitools + jackson-databind-nullable + 0.2.4 + @@ -204,7 +206,6 @@ - org.threeten @@ -213,18 +214,18 @@ - - io.swagger.core.v3 - swagger-annotations - 2.2.8 - + + io.swagger.core.v3 + swagger-annotations + 2.2.8 + - - - io.swagger.core.v3 - swagger-models - 2.2.8 - + + + io.swagger.core.v3 + swagger-models + 2.2.8 + org.junit.jupiter @@ -232,17 +233,17 @@ - + - - - org.springframework.boot - spring-boot-dependencies - 3.0.4 - pom - import - + + + org.springframework.boot + spring-boot-dependencies + 3.0.4 + pom + import + - + - + \ No newline at end of file diff --git a/model/swagger.yml b/model/swagger.yml index 02723de7..26289648 100644 --- a/model/swagger.yml +++ b/model/swagger.yml @@ -4,12 +4,12 @@ info: Registry API enabling advanced search on PDS data and metadata. The API provides end-points to search for bundles, collections and any PDS products with advanced search queries. It also enables to browse the archive hierarchically downward (e.g. collection/s products) or upward (e.g. bundles containing a product). version: 1.3.0 title: PDS Registry Search API - termsOfService: 'http://pds.nasa.gov' + termsOfService: "http://pds.nasa.gov" contact: email: pds-operator@jpl.nasa.gov license: name: Apache 2.0 - url: 'http://www.apache.org/licenses/LICENSE-2.0.html' + url: "http://www.apache.org/licenses/LICENSE-2.0.html" tags: - name: 1. all products @@ -23,10 +23,9 @@ tags: - name: 5. all docs description: access to opensearch API, for experts only - externalDocs: - description: User's Guide - url: https://nasa-pds.github.io/pds-api/guides/search.html + description: User's Guide + url: https://nasa-pds.github.io/pds-api/guides/search.html servers: - url: https://pds.nasa.gov/api/registry/1 @@ -41,27 +40,27 @@ paths: returns payload of system health information. Detection of any fatal issues results in a non-200 response. The primary intention of this endpoint is to provide an accurate assessment of the service to determine if ECS/Fargate should instantiate a new instance of the task. operationId: healthcheck responses: - '200': + "200": description: The system checked out as healthy, returning a JSON payload of results content: "*": schema: type: object additionalProperties: true - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '418': + "418": description: The system did not check out as healthy, returning a JSON payload of results, including error messages indicating the source(s) of the failure(s) content: "*": schema: type: object additionalProperties: true - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" /classes: get: @@ -71,7 +70,7 @@ paths: returns a list of the available PDS product class at this API. This is not all of the PDS product class available in the database, but simply the names that can be used in the /classes/{class} endpoints. operationId: classes responses: - '200': + "200": description: Successful response is always a JSON list of the available class names content: "*": @@ -79,31 +78,31 @@ paths: type: array items: type: string - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" /classes/{class}: get: tags: - - 3. by product classes + - 3. by product classes summary: | returns all PDS products of the given PDS product class that meet all given constraints. operationId: class-list responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -129,7 +128,7 @@ paths: schema: type: string responses: - '200': + "200": description: Successful request content: "*": @@ -137,7 +136,7 @@ paths: type: object parameters: - $ref: "#/components/parameters/Indices" - /products: + /products: get: tags: - 1. all products @@ -145,15 +144,15 @@ paths: search on all PDS data products, including bundles, collections, documentation, context and observational products. operationId: product-list responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -171,15 +170,15 @@ paths: returns one PDS Product with the identifier selected from all PDS Products, including bundles, collections, data, documentation, context and observational products. See identifier for details on how it determines what is returned. operationId: select-by-lidvid responses: - '200': + "200": $ref: "#/components/responses/Singular" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -193,15 +192,15 @@ paths: returns one PDS Product with the identifier selected from all PDS Products. See identifier for details on how it determines what is returned. operationId: select-by-lidvid-latest responses: - '200': + "200": $ref: "#/components/responses/Singular" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -217,15 +216,15 @@ paths: note: if given a lidvid, it will be translated to a lid operationId: select-by-lidvid-all responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -234,6 +233,26 @@ paths: - $ref: "#/components/parameters/Sort" - $ref: "#/components/parameters/SearchAfter" + /products/{identifier}/tools: + get: + tags: + - 1. all products + summary: | + for the given product, returns deep links to all tools that support the display of that product + operationId: product-cross-links + responses: + "200": + $ref: "#/components/responses/Singular" + "400": + $ref: "#/components/responses/Error" + "404": + $ref: "#/components/responses/Error" + "500": + $ref: "#/components/responses/Error" + "501": + $ref: "#/components/responses/Error" + parameters: + - $ref: "#/components/parameters/Identifier" /properties: get: @@ -243,19 +262,18 @@ paths: return a list of all possible searchable metadata fields for products published in the registry operationId: product-properties-list responses: - '200': + "200": $ref: "#/components/responses/PropertiesList" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: [] - /products/{identifier}/members: get: tags: @@ -264,15 +282,15 @@ paths: returns all of the members of the given lid/lidvid operationId: product-members responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -288,15 +306,15 @@ paths: returns all of the members of the given lid/lidvid operationId: product-members-vers responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -313,15 +331,15 @@ paths: returns all of the members of the members of the given lid/lidvid operationId: product-members-members responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -337,15 +355,15 @@ paths: returns all of the members of the members of the given lid/lidvid operationId: product-members-members-vers responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -362,15 +380,15 @@ paths: returns one or more PDS Products that have the given PDS lid/lidvid as a member. operationId: product-member-of responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -386,15 +404,15 @@ paths: returns one or more PDS Products that have the given PDS lid/lidvid as a member. operationId: product-member-of-vers responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -411,15 +429,15 @@ paths: returns one or more PDS Products that have the given PDS lid/lidvid as a member of its members. operationId: product-member-of-of responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -435,15 +453,15 @@ paths: returns one or more PDS Products that have the given PDS lid/lidvid as a member of its members. operationId: product-member-of-of-vers responses: - '200': + "200": $ref: "#/components/responses/Plural" - '400': + "400": $ref: "#/components/responses/Error" - '404': + "404": $ref: "#/components/responses/Error" - '500': + "500": $ref: "#/components/responses/Error" - '501': + "501": $ref: "#/components/responses/Error" parameters: - $ref: "#/components/parameters/Fields" @@ -453,7 +471,6 @@ paths: - $ref: "#/components/parameters/SearchAfter" - $ref: "#/components/parameters/Versions" - components: parameters: Fields: @@ -480,7 +497,7 @@ components: required: true schema: type: string - enum: [any,bundles,collections,documents,observationals] + enum: [any, bundles, collections, documents, observationals] Indices: name: indices in: query @@ -581,7 +598,7 @@ components: required: true schema: type: string - enum: [all,latest] + enum: [all, latest] responses: Error: description: Unsuccessful request @@ -591,34 +608,34 @@ components: type: object "*/*": schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" application/csv: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" application/json: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" application/kvp+json: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" application/vnd.nasa.pds.pds4+json: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" application/vnd.nasa.pds.pds4+xml: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" application/xml: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" text/csv: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" text/html: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" text/xml: schema: - $ref: '#/components/schemas/errorMessage' + $ref: "#/components/schemas/errorMessage" Plural: description: Successful request content: @@ -627,34 +644,34 @@ components: type: object "*/*": schema: - $ref: '#/components/schemas/pdsProducts' + $ref: "#/components/schemas/pdsProducts" application/csv: schema: - $ref: '#/components/schemas/wyriwygProducts' + $ref: "#/components/schemas/wyriwygProducts" application/json: schema: - $ref: '#/components/schemas/pdsProducts' + $ref: "#/components/schemas/pdsProducts" application/kvp+json: schema: - $ref: '#/components/schemas/wyriwygProducts' + $ref: "#/components/schemas/wyriwygProducts" application/vnd.nasa.pds.pds4+json: schema: - $ref: '#/components/schemas/pds4Products' + $ref: "#/components/schemas/pds4Products" application/vnd.nasa.pds.pds4+xml: schema: - $ref: '#/components/schemas/pds4Products' + $ref: "#/components/schemas/pds4Products" application/xml: schema: - $ref: '#/components/schemas/pdsProducts' + $ref: "#/components/schemas/pdsProducts" text/csv: schema: - $ref: '#/components/schemas/wyriwygProducts' + $ref: "#/components/schemas/wyriwygProducts" text/html: schema: - $ref: '#/components/schemas/pdsProducts' + $ref: "#/components/schemas/pdsProducts" text/xml: schema: - $ref: '#/components/schemas/pdsProducts' + $ref: "#/components/schemas/pdsProducts" PropertiesList: description: An array of all searchable properties of products in the registry. content: @@ -663,19 +680,19 @@ components: type: object "*/*": schema: - $ref: '#/components/schemas/propertiesList' + $ref: "#/components/schemas/propertiesList" application/json: schema: - $ref: '#/components/schemas/propertiesList' + $ref: "#/components/schemas/propertiesList" application/xml: schema: - $ref: '#/components/schemas/propertiesList' + $ref: "#/components/schemas/propertiesList" text/html: schema: - $ref: '#/components/schemas/propertiesList' + $ref: "#/components/schemas/propertiesList" text/xml: schema: - $ref: '#/components/schemas/propertiesList' + $ref: "#/components/schemas/propertiesList" Singular: description: Successful request content: @@ -684,34 +701,34 @@ components: type: object "*/*": schema: - $ref: '#/components/schemas/pdsProduct' + $ref: "#/components/schemas/pdsProduct" application/csv: schema: - $ref: '#/components/schemas/wyriwygProduct' + $ref: "#/components/schemas/wyriwygProduct" application/json: schema: - $ref: '#/components/schemas/pdsProduct' + $ref: "#/components/schemas/pdsProduct" application/kvp+json: schema: - $ref: '#/components/schemas/wyriwygProduct' + $ref: "#/components/schemas/wyriwygProduct" application/vnd.nasa.pds.pds4+json: schema: - $ref: '#/components/schemas/pds4Product' + $ref: "#/components/schemas/pds4Product" application/vnd.nasa.pds.pds4+xml: schema: - $ref: '#/components/schemas/pds4Product' + $ref: "#/components/schemas/pds4Product" application/xml: schema: - $ref: '#/components/schemas/pdsProduct' + $ref: "#/components/schemas/pdsProduct" text/csv: - schema: - $ref: '#/components/schemas/wyriwygProduct' + schema: + $ref: "#/components/schemas/wyriwygProduct" text/html: - schema: - $ref: '#/components/schemas/pdsProduct' + schema: + $ref: "#/components/schemas/pdsProduct" text/xml: schema: - $ref: '#/components/schemas/pdsProduct' + $ref: "#/components/schemas/pdsProduct" schemas: propertiesList: type: array @@ -735,126 +752,126 @@ components: q: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" hits: description: total number of matching results. -1 indicates an excessive amount of resource required to compute it type: integer xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" took: description: Number of milliseconds it "took" to do request type: integer xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" search_after: type: array items: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" limit: type: integer xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" sort: type: array items: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" properties: type: array items: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" pdsProduct: type: object description: default PDS product description format for the API. required: - - id - - metadata + - id + - metadata properties: id: type: string description: identifier lidvid of the collection xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" type: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" title: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" description: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" start_date_time: type: string description: start date time of the observations in ISO8601 xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" stop_date_time: type: string description: stop date time of the observations in ISO8601 xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" investigations: type: array description: list of missions or observing campaigns which produced the data items: - $ref: '#/components/schemas/reference' + $ref: "#/components/schemas/reference" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" observing_system_components: type: array description: list of instruments or platforms generating the data items: - $ref: '#/components/schemas/reference' + $ref: "#/components/schemas/reference" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" targets: type: array description: list of targets or feature of interest the observation. items: - $ref: '#/components/schemas/reference' + $ref: "#/components/schemas/reference" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" metadata: - $ref: '#/components/schemas/metadata' + $ref: "#/components/schemas/metadata" properties: type: object description: propertie's values extracted from pds4 model, as a dictionnary, syntax for property name is {namespace}:{property}[{namespace}:{property}]* additionalProperties: - $ref: '#/components/schemas/propertyArrayValues' + $ref: "#/components/schemas/propertyArrayValues" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" pdsProducts: type: object required: @@ -862,10 +879,10 @@ components: - data properties: summary: - $ref: '#/components/schemas/summary' + $ref: "#/components/schemas/summary" data: items: - $ref: '#/components/schemas/pdsProduct' + $ref: "#/components/schemas/pdsProduct" wyriwygProduct: type: object description: minimalistic description of a pds product with only the key value pairs requested by the user (what you request is what you get) @@ -889,56 +906,56 @@ components: - data properties: summary: - $ref: '#/components/schemas/summary' + $ref: "#/components/schemas/summary" data: items: - $ref: '#/components/schemas/wyriwygProduct' + $ref: "#/components/schemas/wyriwygProduct" propertyArrayValues: type: array items: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" reference: type: object description: object describing a reference to a different product. TODO The properties should be defined by a standard (xlink, json-ld) to be chosen required: - - id + - id properties: title: type: string description: name to display for the external reference xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" id: type: string description: external reference, here lidvid urn xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" href: type: string description: external reference url of the current reference resolvable by the current API server, http://pds.nasa.gov/api/products/urn:nasa... xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" type: type: string description: type of the external reference, can be displayed as an icon for example xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" description: type: string description: longer description for the external reference, can be displayed in a tooltip xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" metadata: type: object required: @@ -947,31 +964,31 @@ components: archive_status: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" creation_date_time: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" label_url: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" update_date_time: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" version: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" errorMessage: type: object required: @@ -981,20 +998,20 @@ components: request: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" message: type: string xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" xml: - prefix: 'pds_api' - namespace: 'http://pds.nasa.gov/api' + prefix: "pds_api" + namespace: "http://pds.nasa.gov/api" example: { - request: 'https://pds.nasa.gov/api/1.0/collections?q=mission qt 12', - message: 'query operator gt not supported on field mission' + request: "https://pds.nasa.gov/api/1.0/collections?q=mission qt 12", + message: "query operator gt not supported on field mission", } pds4Product: type: object @@ -1006,7 +1023,7 @@ components: type: string description: LIDVID metadata: - $ref: '#/components/schemas/pds4Metadata' + $ref: "#/components/schemas/pds4Metadata" pds4: type: object description: PDS4 JSON @@ -1017,10 +1034,10 @@ components: - data properties: summary: - $ref: '#/components/schemas/summary' + $ref: "#/components/schemas/summary" data: items: - $ref: '#/components/schemas/pds4Product' + $ref: "#/components/schemas/pds4Product" pds4Metadata: type: object properties: diff --git a/service/cross-links.json b/service/cross-links.json new file mode 100644 index 00000000..876a3d38 --- /dev/null +++ b/service/cross-links.json @@ -0,0 +1,21 @@ +{ + "tools": [ + { + "name": "analysts_notebook", + "base": "https://an.rsl.wustl.edu/{mission}/AN/an3.aspx?it=B1&ii={filenameWithoutFileExtension}", + "description": "description", + "supportsLinksFrom": ["atlas", "astria"], + "aliases": [ + { + "field": "mission", + "alias": "m20", + "from": ["mars_2020", "m2020", "mars2020", "Mars2020"] + } + ], + "reject": [ + { "field": "uri", "match": "/*mars2020_helicam*/" }, + { "field": "uri", "match": "/*mars2020_imgops*/" } + ] + } + ] +} diff --git a/service/for b/service/for new file mode 100644 index 00000000..e69de29b diff --git a/service/pom.xml b/service/pom.xml index a8bd2a67..e226fc9e 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -30,7 +30,9 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 gov.nasa.pds @@ -58,133 +60,133 @@ - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot-version} - - - - repackage - - - - - gov.nasa.pds.api.registry.SpringBootMain - nasapds/registry-api-service - JAR - - + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-version} + + + + repackage + + + + + gov.nasa.pds.api.registry.SpringBootMain + nasapds/registry-api-service + JAR + + 17 -XX:MaxDirectMemorySize=1G - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.1.1 - - - bin-release - package - - single - - - true - - src/main/assembly/tar-assembly.xml - src/main/assembly/zip-assembly.xml - - - jar-with-dependencies - - - - - - posix - - + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.1 + + + bin-release + package + + single + + + true + + src/main/assembly/tar-assembly.xml + src/main/assembly/zip-assembly.xml + + + jar-with-dependencies + + + + + + posix + + org.apache.maven.plugins maven-compiler-plugin - com.iluwatar.urm - urm-maven-plugin - 2.0.0 - - ${project.basedir}/target - - gov.nasa.pds.api.registry - - - - true - false - mermaid - - jar-with-dependencies - - - - - process-classes - - map - - - - + com.iluwatar.urm + urm-maven-plugin + 2.0.0 + + ${project.basedir}/target + + gov.nasa.pds.api.registry + + + + true + false + mermaid + + jar-with-dependencies + + + + + process-classes + + map + + + + - + - + org.springframework.boot spring-boot-starter-web - + - org.springframework.boot - spring-boot-starter-actuator + org.springframework.boot + spring-boot-starter-actuator - org.springframework.data - spring-data-commons - + org.springframework.data + spring-data-commons + - + org.springdoc springdoc-openapi-starter-webmvc-ui 2.0.4 - + - - - org.springdoc - springdoc-openapi-starter-common - 2.0.4 - + + + org.springdoc + springdoc-openapi-starter-common + 2.0.4 + - + org.springframework.boot spring-boot-starter-thymeleaf - - io.swagger.core.v3 - swagger-core - 2.2.8 - + + io.swagger.core.v3 + swagger-core + 2.2.8 + @@ -193,8 +195,8 @@ spring-boot-autoconfigure - - + - - - jakarta.validation - jakarta.validation-api - 3.0.2 - - - - - jakarta.annotation - jakarta.annotation-api - 2.1.1 - + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + @@ -310,40 +312,40 @@ 4.11.1 - - - org.opensearch.client - opensearch-java - 2.10.1 - + + + org.opensearch.client + opensearch-java + 2.10.1 + - - - org.apache.httpcomponents.client5 - httpclient5 - - 5.3.1 - - - + + + org.apache.httpcomponents.client5 + httpclient5 + + 5.3.1 + - - org.apache.httpcomponents.core5 - httpcore5 - 5.2.4 - + + + org.apache.httpcomponents.core5 + httpcore5 + 5.2.4 + - - - org.apache.httpcomponents.core5 - httpcore5-h2 - 5.2.4 - - - - + + org.apache.httpcomponents.core5 + httpcore5-h2 + 5.2.4 + + + + + - - - software.amazon.awssdk - apache-client - 2.25.21 - - + software.amazon.awssdk apache-client 2.25.21 - - - - software.amazon.awssdk - regions - 2.25.21 - - - - - - - software.amazon.awssdk - auth - 2.25.21 - - - - com.amazonaws - aws-java-sdk-core - 1.12.688 - - - + + software.amazon.awssdk + apache-client + 2.25.21 + + + + + software.amazon.awssdk + regions + 2.25.21 + + + + + + software.amazon.awssdk + auth + 2.25.21 + + + + + com.amazonaws + aws-java-sdk-core + 1.12.688 + + - - + + + org.opensearch.client opensearch-rest-client 2.12.0 - + org.opensearch.client opensearch-rest-high-level-client @@ -405,7 +406,6 @@ - org.apache.httpcomponents @@ -419,44 +419,42 @@ commons-collections4 4.2 - + org.springframework.boot spring-boot-starter-test - - junit - junit - + + junit + junit + - - org.junit.jupiter - junit-jupiter-engine - 5.7.0 - test + org.junit.jupiter + junit-jupiter-engine + 5.7.0 + test - org.mockito - mockito-core - 3.6.28 - test + org.mockito + mockito-core + 3.6.28 + test - - - - + + org.springframework.boot spring-boot-starter-validation @@ -474,15 +472,15 @@ guava 32.0.0-jre - + - - jakarta.servlet - jakarta.servlet-api - 6.0.0 - provided - - + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided + + @@ -497,4 +495,4 @@ - + \ No newline at end of file diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java b/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java index 7910a961..d2118473 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java @@ -2,6 +2,7 @@ import java.lang.reflect.InvocationTargetException; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -16,6 +17,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; @@ -35,10 +37,11 @@ import gov.nasa.pds.api.registry.model.api_responses.RawMultipleProductResponse; import gov.nasa.pds.api.registry.model.api_responses.WyriwygBusinessObject; import gov.nasa.pds.api.registry.model.identifiers.PdsProductIdentifier; +import gov.nasa.pds.api.registry.model.tools.CrossLinksLoader; +import gov.nasa.pds.api.registry.model.tools.CrossLinks; import gov.nasa.pds.api.registry.search.RegistrySearchRequestBuilder; - @Controller public class ProductsController implements ProductsApi { @@ -50,6 +53,8 @@ public class ProductsController implements ProductsApi { private final ObjectMapper objectMapper; private OpenSearchClient openSearchClient; private SearchRequest presetSearchRequest; + private CrossLinksLoader crossLinksLoader; + private CrossLinks crossLinks; // TODO move that at a better place, it is not specific to this controller private static Map> formatters = @@ -93,6 +98,8 @@ public ProductsController(ConnectionContext connectionContext, this.openSearchClient = this.connectionContext.getOpenSearchClient(); + this.crossLinksLoader = new CrossLinksLoader(); + this.crossLinks = this.crossLinksLoader.loadConfiguration(); } private ResponseEntity formatSingleProduct(HashMap product, @@ -195,7 +202,6 @@ public ResponseEntity selectByLidvid(String identifier, List fie } - @Override public ResponseEntity selectByLidvidLatest(String identifier, List fields) throws UnhandledException, NotFoundException, AcceptFormatNotSupportedException { @@ -213,6 +219,34 @@ public ResponseEntity selectByLidvidLatest(String identifier, List productCrossLinks(String identifier) + throws UnhandledException, NotFoundException, AcceptFormatNotSupportedException { + + // Get product metadata that we're cross-linking between services + + HashMap product = new HashMap<>(); + + /* + List fields = new ArrayList<>(); + + try { + PdsProductIdentifier pdsIdentifier = PdsProductIdentifier.fromString(identifier); + + if (pdsIdentifier.isLidvid()) { + product = this.getLidVid(pdsIdentifier, fields); + } else { + product = this.getLatestLidVid(pdsIdentifier, fields); + } + } catch (IOException | OpenSearchException e) { + throw new UnhandledException(e); + } + */ + + + return new ResponseEntity(this.crossLinks.getLinks(product), new HttpHeaders(), HttpStatus.OK); + } + @Override public ResponseEntity selectByLidvidAll(String identifier, List fields, Integer limit, List sort, List searchAfter) throws UnhandledException, @@ -348,6 +382,4 @@ private RawMultipleProductResponse getAllLidVid(PdsProductIdentifier identifier, } - - } diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java new file mode 100644 index 00000000..cca11dcb --- /dev/null +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java @@ -0,0 +1,198 @@ +package gov.nasa.pds.api.registry.model.tools; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; + +public class CrossLinks { + private List tools; + public void setTools(List t) { + this.tools = t; + } + public List getTools() { + return tools; + } + + public Object getLinks(HashMap product) { + // first pull out all the supported metadata from the product + //String lid = product.get("lid"); + Map values = new HashMap<>(); + String lidvid = "urn:nasa:pds:mars2020_mastcamz_ops_calibrated:data:zlf_1019_0757408892_144ras_n0490000zcam07114_1100lmj::2.0"; + String filename = "NLF_1019_0757408223_941RAD_N0490000NCAM02019_0A0195J01.IMG"; + int filenameLastIndexOf = filename.lastIndexOf('.'); + String filenameWithoutFileExtension = filename.substring(0, filenameLastIndexOf); + String fileExtension = filename.substring(filenameLastIndexOf + 1); + + values.put("vid", "2.0"); + values.put("lid", "urn:nasa:pds:mars2020_mastcamz_ops_calibrated:data:zlf_1019_0757408892_144ras_n0490000zcam07114_1100lmj"); + values.put("lidvid", lidvid); + values.put("mission", "Mars2020"); + values.put("spacecraft", ""); + values.put("bundle", lidvid.split(":")[3]); + values.put("collection", lidvid.split(":")[4]); + values.put("target", "Mars"); + values.put("filename", filename); + values.put("filenameWithoutFileExtension", filenameWithoutFileExtension); + values.put("fileExtension", fileExtension); + values.put("fileRef", "/mars2020_mastcamz_ops_calibrated/data/sol/01019/ids/rdr/zcam/ZLF_1019_0757408892_144RAS_N0490000ZCAM07114_1100LMJ02.xml"); + values.put("productClass", "Product_Observational"); + values.put("productType", "RAS"); + values.put("nodeName", "PDS_IMG"); + + List> response = new ArrayList<>(); + + for (Tool t : getTools()) { + response.add(formToolLink(t, values, product)); + } + return response; + + //return product;//"lid"; + /* + vid: properties.vid + lidvid: properties.lidvid + mission: properties.pds:Investigation_Area.pds:name + spacecraft: + bundleId: + target: properties.pds:Target_Identification.pds:name + filename: properties.ops:Data_File_Info.ops:file_name + filenameWithoutFileExtension + fileExtension + fileRef: properties.ops:Data_File_Info.ops:file_ref + productClass: properties.productClass + productType: properties.mgn:Magellan_Parameters.mgn:product_type + nodeName: properties.ops:Harvest_Info.ops:node_name + */ + } + + private Map formToolLink(Tool t, Map values, HashMap product) { + + Map l = new HashMap<>(); + l.put("tool", t.getName()); + l.put("description", t.getDescription()); + + String link = t.getBase(); + + for (String field : values.keySet()) { + String value = (String) values.get(field); + + for( Alias a : t.getAliases()) { + if( a.getField().equals(field) ) { + System.out.println(a.getFrom()); + if( a.getFrom().contains(value) ) { + value = a.getAlias(); + break; + } + } + } + link = link.replaceAll("\\{" + field + "\\}", value); + + } + + l.put("link", link); + + return l; + } + + private static class Tool { + private String name; + public void setName(String n) { + this.name = n; + } + public String getName() { + return name; + } + + private String base; + public void setBase(String b) { + this.base = b; + } + public String getBase() { + return base; + } + + private String description; + public void setDescription(String d) { + this.description = d; + } + public String getDescription() { + return description; + } + private List supportsLinksFrom; + public void setSupportsLinksFrom(List s) { + this.supportsLinksFrom = s; + } + public List getSupportsLinksFrom() { + return supportsLinksFrom; + } + + private List aliases; + public void setAliases(List a) { + this.aliases = a; + } + public List getAliases() { + return aliases; + } + + private List reject; + public void setReject(List r) { + this.reject = r; + } + public List getReject() { + return reject; + } + } + + private static class Alias { + private String field; + public void setField(String f) { + this.field = f; + } + public String getField() { + return field; + } + + private String alias; + public void setAlias(String a) { + this.alias = a; + } + public String getAlias() { + return alias; + } + + private List from; + public void setFrom(List f) { + this.from = f; + } + public List getFrom() { + return from; + } + + } + + private static class Reject { + private String field; + public void setField(String f) { + this.field = f; + } + public String getField() { + return field; + } + + private String match; + public void setMatch(String m) { + this.match = m; + } + public String getMatch() { + return match; + } + + } +} + + diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java new file mode 100644 index 00000000..8b0364f0 --- /dev/null +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java @@ -0,0 +1,34 @@ +package gov.nasa.pds.api.registry.model.tools; + +import java.io.File; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; + +// So that we don't have to load the json multiple times +public class CrossLinksLoader { + private CrossLinks config; + + public CrossLinks loadConfiguration() { + System.out.println("=================================================================================================================="); + if (config == null) { + ObjectMapper mapper = new ObjectMapper(); + try { + config = mapper.readValue(new File("cross-links.json"), CrossLinks.class); + System.out.println(config); + } catch (IOException e) { + // Handle exception + System.out.println(e); + } + } + return config; + } +} \ No newline at end of file diff --git a/service/unittests.txt b/service/unittests.txt new file mode 100644 index 00000000..e69de29b From fa8cf50dfd44c33cdb3c243d8af388f2e66404ff Mon Sep 17 00:00:00 2001 From: tariqksoliman Date: Tue, 16 Jul 2024 18:48:04 -0700 Subject: [PATCH 2/6] #472 Crosslinks - use values from queried doc --- .../controllers/ProductsController.java | 7 +-- .../pds/api/registry/model/EntityProduct.java | 8 +-- .../api/registry/model/tools/CrossLinks.java | 51 ++++++++----------- 3 files changed, 28 insertions(+), 38 deletions(-) diff --git a/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java b/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java index d2118473..876f9406 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/controllers/ProductsController.java @@ -226,8 +226,7 @@ public ResponseEntity productCrossLinks(String identifier) // Get product metadata that we're cross-linking between services HashMap product = new HashMap<>(); - - /* + List fields = new ArrayList<>(); try { @@ -241,8 +240,6 @@ public ResponseEntity productCrossLinks(String identifier) } catch (IOException | OpenSearchException e) { throw new UnhandledException(e); } - */ - return new ResponseEntity(this.crossLinks.getLinks(product), new HttpHeaders(), HttpStatus.OK); } @@ -310,12 +307,12 @@ private HashMap getLidVid(PdsProductIdentifier identifier, List< SearchRequest searchRequest = registrySearchRequestBuilder.addLidvidMatch(identifier).fields(fields).build(); - // useless to detail here that the HashMap is parameterized // because of compilation features, see // https://stackoverflow.com/questions/2390662/java-how-do-i-get-a-class-literal-from-a-generic-type SearchResponse searchResponse = this.openSearchClient.search(searchRequest, HashMap.class); + if (searchResponse.hits().total().value() == 0) { throw new NotFoundException("No product found with identifier " + identifier.toString()); } diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/EntityProduct.java b/service/src/main/java/gov/nasa/pds/api/registry/model/EntityProduct.java index c0aee1a3..4a0db0bb 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/model/EntityProduct.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/EntityProduct.java @@ -112,20 +112,20 @@ public List getRef_lid_target() { return ref_lid_target; } - private static String getFirstElmentOrNull(List l) { + private static String getFirstElementOrNull(List l) { return l != null ? l.get(0) : null; } public String getPDS4FileRef() { - return EntityProduct.getFirstElmentOrNull(this.pds4FileReference); + return EntityProduct.getFirstElementOrNull(this.pds4FileReference); } public String getStartDateTime() { - return EntityProduct.getFirstElmentOrNull(this.start_date_time); + return EntityProduct.getFirstElementOrNull(this.start_date_time); } public String getStopDateTime() { - return EntityProduct.getFirstElmentOrNull(this.stop_date_time); + return EntityProduct.getFirstElementOrNull(this.stop_date_time); } public List getModificationDate() { diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java index cca11dcb..d6721034 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java @@ -19,31 +19,41 @@ public List getTools() { return tools; } + public String get(HashMap product, String str) { + Object obj = product.get(str); + String value = obj != null ? obj.toString() : null; + if( value != null ) { + String array[] = value.replace("[", "").replace("]", "").split(","); + return array[0]; + } + return ""; + } + public Object getLinks(HashMap product) { // first pull out all the supported metadata from the product - //String lid = product.get("lid"); + Map values = new HashMap<>(); - String lidvid = "urn:nasa:pds:mars2020_mastcamz_ops_calibrated:data:zlf_1019_0757408892_144ras_n0490000zcam07114_1100lmj::2.0"; - String filename = "NLF_1019_0757408223_941RAD_N0490000NCAM02019_0A0195J01.IMG"; + String lidvid = this.get(product, "lidvid"); + String filename = this.get(product, "pds:File/pds:file_name"); int filenameLastIndexOf = filename.lastIndexOf('.'); String filenameWithoutFileExtension = filename.substring(0, filenameLastIndexOf); String fileExtension = filename.substring(filenameLastIndexOf + 1); - values.put("vid", "2.0"); - values.put("lid", "urn:nasa:pds:mars2020_mastcamz_ops_calibrated:data:zlf_1019_0757408892_144ras_n0490000zcam07114_1100lmj"); + values.put("vid", this.get(product, "vid")); + values.put("lid", this.get(product, "lid")); values.put("lidvid", lidvid); - values.put("mission", "Mars2020"); - values.put("spacecraft", ""); + values.put("mission", this.get(product, "pds:Investigation_Area/pds:name")); + values.put("spacecraft", this.get(product, "pds:Observing_System/pds:name")); values.put("bundle", lidvid.split(":")[3]); values.put("collection", lidvid.split(":")[4]); - values.put("target", "Mars"); + values.put("target", this.get(product, "pds:Target_Identification/pds:name")); values.put("filename", filename); values.put("filenameWithoutFileExtension", filenameWithoutFileExtension); values.put("fileExtension", fileExtension); - values.put("fileRef", "/mars2020_mastcamz_ops_calibrated/data/sol/01019/ids/rdr/zcam/ZLF_1019_0757408892_144RAS_N0490000ZCAM07114_1100LMJ02.xml"); - values.put("productClass", "Product_Observational"); - values.put("productType", "RAS"); - values.put("nodeName", "PDS_IMG"); + values.put("fileRef", this.get(product, "ops:Data_File_Info/ops:file_ref")); + values.put("productClass", this.get(product, "product_class")); + values.put("productType", this.get(product, "msn:Mission_Information/msn:product_type_name")); + values.put("nodeName", this.get(product, "ops:Harvest_Info/ops:node_name")); List> response = new ArrayList<>(); @@ -51,23 +61,6 @@ public Object getLinks(HashMap product) { response.add(formToolLink(t, values, product)); } return response; - - //return product;//"lid"; - /* - vid: properties.vid - lidvid: properties.lidvid - mission: properties.pds:Investigation_Area.pds:name - spacecraft: - bundleId: - target: properties.pds:Target_Identification.pds:name - filename: properties.ops:Data_File_Info.ops:file_name - filenameWithoutFileExtension - fileExtension - fileRef: properties.ops:Data_File_Info.ops:file_ref - productClass: properties.productClass - productType: properties.mgn:Magellan_Parameters.mgn:product_type - nodeName: properties.ops:Harvest_Info.ops:node_name - */ } private Map formToolLink(Tool t, Map values, HashMap product) { From 3069f40ff087af5b9c37d8aa8dc0caff252a6f88 Mon Sep 17 00:00:00 2001 From: tariqksoliman Date: Wed, 17 Jul 2024 12:41:06 -0700 Subject: [PATCH 3/6] #472 Crosslinks - support acceptOnly and reject --- service/cross-links.json | 43 +++++++-- .../api/registry/model/tools/CrossLinks.java | 96 ++++++++++++++++--- .../model/tools/CrossLinksLoader.java | 1 - 3 files changed, 119 insertions(+), 21 deletions(-) diff --git a/service/cross-links.json b/service/cross-links.json index 876a3d38..9772aa20 100644 --- a/service/cross-links.json +++ b/service/cross-links.json @@ -1,21 +1,52 @@ { + "injectableParams": [ + "vid", + "lid", + "lidvid", + "mission", + "spacecraft", + "bundle", + "collection", + "target", + "filename", + "filenameWithoutFileExtension", + "fileExtension", + "fileRef", + "productClass", + "productType", + "nodeName" + ], "tools": [ { "name": "analysts_notebook", "base": "https://an.rsl.wustl.edu/{mission}/AN/an3.aspx?it=B1&ii={filenameWithoutFileExtension}", - "description": "description", - "supportsLinksFrom": ["atlas", "astria"], + "description": "A tool for accessing the science data archives from NASA landed Mars and lunar missions.", "aliases": [ { "field": "mission", "alias": "m20", "from": ["mars_2020", "m2020", "mars2020", "Mars2020"] + }, + { + "field": "mission", + "alias": "ins", + "from": ["InSight"] } ], - "reject": [ - { "field": "uri", "match": "/*mars2020_helicam*/" }, - { "field": "uri", "match": "/*mars2020_imgops*/" } - ] + "acceptOnly": [ + { "field": "mission", "match": "m20" }, + { "field": "mission", "match": "ins" }, + { "field": "fileExtension", "match": "\\.IMG" } + ], + "reject": [{ "field": "uri", "match": ".*mars2020_helicam.*" }] + }, + { + "name": "atlas4", + "base": "https://pds-imaging.jpl.nasa.gov/beta/record?lidvid={lidvid}", + "description": "The Official Image Search of the PDS Cartography and Imaging Sciences Node (PDSIMG)", + "aliases": [], + "acceptOnly": [], + "reject": [] } ] } diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java index d6721034..e237551c 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinks.java @@ -11,6 +11,14 @@ import com.fasterxml.jackson.databind.JsonNode; public class CrossLinks { + private String[] injectableParams; + public void setInjectableParams(String[] i) { + this.injectableParams = i; + } + public String[] getInjectableParams() { + return injectableParams; + } + private List tools; public void setTools(List t) { this.tools = t; @@ -35,9 +43,16 @@ public Object getLinks(HashMap product) { Map values = new HashMap<>(); String lidvid = this.get(product, "lidvid"); String filename = this.get(product, "pds:File/pds:file_name"); - int filenameLastIndexOf = filename.lastIndexOf('.'); - String filenameWithoutFileExtension = filename.substring(0, filenameLastIndexOf); - String fileExtension = filename.substring(filenameLastIndexOf + 1); + int filenameLastIndexOf = -1; + String filenameWithoutFileExtension = ""; + String fileExtension = ""; + if( filename != null ) { + filenameLastIndexOf = filename.lastIndexOf('.'); + if( filenameLastIndexOf > -1 ) { + filenameWithoutFileExtension = filename.substring(0, filenameLastIndexOf); + fileExtension = filename.substring(filenameLastIndexOf + 1); + } + } values.put("vid", this.get(product, "vid")); values.put("lid", this.get(product, "lid")); @@ -58,7 +73,10 @@ public Object getLinks(HashMap product) { List> response = new ArrayList<>(); for (Tool t : getTools()) { - response.add(formToolLink(t, values, product)); + Map linkObj = formToolLink(t, values, product); + if( linkObj != null ) { + response.add(linkObj); + } } return response; } @@ -71,25 +89,54 @@ private Map formToolLink(Tool t, Map values, Has String link = t.getBase(); + boolean accept = false; + boolean reject = false; + for (String field : values.keySet()) { String value = (String) values.get(field); + // Aliases for( Alias a : t.getAliases()) { if( a.getField().equals(field) ) { - System.out.println(a.getFrom()); if( a.getFrom().contains(value) ) { value = a.getAlias(); break; } } } + + // Accept + for( Accept a : t.getAcceptOnly()) { + if( a.getField().equals(field) ) { + if( value.matches(a.getMatch()) ) { + accept = true; + } + } + } + if( t.getAcceptOnly().size() == 0 ) { + accept = true; + } + + // Reject + for( Reject a : t.getReject()) { + if( a.getField().equals(field) ) { + if( value.matches(a.getMatch()) ) { + reject = false; + } + } + } + link = link.replaceAll("\\{" + field + "\\}", value); } - + l.put("link", link); - return l; + if( accept == true && reject == false ) { + return l; + } + return null; + } private static class Tool { @@ -116,13 +163,6 @@ public void setDescription(String d) { public String getDescription() { return description; } - private List supportsLinksFrom; - public void setSupportsLinksFrom(List s) { - this.supportsLinksFrom = s; - } - public List getSupportsLinksFrom() { - return supportsLinksFrom; - } private List aliases; public void setAliases(List a) { @@ -132,6 +172,15 @@ public List getAliases() { return aliases; } + + private List acceptOnly; + public void setAcceptOnly(List a) { + this.acceptOnly = a; + } + public List getAcceptOnly() { + return acceptOnly; + } + private List reject; public void setReject(List r) { this.reject = r; @@ -168,6 +217,25 @@ public List getFrom() { } + private static class Accept { + private String field; + public void setField(String f) { + this.field = f; + } + public String getField() { + return field; + } + + private String match; + public void setMatch(String m) { + this.match = m; + } + public String getMatch() { + return match; + } + + } + private static class Reject { private String field; public void setField(String f) { diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java index 8b0364f0..e42afa86 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java @@ -18,7 +18,6 @@ public class CrossLinksLoader { private CrossLinks config; public CrossLinks loadConfiguration() { - System.out.println("=================================================================================================================="); if (config == null) { ObjectMapper mapper = new ObjectMapper(); try { From 5299e344c0679bbee3109e26ac04e6e808d6dc75 Mon Sep 17 00:00:00 2001 From: tariqksoliman Date: Thu, 18 Jul 2024 10:58:26 -0700 Subject: [PATCH 4/6] #472 Fix accidentally deleted line --- model/swagger.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/model/swagger.yml b/model/swagger.yml index c1ce66e0..6a0fad1e 100644 --- a/model/swagger.yml +++ b/model/swagger.yml @@ -866,6 +866,7 @@ components: $ref: '#/components/schemas/metadata' properties: type: object + description: properties' values extracted from pds4 model, as a dictionary, syntax for property name is {namespace}:{property}[{namespace}:{property}]* additionalProperties: $ref: '#/components/schemas/propertyArrayValues' xml: From dfbc0f14939328efaa7740f5f0e9eb14b636b1cd Mon Sep 17 00:00:00 2001 From: tariqksoliman Date: Thu, 18 Jul 2024 11:00:20 -0700 Subject: [PATCH 5/6] #472 Undo service/pom.xml formatting --- service/pom.xml | 402 ++++++++++++++++++++++++------------------------ 1 file changed, 202 insertions(+), 200 deletions(-) diff --git a/service/pom.xml b/service/pom.xml index e226fc9e..a8bd2a67 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -30,9 +30,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 gov.nasa.pds @@ -60,133 +58,133 @@ - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot-version} - - - - repackage - - - - - gov.nasa.pds.api.registry.SpringBootMain - nasapds/registry-api-service - JAR - - + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-version} + + + + repackage + + + + + gov.nasa.pds.api.registry.SpringBootMain + nasapds/registry-api-service + JAR + + 17 -XX:MaxDirectMemorySize=1G - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.1.1 - - - bin-release - package - - single - - - true - - src/main/assembly/tar-assembly.xml - src/main/assembly/zip-assembly.xml - - - jar-with-dependencies - - - - - - posix - - + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.1 + + + bin-release + package + + single + + + true + + src/main/assembly/tar-assembly.xml + src/main/assembly/zip-assembly.xml + + + jar-with-dependencies + + + + + + posix + + org.apache.maven.plugins maven-compiler-plugin - com.iluwatar.urm - urm-maven-plugin - 2.0.0 - - ${project.basedir}/target - - gov.nasa.pds.api.registry - - - - true - false - mermaid - - jar-with-dependencies - - - - - process-classes - - map - - - - + com.iluwatar.urm + urm-maven-plugin + 2.0.0 + + ${project.basedir}/target + + gov.nasa.pds.api.registry + + + + true + false + mermaid + + jar-with-dependencies + + + + + process-classes + + map + + + + - + - + org.springframework.boot spring-boot-starter-web - + - org.springframework.boot - spring-boot-starter-actuator + org.springframework.boot + spring-boot-starter-actuator - org.springframework.data - spring-data-commons - + org.springframework.data + spring-data-commons + - + org.springdoc springdoc-openapi-starter-webmvc-ui 2.0.4 - + - - - org.springdoc - springdoc-openapi-starter-common - 2.0.4 - + + + org.springdoc + springdoc-openapi-starter-common + 2.0.4 + - + org.springframework.boot spring-boot-starter-thymeleaf - - io.swagger.core.v3 - swagger-core - 2.2.8 - + + io.swagger.core.v3 + swagger-core + 2.2.8 + @@ -195,8 +193,8 @@ spring-boot-autoconfigure - - + - - - jakarta.validation - jakarta.validation-api - 3.0.2 - - - - - jakarta.annotation - jakarta.annotation-api - 2.1.1 - + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + @@ -312,40 +310,40 @@ 4.11.1 - - - org.opensearch.client - opensearch-java - 2.10.1 - - - - - org.apache.httpcomponents.client5 - httpclient5 - - 5.3.1 - - - + + + org.opensearch.client + opensearch-java + 2.10.1 + - - org.apache.httpcomponents.core5 - httpcore5 - 5.2.4 - + + + org.apache.httpcomponents.client5 + httpclient5 + + 5.3.1 + + + + + org.apache.httpcomponents.core5 + httpcore5 + 5.2.4 + - - - org.apache.httpcomponents.core5 - httpcore5-h2 - 5.2.4 - - + + + org.apache.httpcomponents.core5 + httpcore5-h2 + 5.2.4 + + + - - - - software.amazon.awssdk - apache-client - 2.25.21 - - + + + software.amazon.awssdk + apache-client + 2.25.21 + + software.amazon.awssdk apache-client 2.25.21 + + + + software.amazon.awssdk + regions + 2.25.21 + + + + + + + software.amazon.awssdk + auth + 2.25.21 + - - - software.amazon.awssdk - regions - 2.25.21 - - - - - - software.amazon.awssdk - auth - 2.25.21 - - - - - com.amazonaws - aws-java-sdk-core - 1.12.688 - - - + + + com.amazonaws + aws-java-sdk-core + 1.12.688 + + + - - + + org.opensearch.client opensearch-rest-client 2.12.0 - + org.opensearch.client opensearch-rest-high-level-client @@ -406,6 +405,7 @@ + org.apache.httpcomponents @@ -419,42 +419,44 @@ commons-collections4 4.2 - + org.springframework.boot spring-boot-starter-test - - junit - junit - + + junit + junit + - - org.junit.jupiter - junit-jupiter-engine - 5.7.0 - test + org.junit.jupiter + junit-jupiter-engine + 5.7.0 + test - org.mockito - mockito-core - 3.6.28 - test + org.mockito + mockito-core + 3.6.28 + test - - + + + + org.springframework.boot spring-boot-starter-validation @@ -472,15 +474,15 @@ guava 32.0.0-jre - + - - jakarta.servlet - jakarta.servlet-api - 6.0.0 - provided - - + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided + + @@ -495,4 +497,4 @@ - \ No newline at end of file + From d6f2c24f89b3e0e646bff0f5c388994a63633a01 Mon Sep 17 00:00:00 2001 From: tariqksoliman Date: Thu, 1 Aug 2024 18:00:11 -0700 Subject: [PATCH 6/6] #472 Move cross-links.json to src/main/resources --- .../gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java | 2 +- service/{ => src/main/resources}/cross-links.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename service/{ => src/main/resources}/cross-links.json (94%) diff --git a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java index 4479b687..1de33721 100644 --- a/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java +++ b/service/src/main/java/gov/nasa/pds/api/registry/model/tools/CrossLinksLoader.java @@ -33,7 +33,7 @@ public CrossLinks loadConfiguration() { if (config == null) { ObjectMapper mapper = new ObjectMapper(); try { - config = mapper.readValue(new File("cross-links.json"), CrossLinks.class); + config = mapper.readValue(new File("src/main/resources/cross-links.json"), CrossLinks.class); System.out.println(config); } catch (IOException e) { // Handle exception diff --git a/service/cross-links.json b/service/src/main/resources/cross-links.json similarity index 94% rename from service/cross-links.json rename to service/src/main/resources/cross-links.json index 9772aa20..5e3d6e9a 100644 --- a/service/cross-links.json +++ b/service/src/main/resources/cross-links.json @@ -38,7 +38,7 @@ { "field": "mission", "match": "ins" }, { "field": "fileExtension", "match": "\\.IMG" } ], - "reject": [{ "field": "uri", "match": ".*mars2020_helicam.*" }] + "reject": [{ "field": "lidvid", "match": ".*mars2020_helicam.*" }] }, { "name": "atlas4",