Skip to content

Commit

Permalink
Initial conceptId endpoint implementation (#48)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshgarde authored Oct 3, 2024
1 parent 181d5ca commit 612fbdc
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/main/java/gov/nasa/podaac/swodlr/SwodlrProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
public record SwodlrProperties(
Map<String, String> teaMapping,
String productCreateQueueUrl,
String availableTilesTableName
String availableTilesTableName,
String cmrGraphqlEndpoint,
String rasterCollectionConceptId
) { }
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gov.nasa.podaac.swodlr.l2rasterproduct;

import gov.nasa.podaac.swodlr.exception.SwodlrException;
import gov.nasa.podaac.swodlr.l2rasterproduct.cmr.CmrSearchService;
import gov.nasa.podaac.swodlr.rasterdefinition.GridType;
import gov.nasa.podaac.swodlr.status.State;
import gov.nasa.podaac.swodlr.status.Status;
Expand Down Expand Up @@ -31,6 +32,9 @@
public class L2RasterProductController {
private Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private CmrSearchService cmrSearchService;

@Autowired
private L2RasterProductService l2RasterProductService;

Expand Down Expand Up @@ -80,6 +84,51 @@ public Mono<L2RasterProduct> generateL2RasterProduct(
});
}

@MutationMapping
public Mono<L2RasterProduct> generateL2RasterProductByConceptId(
@ContextValue UserReference userRef,
@Argument String conceptId,
@Argument boolean outputGranuleExtentFlag,
@Argument @NotNull GridType outputSamplingGridType,
@Argument int rasterResolution,
@Argument Integer utmZoneAdjust,
@Argument Integer mgrsBandAdjust
) {
return Mono.defer(() -> {
User user = userRef.fetch();

return cmrSearchService
.findL2RasterProductById(conceptId)
.flatMap((result) -> {
return l2RasterProductService
.getL2RasterProduct(
user,
result.cycle(),
result.pass(),
result.scene(),
outputGranuleExtentFlag,
outputSamplingGridType,
rasterResolution,
utmZoneAdjust,
mgrsBandAdjust
)
.switchIfEmpty(
Mono.defer(() -> l2RasterProductService.createL2RasterProduct(
user,
result.cycle(),
result.pass(),
result.scene(),
outputGranuleExtentFlag,
outputSamplingGridType,
rasterResolution,
utmZoneAdjust,
mgrsBandAdjust
))
);
});
});
}

@PreAuthorize("hasRole(\"ROLE_Administrator\")")
@MutationMapping
@Transactional
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package gov.nasa.podaac.swodlr.l2rasterproduct.cmr;

import java.util.Map;

public class CmrGraphqlRequest {
private static final String QUERY =
"""
query($params: GranulesInput) {
granules(params: $params) {
items {
granuleUr
}
}
}
""";

private final Map<String, Object> variables;

public CmrGraphqlRequest(String collectionConceptId, String conceptId) {
variables = Map.of("params", Map.of(
"conceptId", conceptId,
"collectionConceptId", collectionConceptId
));
}

public final String getQuery() {
return QUERY;
}

public final Map<String, Object> getVariables() {
return variables;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package gov.nasa.podaac.swodlr.l2rasterproduct.cmr;

import gov.nasa.podaac.swodlr.SwodlrProperties;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@Service
public class CmrSearchService {
private Logger logger = LoggerFactory.getLogger(getClass());
private Pattern granuleUrRe = Pattern.compile("SWOT_L2_HR_Raster_\\d{3}m_\\w+?_(?<cycle>\\d{3})_(?<pass>\\d{3})_(?<scene>\\d{3})F_\\d+T\\d+_\\d+T\\d+_(?<crid>\\w+?)_\\d{2}");

@Autowired
private SwodlrProperties properties;

public Mono<GranuleResult> findL2RasterProductById(String id) {
return getUserToken()
.flatMap((token) -> {
return Mono.defer(() -> {
return WebClient.create()
.post()
.uri(URI.create(properties.cmrGraphqlEndpoint()))
.header("Authorization", "Bearer " + token)
.bodyValue(new CmrGraphqlRequest(
properties.rasterCollectionConceptId(),
id
))
.retrieve()
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {});
});
})
.map((response) -> {
if (response.get("errors") != null) {
for (var error : (List<Object>) response.get("errors")) {
logger.error("GraphQL query error: %s", error.toString());
}

throw new RuntimeException("GraphQL search returned an error");
}

if (response.get("data") == null) {
throw new RuntimeException("No data found in CMR response");
}

var data = (Map<String, Object>) response.get("data");
var granules = (Map<String, Object>) data.get("granules");
var items = (List<Map<String, Object>>) granules.get("items");

if (items.size() != 1) {
return null;
}

var result = items.get(0);
var granuleUr = (String) result.get("granuleUr");
var matcher = granuleUrRe.matcher(granuleUr);

if (!matcher.matches()) {
throw new RuntimeException("Regex failed to match granuleUr");
}

return new GranuleResult(
Integer.parseInt(matcher.group("cycle")),
Integer.parseInt(matcher.group("pass")),
Integer.parseInt(matcher.group("scene")),
matcher.group("crid")
);
});
}

private Mono<String> getUserToken() {
return ReactiveSecurityContextHolder
.getContext()
.map((securityContext) -> securityContext.getAuthentication())
.filter((authentication) -> authentication != null)
.cast(JwtAuthenticationToken.class)
.map((jwt) -> jwt.getToken().getTokenValue());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gov.nasa.podaac.swodlr.l2rasterproduct.cmr;

public record GranuleResult(
int cycle,
int pass,
int scene,
String crid
) { }
3 changes: 2 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ spring.security.oauth2.client.provider.edl.token-uri=https://urs.earthdata.nasa.
spring.security.oauth2.client.provider.edl.user-info-uri=https://urs.earthdata.nasa.gov/api/users
spring.security.oauth2.client.provider.edl.user-name-attribute=uid

swodlr.cmr.endpoint=https://graphql.earthdata.nasa.gov/api
swodlr.cmr-graphql-endpoint=https://graphql.earthdata.nasa.gov/api
swodlr.raster-collection-concept-id=C2799438271-POCLOUD
swodlr.security.sessionLength=24h

#---
Expand Down
9 changes: 9 additions & 0 deletions src/main/resources/graphql/mutation.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ type Mutation {
mgrsBandAdjust: Int
): L2RasterProduct!

generateL2RasterProductByConceptId(
conceptId: ID!,
outputGranuleExtentFlag: Boolean!,
outputSamplingGridType: GridType!,
rasterResolution: Int!,
utmZoneAdjust: Int,
mgrsBandAdjust: Int
): L2RasterProduct!

# -- Raster Definitions --
deleteRasterDefinition(id: ID!): Boolean!
createRasterDefinition(
Expand Down

0 comments on commit 612fbdc

Please sign in to comment.