Skip to content

Commit

Permalink
Merge pull request #512 from NASA-PDS/classes-endpoints
Browse files Browse the repository at this point in the history
Add newly refactored `/classes/{class}` endpoint
  • Loading branch information
jordanpadams authored Jul 29, 2024
2 parents d2a2895 + 1475d1f commit 142ed47
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

import java.lang.reflect.InvocationTargetException;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.*;

import gov.nasa.pds.api.base.ClassesApi;
import gov.nasa.pds.api.registry.model.exceptions.*;
import gov.nasa.pds.api.registry.model.identifiers.PdsLid;
import gov.nasa.pds.api.registry.model.identifiers.PdsLidVid;
Expand All @@ -22,8 +19,10 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import gov.nasa.pds.api.base.ProductsApi;
Expand All @@ -40,7 +39,16 @@


@Controller
public class ProductsController implements ProductsApi {
// TODO: Refactor common controller code out of ProductsController and split the additional API implementations out into
// corresponding controllers
public class ProductsController implements ProductsApi, ClassesApi {

@Override
// TODO: Remove this when the common controller code is refactored out - it is only necessary because additional
// interfaces have been implemented as a stopgap
public Optional<NativeWebRequest> getRequest() {
return ProductsApi.super.getRequest();
}

private static final Logger log = LoggerFactory.getLogger(ProductsController.class);

Expand Down Expand Up @@ -600,4 +608,36 @@ public ResponseEntity<Object> productMemberOfOf(
}
}

@Override
// TODO: Relocate this to ClassesController once common controller code has been extracted/refactored
public ResponseEntity<Object> classList(String propertyClass, List<String> fields, List<String> keywords, Integer limit, String q, List<String> sort, List<String> searchAfter) throws Exception {
PdsProductClasses pdsProductClass;
try {
pdsProductClass = PdsProductClasses.fromSwaggerName(propertyClass);
} catch (IllegalArgumentException err) {
throw new BadRequestException(err.getMessage());
}

SearchRequest searchRequest = new RegistrySearchRequestBuilder(this.connectionContext)
.matchProductClass(pdsProductClass)
.constrainByQueryString(q)
.addKeywordsParam(keywords)
.fieldsFromStrings(fields)
.paginate(limit, sort, searchAfter)
.onlyLatest()
.build();

SearchResponse<HashMap> searchResponse =
this.openSearchClient.search(searchRequest, HashMap.class);

RawMultipleProductResponse products = new RawMultipleProductResponse(searchResponse);

return formatMultipleProducts(products, fields);
}

@Override
// TODO: Relocate this to ClassesController once common controller code has been extracted/refactored
public ResponseEntity<List<String>> classes() throws Exception {
return new ResponseEntity<>(Arrays.stream(PdsProductClasses.values()).map(PdsProductClasses::getSwaggerName).toList(), HttpStatusCode.valueOf(200));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package gov.nasa.pds.api.registry.model.identifiers;

import java.util.Arrays;
import java.util.List;

/**
* An enumeration of the valid product_class values from the PDS4 Data Dictionary
* <a href="https://pds.nasa.gov/datastandards/documents/dd/v1/PDS4_PDS_DD_1M00.html#N-1195656387">...</a>
Expand Down Expand Up @@ -52,12 +55,52 @@ public String getValue() {
}

/**
* @return The database property/field these string values appear in. Provided for convenience.
* @return the database property/field these string values appear in. Provided for convenience.
*/
public static String getPropertyName() {
return "product_class";
}

public static List<String> getValidSwaggerNames() {
return Arrays.stream(PdsProductClasses.values()).map(PdsProductClasses::getSwaggerName).toList();
}

/**
* @return the shorthand name used for convenience in API routes, ex. "Product_Bundle" -> "bundle"
*/
public String getSwaggerName() {
List<String> chunks = Arrays.asList(this.value.split("_"));

if (chunks.size() < 2 || !chunks.get(0).equals("Product")) {
throw new IllegalArgumentException("Could not generate swagger name for PDSProductClasses value '" + this.value + "'");
}

List<String> relevantChunks = chunks.subList(1, chunks.size());

return String.join("-", relevantChunks).toLowerCase();
}

/**
* @return the PdsProductClass which is equivalent to a given swagger-formatted product class name
*/
public static PdsProductClasses fromSwaggerName(String swaggerName) {
List<PdsProductClasses> matches = Arrays.stream(PdsProductClasses.values())
.filter(value -> value.getSwaggerName().equals(swaggerName))
.toList();

if (matches.isEmpty()) {
throw new IllegalArgumentException("No PdsProductClass matches swagger name '" + swaggerName + "'"
+ "'. Valid names are: " + String.join(", ", getValidSwaggerNames()));
}

if (matches.size() > 1) {
// This should never be possible and indicates an error in the enum value definitions
throw new IllegalArgumentException("Multiple PdsProductClass matches swagger name '" + swaggerName + "'");
}

return matches.get(0);
}

public Boolean isBundle() {
return this == Product_Bundle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ public RegistrySearchRequestBuilder matchLid(PdsProductIdentifier identifier) {
return this.matchField("lid", identifier.getLid());
}

public RegistrySearchRequestBuilder matchProductClass(PdsProductClasses productClass) {
return this.matchField(PdsProductClasses.getPropertyName(), productClass.getValue());
}

public RegistrySearchRequestBuilder matchMembersOfBundle(PdsLidVid identifier) {
return this.matchField("ops:Provenance/ops:parent_bundle_identifier", identifier);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package gov.nasa.pds.api.registry.model;

import gov.nasa.pds.api.registry.model.identifiers.PdsProductClasses;
import org.junit.Assert;
import org.junit.Test;

public class PdsProductClassesTest {
@Test
public void testSwaggerConversions() {
for (PdsProductClasses canonicalClass : PdsProductClasses.values()) {
String swaggerName = canonicalClass.getSwaggerName();
PdsProductClasses parsedClass = PdsProductClasses.fromSwaggerName(swaggerName);
Assert.assertEquals(canonicalClass, parsedClass);
}
}
}

0 comments on commit 142ed47

Please sign in to comment.