Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAT-6180 Add ELM (XML and JSON) to QDM measure export #3

Merged
merged 7 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
<puppycrawl.checkstyle.version>10.1</puppycrawl.checkstyle.version>
<spotify.fmt.version>2.21.1</spotify.fmt.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down Expand Up @@ -60,27 +59,27 @@
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>gov.cms.madie</groupId>
<artifactId>madie-java-models</artifactId>
<version>0.6.13-SNAPSHOT</version>
<version>0.6.15-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>gov.cms.madie.packaging</groupId>
<artifactId>packaging-utility</artifactId>
<version>0.2.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

<repositories>
<repository>
<releases>
Expand All @@ -91,7 +90,6 @@
<url>https://maven.pkg.github.com/measureauthoringtool/madie-java-models</url>
</repository>
</repositories>

<build>
<pluginManagement>
<plugins>
Expand Down Expand Up @@ -211,7 +209,6 @@
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
Expand All @@ -234,7 +231,6 @@
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package gov.cms.madie.Exceptions;

public class TranslationServiceException extends RuntimeException {

public TranslationServiceException(String message, Exception cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package gov.cms.madie.Exceptions;

public class UnsupportedModelException extends RuntimeException {
public UnsupportedModelException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package gov.cms.madie.madieqdmservice;
package gov.cms.madie;

import gov.cms.madie.madieqdmservice.config.LogInterceptor;
import gov.cms.madie.config.LogInterceptor;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package gov.cms.madie.config;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Getter
@Configuration
public class CqlElmTranslatorClientConfig {

@Value("${madie.cql-elm.service.base-url}")
private String baseUrl;

@Value("${madie.cql-elm.service.cql-elm-urn}")
private String cqlElmUrn;

@Bean
public RestTemplate elmTranslatorRestTemplate() {
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gov.cms.madie.madieqdmservice.config;
package gov.cms.madie.config;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gov.cms.madie.madieqdmservice.config;
package gov.cms.madie.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package gov.cms.madie.resources;

import gov.cms.madie.Exceptions.TranslationServiceException;
import gov.cms.madie.Exceptions.UnsupportedModelException;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;

import java.util.Map;

@ControllerAdvice
@RequiredArgsConstructor
public class CustomErrorHandlerAdvice {
private final ErrorAttributes errorAttributes;

@ExceptionHandler({TranslationServiceException.class, UnsupportedModelException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
Map<String, Object> handleCustomException(WebRequest request) {
return getErrorAttributes(request, HttpStatus.BAD_REQUEST);
}

private Map<String, Object> getErrorAttributes(WebRequest request, HttpStatus httpStatus) {
ErrorAttributeOptions errorOptions =
ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);
Map<String, Object> errorAttributes =
this.errorAttributes.getErrorAttributes(request, errorOptions);
errorAttributes.put("status", httpStatus.value());
errorAttributes.put("error", httpStatus.getReasonPhrase());
return errorAttributes;
}
}
39 changes: 39 additions & 0 deletions src/main/java/gov/cms/madie/resources/PackageController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package gov.cms.madie.resources;

import gov.cms.madie.Exceptions.UnsupportedModelException;
import gov.cms.madie.services.PackagingService;
import gov.cms.madie.models.measure.Measure;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping(path = "/qdm/measures")
@RequiredArgsConstructor
public class PackageController {

private final PackagingService packagingService;

@PutMapping(
value = "/package",
produces = {
MediaType.APPLICATION_OCTET_STREAM_VALUE,
},
consumes = {MediaType.APPLICATION_JSON_VALUE})
public byte[] getMeasurePackage(
@RequestBody @Validated(Measure.ValidationSequence.class) Measure measure,
@RequestHeader("Authorization") String accessToken) {
// generate package if the model type is QDM
if (measure.getModel() != null && measure.getModel().contains("QDM")) {
return packagingService.createMeasurePackage(measure, accessToken);
}
throw new UnsupportedModelException("Unsupported model type: " + measure.getModel());
}
}
42 changes: 42 additions & 0 deletions src/main/java/gov/cms/madie/services/PackagingService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package gov.cms.madie.services;

import gov.cms.madie.models.dto.TranslatedLibrary;
import gov.cms.madie.models.measure.Measure;
import gov.cms.madie.packaging.utils.ZipUtility;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class PackagingService {
private final TranslationServiceClient translationServiceClient;

public byte[] createMeasurePackage(Measure measure, String accessToken) {
log.info("Creating the measure package for measure [{}]", measure.getId());
List<TranslatedLibrary> translatedLibraries =
translationServiceClient.getTranslatedLibraries(measure.getCql(), accessToken);
if (CollectionUtils.isEmpty(translatedLibraries)) {
return new byte[0];
}
log.info("Adding measure package artifacts to the measure package");
String resourcesDir = "resources/";
String cqlDir = "cql/";
Map<String, byte[]> entries = new HashMap<>();
for (TranslatedLibrary translatedLibrary : translatedLibraries) {
String entryName = translatedLibrary.getName() + "-v" + translatedLibrary.getVersion();
entries.put(resourcesDir + entryName + ".json", translatedLibrary.getElmJson().getBytes());
entries.put(resourcesDir + entryName + ".xml", translatedLibrary.getElmXml().getBytes());
entries.put(cqlDir + entryName + ".cql", translatedLibrary.getCql().getBytes());
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
return new ZipUtility().zipEntries(entries, outputStream);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package gov.cms.madie.services;

import gov.cms.madie.Exceptions.TranslationServiceException;
import gov.cms.madie.config.CqlElmTranslatorClientConfig;
import gov.cms.madie.models.dto.TranslatedLibrary;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.List;

@Slf4j
@Service
public record TranslationServiceClient(
CqlElmTranslatorClientConfig translatorClientConfig, RestTemplate elmTranslatorRestTemplate) {

public List<TranslatedLibrary> getTranslatedLibraries(String cql, String accessToken) {
URI uri =
URI.create(translatorClientConfig.getBaseUrl() + translatorClientConfig.getCqlElmUrn());
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.AUTHORIZATION, accessToken);
headers.set(HttpHeaders.ACCEPT, MediaType.ALL_VALUE);
headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
HttpEntity<String> entity = new HttpEntity<>(cql, headers);
ParameterizedTypeReference<List<TranslatedLibrary>> responseType =
new ParameterizedTypeReference<>() {};
try {
log.info("fetching the elm for measure cql & included libraries");
return elmTranslatorRestTemplate
.exchange(uri, HttpMethod.PUT, entity, responseType)
.getBody();
} catch (Exception ex) {
String msg = "An issue occurred while fetching the translated artifacts for measure cql";
log.error(msg, ex);
throw new TranslationServiceException(msg, ex);
}
}
}
4 changes: 4 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ server:

madie:
allowedApi: http://localhost:9000
cql-elm:
service:
base-url: ${ELM_TRANSLATOR_SERVICE_URL:http://localhost:8084/api}
cql-elm-urn: /cql/elm

management:
endpoints:
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading