From 777f37563317590d9d058791a8f841e27a789c98 Mon Sep 17 00:00:00 2001 From: nmorasb Date: Mon, 4 Mar 2024 23:12:21 -0500 Subject: [PATCH] MAT-6785: more mappings for CqlLookups, update SimpleXML schema to account for some gaps and issues --- .../madie/simplexml/AllUsedCQLLibsType.java | 36 +++--- .../cms/madie/simplexml/ArgumentsType.java | 36 +++--- .../cms/madie/simplexml/ParametersType.java | 36 +++--- .../madie/resources/PackageController.java | 8 +- .../gov/cms/madie/services/MeasureMapper.java | 115 +++++++++++++++++- .../cms/madie/services/SimpleXmlService.java | 2 +- .../resources/schemas/SimpleXML-QDM-5-6.xsd | 6 +- .../resources/PackageControllerMvcTest.java | 3 +- .../cms/madie/services/HqmfServiceTest.java | 4 +- .../cms/madie/services/MeasureMapperTest.java | 8 +- .../madie/services/SimpleXmlServiceTest.java | 3 +- 11 files changed, 198 insertions(+), 59 deletions(-) diff --git a/src/main/java/generated/gov/cms/madie/simplexml/AllUsedCQLLibsType.java b/src/main/java/generated/gov/cms/madie/simplexml/AllUsedCQLLibsType.java index 9e1a692..3eeda6d 100644 --- a/src/main/java/generated/gov/cms/madie/simplexml/AllUsedCQLLibsType.java +++ b/src/main/java/generated/gov/cms/madie/simplexml/AllUsedCQLLibsType.java @@ -6,9 +6,10 @@ package generated.gov.cms.madie.simplexml; +import java.util.ArrayList; +import java.util.List; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; -import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlType; /** @@ -21,7 +22,7 @@ * * * - * + * * * * @@ -34,24 +35,29 @@ propOrder = {"lib"}) public class AllUsedCQLLibsType { - @XmlElement(required = true) - protected LibType lib; + protected List lib; /** * Gets the value of the lib property. * - * @return possible object is {@link LibType } - */ - public LibType getLib() { - return lib; - } - - /** - * Sets the value of the lib property. + *

This accessor method returns a reference to the live list, not a snapshot. Therefore any + * modification you make to the returned list will be present inside the JAXB object. This is why + * there is not a set method for the lib property. + * + *

For example, to add a new item, do as follows: + * + *

+   * getLib().add(newItem);
+   * 
+ * + *

Objects of the following type(s) are allowed in the list {@link LibType } * - * @param value allowed object is {@link LibType } + * @return The value of the lib property. */ - public void setLib(LibType value) { - this.lib = value; + public List getLib() { + if (lib == null) { + lib = new ArrayList<>(); + } + return this.lib; } } diff --git a/src/main/java/generated/gov/cms/madie/simplexml/ArgumentsType.java b/src/main/java/generated/gov/cms/madie/simplexml/ArgumentsType.java index 9e43718..868babf 100644 --- a/src/main/java/generated/gov/cms/madie/simplexml/ArgumentsType.java +++ b/src/main/java/generated/gov/cms/madie/simplexml/ArgumentsType.java @@ -6,9 +6,10 @@ package generated.gov.cms.madie.simplexml; +import java.util.ArrayList; +import java.util.List; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; -import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlType; /** @@ -21,7 +22,7 @@ * * * - * + * * * * @@ -34,24 +35,29 @@ propOrder = {"argument"}) public class ArgumentsType { - @XmlElement(required = true) - protected ArgumentType argument; + protected List argument; /** * Gets the value of the argument property. * - * @return possible object is {@link ArgumentType } - */ - public ArgumentType getArgument() { - return argument; - } - - /** - * Sets the value of the argument property. + *

This accessor method returns a reference to the live list, not a snapshot. Therefore any + * modification you make to the returned list will be present inside the JAXB object. This is why + * there is not a set method for the argument property. + * + *

For example, to add a new item, do as follows: + * + *

+   * getArgument().add(newItem);
+   * 
+ * + *

Objects of the following type(s) are allowed in the list {@link ArgumentType } * - * @param value allowed object is {@link ArgumentType } + * @return The value of the argument property. */ - public void setArgument(ArgumentType value) { - this.argument = value; + public List getArgument() { + if (argument == null) { + argument = new ArrayList<>(); + } + return this.argument; } } diff --git a/src/main/java/generated/gov/cms/madie/simplexml/ParametersType.java b/src/main/java/generated/gov/cms/madie/simplexml/ParametersType.java index 3e0061a..84c668b 100644 --- a/src/main/java/generated/gov/cms/madie/simplexml/ParametersType.java +++ b/src/main/java/generated/gov/cms/madie/simplexml/ParametersType.java @@ -6,9 +6,10 @@ package generated.gov.cms.madie.simplexml; +import java.util.ArrayList; +import java.util.List; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; -import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlType; /** @@ -21,7 +22,7 @@ * * * - * + * * * * @@ -34,24 +35,29 @@ propOrder = {"parameter"}) public class ParametersType { - @XmlElement(required = true) - protected ParameterType parameter; + protected List parameter; /** * Gets the value of the parameter property. * - * @return possible object is {@link ParameterType } - */ - public ParameterType getParameter() { - return parameter; - } - - /** - * Sets the value of the parameter property. + *

This accessor method returns a reference to the live list, not a snapshot. Therefore any + * modification you make to the returned list will be present inside the JAXB object. This is why + * there is not a set method for the parameter property. + * + *

For example, to add a new item, do as follows: + * + *

+   * getParameter().add(newItem);
+   * 
+ * + *

Objects of the following type(s) are allowed in the list {@link ParameterType } * - * @param value allowed object is {@link ParameterType } + * @return The value of the parameter property. */ - public void setParameter(ParameterType value) { - this.parameter = value; + public List getParameter() { + if (parameter == null) { + parameter = new ArrayList<>(); + } + return this.parameter; } } diff --git a/src/main/java/gov/cms/madie/resources/PackageController.java b/src/main/java/gov/cms/madie/resources/PackageController.java index 0dfacf1..c6efbd9 100644 --- a/src/main/java/gov/cms/madie/resources/PackageController.java +++ b/src/main/java/gov/cms/madie/resources/PackageController.java @@ -7,6 +7,7 @@ import gov.cms.madie.services.PackagingService; import gov.cms.madie.models.measure.Measure; import gov.cms.madie.services.SimpleXmlService; +import gov.cms.madie.services.TranslationServiceClient; import jakarta.xml.bind.JAXBException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -28,6 +29,7 @@ public class PackageController { private final PackagingService packagingService; private final SimpleXmlService simpleXmlService; private final HqmfService hqmfService; + private final TranslationServiceClient translationServiceClient; @PutMapping( value = "/package", @@ -56,9 +58,9 @@ public String getMeasureSimpleXml( @RequestHeader("Authorization") String accessToken) throws JAXBException { if (measure.getModel() != null && measure.getModel().contains("QDM")) { - // TODO: replace this with fetch CqlLookups from translator - CqlLookups cqlLookups = CqlLookups.builder().build(); - return simpleXmlService.measureToSimpleXml((QdmMeasure) measure, cqlLookups); + QdmMeasure qdmMeasure = (QdmMeasure) measure; + CqlLookups cqlLookups = translationServiceClient.getCqlLookups(qdmMeasure, accessToken); + return simpleXmlService.measureToSimpleXml(qdmMeasure, cqlLookups); } throw new UnsupportedModelException("Unsupported model type: " + measure.getModel()); } diff --git a/src/main/java/gov/cms/madie/services/MeasureMapper.java b/src/main/java/gov/cms/madie/services/MeasureMapper.java index b85683d..bfe313c 100644 --- a/src/main/java/gov/cms/madie/services/MeasureMapper.java +++ b/src/main/java/gov/cms/madie/services/MeasureMapper.java @@ -1,6 +1,12 @@ package gov.cms.madie.services; import generated.gov.cms.madie.simplexml.*; +import gov.cms.madie.dto.CQLCode; +import gov.cms.madie.dto.CQLCodeSystem; +import gov.cms.madie.dto.CQLDefinition; +import gov.cms.madie.dto.CQLFunctionArgument; +import gov.cms.madie.dto.CQLParameter; +import gov.cms.madie.dto.CqlLookups; import gov.cms.madie.models.common.Organization; import gov.cms.madie.models.common.Version; import gov.cms.madie.models.measure.BaseConfigurationTypes; @@ -29,17 +35,20 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import java.util.stream.IntStream; @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface MeasureMapper { + @Mapping(target = "cqlLookUp", source = "cqlLookups") @Mapping(target = "measureDetails", source = "measure") @Mapping(target = "measureGrouping", source = "measure") @Mapping(target = "supplementalDataElements", source = "measure.supplementalData") @Mapping(target = "riskAdjustmentVariables", source = "measure.riskAdjustments") - MeasureType measureToMeasureType(QdmMeasure measure); + MeasureType measureToMeasureType(QdmMeasure measure, CqlLookups cqlLookups); @Mapping(target = "title", source = "measureName") @Mapping(target = "measureModel", source = "model") @@ -359,4 +368,108 @@ default FinalizedDateType instantToFinalizedDateType(Measure measure) { .format(measure.getLastModifiedAt())); return finalizedDateType; } + + @Mapping(target = "definitions", source = "definitions") + @Mapping(target = "functions", source = "definitions") + CqlLookUpType cqlLookupsToCqlLookUpType(CqlLookups cqlLookups); + + default CodeSystemsType cqlCodeSystemsToCodeSystemsType(Set codeSystems) { + if (!CollectionUtils.isEmpty(codeSystems)) { + CodeSystemsType codeSystemsType = new CodeSystemsType(); + codeSystemsType.getCodeSystem().addAll(cqlCodeSystemsToCodeSystems(codeSystems)); + return codeSystemsType; + } + + return null; + } + + default CodesType cqlCodesToCodesType(Set cqlCodes) { + if (!CollectionUtils.isEmpty(cqlCodes)) { + CodesType codesType = new CodesType(); + codesType.getCode().addAll(cqlCodesToCodes(cqlCodes)); + return codesType; + } + + return null; + } + + default ParametersType cqlParametersToParametersType(Set cqlParameters) { + if (!CollectionUtils.isEmpty(cqlParameters)) { + ParametersType parametersType = new ParametersType(); + parametersType.getParameter().addAll(cqlParametersToParameterTypes(cqlParameters)); + return parametersType; + } + return null; + } + + List cqlParametersToParameterTypes(Set cqlParameters); + + default DefinitionsType cqlDefinitionsToDefinitionsType(Set cqlDefinitions) { + if (!CollectionUtils.isEmpty(cqlDefinitions)) { + Set defsWithoutFuncs = + cqlDefinitions.stream().filter(d -> !d.isFunction()).collect(Collectors.toSet()); + if (!CollectionUtils.isEmpty(defsWithoutFuncs)) { + DefinitionsType definitionsType = new DefinitionsType(); + definitionsType.getDefinition().addAll(cqlDefinitionsToDefinitionTypes(defsWithoutFuncs)); + return definitionsType; + } + } + + return null; + } + + default FunctionsType cqlDefinitionsToFunctionsType(Set cqlDefinitions) { + if (!CollectionUtils.isEmpty(cqlDefinitions)) { + Set defsOnlyFuncs = + cqlDefinitions.stream().filter(CQLDefinition::isFunction).collect(Collectors.toSet()); + if (!CollectionUtils.isEmpty(defsOnlyFuncs)) { + FunctionsType functionsType = new FunctionsType(); + functionsType.getFunction().addAll(cqlDefinitionsToFunctionTypes(defsOnlyFuncs)); + return functionsType; + } + } + + return null; + } + + List cqlCodeSystemsToCodeSystems(Set codeSystems); + + List cqlCodesToCodes(Set cqlCodes); + + @Mapping( + target = "codeSystemOID", + expression = + "java(org.apache.commons.lang3.StringUtils.replaceChars(cqlCode.getCodeSystemOID(), \"urn:oid:\",\"\"))") + @Mapping(target = "codeOID", source = "id") + @Mapping(target = "isValidatedWithVsac", source = "isValidatedWithVsac") + @Mapping( + target = "isCodeSystemVersionIncluded", + expression = "java(String.valueOf(cqlCode.isCodeSystemVersionIncluded()))") + CodeType cqlCodeToCodeType(CQLCode cqlCode); + + List cqlDefinitionsToDefinitionTypes(Set cqlDefinitions); + + List cqlDefinitionsToFunctionTypes(Set cqlDefinitions); + + @Mapping(target = "logic", source = "definitionLogic") + DefinitionType cqlDefinitionToDefinitionType(CQLDefinition cqlDefinition); + + @Mapping(target = "logic", source = "definitionLogic") + @Mapping(target = "arguments", source = "functionArguments") + FunctionType cqlDefinitionToFunctionType(CQLDefinition cqlDefinition); + + default ArgumentsType functionArgumentsToArgumentsType( + List functionArguments) { + if (!CollectionUtils.isEmpty(functionArguments)) { + ArgumentsType argumentsType = new ArgumentsType(); + argumentsType.getArgument().addAll(functionArgumentsToArgumentTypes(functionArguments)); + return argumentsType; + } + return null; + } + + List functionArgumentsToArgumentTypes(List functionArguments); + + @Mapping(target = "type", source = "argumentType") + ArgumentType functionArgumentToArgumentType(CQLFunctionArgument functionArguments); } diff --git a/src/main/java/gov/cms/madie/services/SimpleXmlService.java b/src/main/java/gov/cms/madie/services/SimpleXmlService.java index cb0dff3..bacfbd7 100644 --- a/src/main/java/gov/cms/madie/services/SimpleXmlService.java +++ b/src/main/java/gov/cms/madie/services/SimpleXmlService.java @@ -24,7 +24,7 @@ public class SimpleXmlService { public String measureToSimpleXml(QdmMeasure measure, CqlLookups cqlLookups) throws JAXBException { StringWriter sw = new StringWriter(); if (measure != null) { - MeasureType measureType = measureMapper.measureToMeasureType(measure); + MeasureType measureType = measureMapper.measureToMeasureType(measure, cqlLookups); JAXBElement jaxbElement = new JAXBElement<>(new QName(null, "measure"), MeasureType.class, measureType); simpleXmlMarshaller.marshal(jaxbElement, sw); diff --git a/src/main/resources/schemas/SimpleXML-QDM-5-6.xsd b/src/main/resources/schemas/SimpleXML-QDM-5-6.xsd index d977c89..d0b69a2 100644 --- a/src/main/resources/schemas/SimpleXML-QDM-5-6.xsd +++ b/src/main/resources/schemas/SimpleXML-QDM-5-6.xsd @@ -75,7 +75,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -265,7 +265,7 @@ - + diff --git a/src/test/java/gov/cms/madie/resources/PackageControllerMvcTest.java b/src/test/java/gov/cms/madie/resources/PackageControllerMvcTest.java index 78646e8..7b95e15 100644 --- a/src/test/java/gov/cms/madie/resources/PackageControllerMvcTest.java +++ b/src/test/java/gov/cms/madie/resources/PackageControllerMvcTest.java @@ -93,7 +93,8 @@ void testGetMeasureSimpleXml() throws Exception { .contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(status().isOk()) .andReturn(); - verify(simpleXmlService, times(1)).measureToSimpleXml(any(QdmMeasure.class), any(CqlLookups.class)); + verify(simpleXmlService, times(1)) + .measureToSimpleXml(any(QdmMeasure.class), any(CqlLookups.class)); } @Test diff --git a/src/test/java/gov/cms/madie/services/HqmfServiceTest.java b/src/test/java/gov/cms/madie/services/HqmfServiceTest.java index 99303ca..332a035 100644 --- a/src/test/java/gov/cms/madie/services/HqmfServiceTest.java +++ b/src/test/java/gov/cms/madie/services/HqmfServiceTest.java @@ -52,7 +52,7 @@ void generateHqmf() throws Exception { when(simpleXmlService.measureToSimpleXml(any(QdmMeasure.class), any(CqlLookups.class))) .thenReturn(""); when(translationServiceClient.getCqlLookups(any(QdmMeasure.class), anyString())) - .thenReturn(CqlLookups.builder().build()); + .thenReturn(CqlLookups.builder().build()); HQMFGenerator generator = mock(HQMFGenerator.class); when(factory.getHQMFGenerator()).thenReturn(generator); @@ -66,7 +66,7 @@ void generateHqmf() throws Exception { @Test void generateHqmfWhenSimpleXmlGenerationFailed() throws Exception { when(translationServiceClient.getCqlLookups(any(QdmMeasure.class), anyString())) - .thenReturn(CqlLookups.builder().build()); + .thenReturn(CqlLookups.builder().build()); String message = "An issue occurred while generating the simple xml for measure"; doThrow(new JAXBException(message)) .when(simpleXmlService) diff --git a/src/test/java/gov/cms/madie/services/MeasureMapperTest.java b/src/test/java/gov/cms/madie/services/MeasureMapperTest.java index 45d29e6..125567b 100644 --- a/src/test/java/gov/cms/madie/services/MeasureMapperTest.java +++ b/src/test/java/gov/cms/madie/services/MeasureMapperTest.java @@ -8,6 +8,7 @@ import generated.gov.cms.madie.simplexml.ScoringType; import generated.gov.cms.madie.simplexml.StewardType; import generated.gov.cms.madie.simplexml.TypesType; +import gov.cms.madie.dto.CqlLookups; import gov.cms.madie.models.common.ModelType; import gov.cms.madie.models.common.Organization; import gov.cms.madie.models.common.Version; @@ -44,7 +45,7 @@ void setup() { @Test void testMeasureToMeasureTypeNull() { - MeasureType output = measureMapper.measureToMeasureType(null); + MeasureType output = measureMapper.measureToMeasureType(null, null); assertThat(output, is(nullValue())); } @@ -89,7 +90,10 @@ void testMeasureToMeasureType() { .build())) .build()) .build(); - MeasureType output = measureMapper.measureToMeasureType(measure); + + CqlLookups cqlLookups = CqlLookups.builder().build(); + + MeasureType output = measureMapper.measureToMeasureType(measure, cqlLookups); assertThat(output, is(notNullValue())); assertThat(output.getMeasureDetails(), is(notNullValue())); assertThat( diff --git a/src/test/java/gov/cms/madie/services/SimpleXmlServiceTest.java b/src/test/java/gov/cms/madie/services/SimpleXmlServiceTest.java index 4e0e923..ee71795 100644 --- a/src/test/java/gov/cms/madie/services/SimpleXmlServiceTest.java +++ b/src/test/java/gov/cms/madie/services/SimpleXmlServiceTest.java @@ -49,7 +49,8 @@ void testMeasureToSimpleXmlValidMeasure() throws JAXBException { CqlLookups cqlLookups = CqlLookups.builder().build(); - when(measureMapper.measureToMeasureType(any(QdmMeasure.class))).thenReturn(measureType); + when(measureMapper.measureToMeasureType(any(QdmMeasure.class), any(CqlLookups.class))) + .thenReturn(measureType); Mockito.doAnswer( invocationOnMock -> { StringWriter writer = invocationOnMock.getArgument(1);