diff --git a/pom.xml b/pom.xml index a0c0321e..abcc033e 100644 --- a/pom.xml +++ b/pom.xml @@ -205,6 +205,23 @@ 2.3.3 + + org.springframework + spring-context-support + + + + org.freemarker + freemarker + 2.3.32 + + + + gov.cms.madie + madie-java-models + 0.4.5-SNAPSHOT + + org.springframework.boot spring-boot-starter-tomcat @@ -229,28 +246,11 @@ - - org.springframework - spring-context-support - - org.springframework.security spring-security-test test - - - org.freemarker - freemarker - 2.3.32 - - - - gov.cms.madie - madie-java-models - 0.4.5-SNAPSHOT - @@ -299,7 +299,7 @@ - + diff --git a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableCodeModel.java b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableCodeModel.java index f726e990..c8f1ad70 100644 --- a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableCodeModel.java +++ b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableCodeModel.java @@ -5,141 +5,156 @@ @NoArgsConstructor public class HumanReadableCodeModel implements HumanReadableTerminologyModel { - private String name; - private String oid; - private String codesystemName; - private String codesystemVersion; - private boolean isCodesystemVersionIncluded; - private String datatype; - private String terminologyDisplay; - private String dataCriteriaDisplay; - - public HumanReadableCodeModel(String name, String oid, String codesystemName, boolean isCodeSystemVersionIncluded, String codesystemVersion, String datatype) { - this.name = name; - this.oid = oid; - this.codesystemName = codesystemName; - this.codesystemVersion = codesystemVersion; - this.isCodesystemVersionIncluded = isCodeSystemVersionIncluded; - this.datatype = datatype; - createDataCriteriaDisplay(); - createTerminologyDisplay(); - } - - @Override - public String getName() { - return name; - } - - @Override - public void setName(String name) { - this.name = name; - } - - public String getOid() { - return oid; - } - - public void setOid(String oid) { - this.oid = oid; - } - - public String getCodesystemName() { - return codesystemName; - } - - public void setCodesystemName(String taxonomy) { - this.codesystemName = taxonomy; - } - - public boolean getIsCodesystemVersionIncluded() { - return isCodesystemVersionIncluded; - } - - public void setIsCodesystemVersionIncluded(boolean isCodeSystemIncluded) { - this.isCodesystemVersionIncluded = isCodeSystemIncluded; - } - - public String getTerminologyDisplay() { - createTerminologyDisplay(); - return this.terminologyDisplay; - } - - private void createTerminologyDisplay() { - String codeSystemVersion = ""; - if (isCodesystemVersionIncluded) { - codeSystemVersion = " version " + codesystemVersion; - } - - String codeOutput = "code \"" + name + "\" (\"" + codesystemName + codeSystemVersion + " Code (" + oid - + ")\")"; - this.terminologyDisplay = codeOutput; - } - - @Override - public void setTerminologyDisplay(String display) { - this.terminologyDisplay = display; - } - - public String getCodesystemVersion() { - return codesystemVersion; - } - - public void setCodesystemVersion(String codesystemVersion) { - this.codesystemVersion = codesystemVersion; - } - - public String getDatatype() { - return datatype; - } - - public void setDatatype(String datatype) { - this.datatype = datatype; - } - - private void createDataCriteriaDisplay() { - if("attribute".equals(datatype)){ - datatype = "Attribute"; - } - - String output = ""; - if(isCodesystemVersionIncluded) { - output = String.format("\"%s: %s\" using \"%s (%s version %s Code %s)\"", datatype, name, name, codesystemName, codesystemVersion, oid); - } else { - output = String.format("\"%s: %s\" using \"%s (%s Code %s)\"", datatype, name, name, codesystemName, oid); - } - - this.dataCriteriaDisplay = output; - } - - @Override - public String getDataCriteriaDisplay() { - createDataCriteriaDisplay(); - return dataCriteriaDisplay; - } - - @Override - public void setDataCriteriaDisplay(String dataCriteriaDisplay) { - this.dataCriteriaDisplay = dataCriteriaDisplay; - } - - @Override - public int hashCode() { - return Objects.hash(name, oid, codesystemName, codesystemVersion, datatype); - } - - @Override - public boolean equals(Object obj) { - HumanReadableCodeModel model = (HumanReadableCodeModel) obj; - return name.equals(model.name) && oid.equals(model.oid) && codesystemName.equals(model.codesystemName) && codesystemVersion.equals(model.codesystemVersion) && isDatatypeEqual(datatype, model.datatype); - } - - private boolean isDatatypeEqual(String d1, String d2) { - // if datatype 1 is not null, then check the equality to datatype 2. - // if datatype 1 is null, then check to see if datatype 2 is null. - if(d1 != null) { - return d1.equals(d2); - } else { - return d2 == null; - } - } + private String name; + private String oid; + private String codesystemName; + private String codesystemVersion; + private boolean isCodesystemVersionIncluded; + private String datatype; + private String terminologyDisplay; + private String dataCriteriaDisplay; + + public HumanReadableCodeModel( + String name, + String oid, + String codesystemName, + boolean isCodeSystemVersionIncluded, + String codesystemVersion, + String datatype) { + this.name = name; + this.oid = oid; + this.codesystemName = codesystemName; + this.codesystemVersion = codesystemVersion; + this.isCodesystemVersionIncluded = isCodeSystemVersionIncluded; + this.datatype = datatype; + createDataCriteriaDisplay(); + createTerminologyDisplay(); + } + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + public String getOid() { + return oid; + } + + public void setOid(String oid) { + this.oid = oid; + } + + public String getCodesystemName() { + return codesystemName; + } + + public void setCodesystemName(String taxonomy) { + this.codesystemName = taxonomy; + } + + public boolean getIsCodesystemVersionIncluded() { + return isCodesystemVersionIncluded; + } + + public void setIsCodesystemVersionIncluded(boolean isCodeSystemIncluded) { + this.isCodesystemVersionIncluded = isCodeSystemIncluded; + } + + public String getTerminologyDisplay() { + createTerminologyDisplay(); + return this.terminologyDisplay; + } + + private void createTerminologyDisplay() { + String codeSystemVersion = ""; + if (isCodesystemVersionIncluded) { + codeSystemVersion = " version " + codesystemVersion; + } + + String codeOutput = + "code \"" + name + "\" (\"" + codesystemName + codeSystemVersion + " Code (" + oid + ")\")"; + this.terminologyDisplay = codeOutput; + } + + @Override + public void setTerminologyDisplay(String display) { + this.terminologyDisplay = display; + } + + public String getCodesystemVersion() { + return codesystemVersion; + } + + public void setCodesystemVersion(String codesystemVersion) { + this.codesystemVersion = codesystemVersion; + } + + public String getDatatype() { + return datatype; + } + + public void setDatatype(String datatype) { + this.datatype = datatype; + } + + private void createDataCriteriaDisplay() { + if ("attribute".equals(datatype)) { + datatype = "Attribute"; + } + + String output = ""; + if (isCodesystemVersionIncluded) { + output = + String.format( + "\"%s: %s\" using \"%s (%s version %s Code %s)\"", + datatype, name, name, codesystemName, codesystemVersion, oid); + } else { + output = + String.format( + "\"%s: %s\" using \"%s (%s Code %s)\"", datatype, name, name, codesystemName, oid); + } + + this.dataCriteriaDisplay = output; + } + + @Override + public String getDataCriteriaDisplay() { + createDataCriteriaDisplay(); + return dataCriteriaDisplay; + } + + @Override + public void setDataCriteriaDisplay(String dataCriteriaDisplay) { + this.dataCriteriaDisplay = dataCriteriaDisplay; + } + + @Override + public int hashCode() { + return Objects.hash(name, oid, codesystemName, codesystemVersion, datatype); + } + + @Override + public boolean equals(Object obj) { + HumanReadableCodeModel model = (HumanReadableCodeModel) obj; + return name.equals(model.name) + && oid.equals(model.oid) + && codesystemName.equals(model.codesystemName) + && codesystemVersion.equals(model.codesystemVersion) + && isDatatypeEqual(datatype, model.datatype); + } + + private boolean isDatatypeEqual(String d1, String d2) { + // if datatype 1 is not null, then check the equality to datatype 2. + // if datatype 1 is null, then check to see if datatype 2 is null. + if (d1 != null) { + return d1.equals(d2); + } else { + return d2 == null; + } + } } diff --git a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableExpressionModel.java b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableExpressionModel.java index 36134bb8..92fb8663 100644 --- a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableExpressionModel.java +++ b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableExpressionModel.java @@ -19,10 +19,13 @@ private String idFromName(String name) { StringBuilder result = new StringBuilder(); for (int i = 0; i < name.length(); i++) { char c = name.charAt(i); - if (c >= 48 && c <= 57 || //0-9 - c >= 65 && c <= 90 || //A-Z - c >= 97 && c <= 122 || //a-z - c == 95) { //_ + if (c >= 48 && c <= 57 + || // 0-9 + c >= 65 && c <= 90 + || // A-Z + c >= 97 && c <= 122 + || // a-z + c == 95) { // _ result.append(c); } else { result.append('_'); diff --git a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationCriteriaModel.java b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationCriteriaModel.java index 3548bf89..3e8e71bf 100644 --- a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationCriteriaModel.java +++ b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationCriteriaModel.java @@ -15,6 +15,5 @@ public class HumanReadablePopulationCriteriaModel { private String id; private int sequence; private List populations; - @Builder.Default - private String scoreUnit = ""; + @Builder.Default private String scoreUnit = ""; } diff --git a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationModel.java b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationModel.java index 742a70cb..d3b8ed24 100644 --- a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationModel.java +++ b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadablePopulationModel.java @@ -19,4 +19,5 @@ public class HumanReadablePopulationModel { private boolean inGroup; private String associatedPopulationName; private String display; - private String type; } + private String type; +} diff --git a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableTerminologyModel.java b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableTerminologyModel.java index 3973bed1..d93343ca 100644 --- a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableTerminologyModel.java +++ b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableTerminologyModel.java @@ -1,10 +1,19 @@ package gov.cms.madie.qdm.humanreadable.model; -public interface HumanReadableTerminologyModel { String getTerminologyDisplay(); +public interface HumanReadableTerminologyModel { + String getTerminologyDisplay(); + String getDataCriteriaDisplay(); + void setDataCriteriaDisplay(String display); + void setTerminologyDisplay(String display); + String getName(); + void setName(String name); + String getDatatype(); - void setDatatype(String datatype);} + + void setDatatype(String datatype); +} diff --git a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableValuesetModel.java b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableValuesetModel.java index 1b142149..1d261614 100644 --- a/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableValuesetModel.java +++ b/src/main/java/gov/cms/madie/qdm/humanreadable/model/HumanReadableValuesetModel.java @@ -50,7 +50,7 @@ public void setVersion(String version) { private void createTerminologyDisplay() { String output = ""; - if(StringUtils.isNotBlank(version) && !version.equalsIgnoreCase("1.0")) { + if (StringUtils.isNotBlank(version) && !version.equalsIgnoreCase("1.0")) { output = "valueset \"" + name + "\" (" + oid + ", version " + version + ")"; } else { output = "valueset \"" + name + "\" (" + oid + ")"; @@ -69,7 +69,7 @@ public void setTerminologyDisplay(String display) { } private void createtDataCriteriaDisplay() { - if( StringUtils.isBlank(name) && StringUtils.isBlank(oid)){ + if (StringUtils.isBlank(name) && StringUtils.isBlank(oid)) { this.dataCriteriaDisplay = '"' + datatype + '"'; } else { if ("attribute".equals(datatype)) { @@ -79,7 +79,9 @@ private void createtDataCriteriaDisplay() { String output = String.format("\"%s: %s\" using \"%s (%s)\"", datatype, name, name, oid); if (StringUtils.isNotBlank(version) && !version.equals("1.0") && !version.equals("1")) { - output = String.format("\"%s: %s\" using \"%s (%s, version %s)\"", datatype, name, name, oid, version); + output = + String.format( + "\"%s: %s\" using \"%s (%s, version %s)\"", datatype, name, name, oid, version); } this.dataCriteriaDisplay = output; @@ -113,13 +115,16 @@ public int hashCode() { @Override public boolean equals(Object obj) { HumanReadableValuesetModel model = (HumanReadableValuesetModel) obj; - return name.equals(model.name) && oid.equals(model.oid) && version.equals(model.version) && isDatatypeEqual(datatype, model.datatype); + return name.equals(model.name) + && oid.equals(model.oid) + && version.equals(model.version) + && isDatatypeEqual(datatype, model.datatype); } private boolean isDatatypeEqual(String d1, String d2) { // if datatype 1 is not null, then check the equality to datatype 2. // if datatype 1 is null, then check to see if datatype 2 is null. - if(d1 != null) { + if (d1 != null) { return d1.equals(d2); } else { return d2 == null; diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/controllers/CqlToolsController.java b/src/main/java/gov/cms/mat/cql_elm_translation/controllers/CqlToolsController.java index 4b49d0d7..c2117ea1 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/controllers/CqlToolsController.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/controllers/CqlToolsController.java @@ -1,17 +1,20 @@ package gov.cms.mat.cql_elm_translation.controllers; import gov.cms.mat.cql_elm_translation.data.DataCriteria; +import gov.cms.mat.cql_elm_translation.dto.SourceDataCriteria; import gov.cms.mat.cql_elm_translation.exceptions.CqlFormatException; import gov.cms.mat.cql_elm_translation.service.DataCriteriaService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.cqframework.cql.tools.formatter.CqlFormatterVisitor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.Principal; +import java.util.List; @Slf4j @RestController @@ -40,10 +43,15 @@ public ResponseEntity formatCql(@RequestBody String cqlData, Principal p @GetMapping("/cql/dataCriteria") public ResponseEntity getDataCriteria( - @RequestBody String cql, - @RequestHeader("Authorization") String accessToken) { + @RequestBody String cql, @RequestHeader("Authorization") String accessToken) { - return ResponseEntity.ok( - dataCriteriaService.parseDataCriteriaFromCql(cql, accessToken)); + return ResponseEntity.ok(dataCriteriaService.parseDataCriteriaFromCql(cql, accessToken)); + } + + @GetMapping("/cql/source-data-criteria") + public ResponseEntity> getSourceDataCriteria( + @RequestBody String cql, @RequestHeader("Authorization") String accessToken) { + return ResponseEntity.status(HttpStatus.OK) + .body(dataCriteriaService.getSourceDataCriteria(cql, accessToken)); } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/data/DataCriteria.java b/src/main/java/gov/cms/mat/cql_elm_translation/data/DataCriteria.java index 543ce2cc..5399133d 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/data/DataCriteria.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/data/DataCriteria.java @@ -15,11 +15,10 @@ @Builder @AllArgsConstructor @NoArgsConstructor -//TODO Move to madie java models +// TODO Move to madie java models public class DataCriteria { - @Builder.Default - private Map> dataCriteriaWithCodes = new HashMap<>(); + @Builder.Default private Map> dataCriteriaWithCodes = new HashMap<>(); + @Builder.Default private Map> dataCriteriaWithValueSets = new HashMap<>(); } - diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/data/RequestData.java b/src/main/java/gov/cms/mat/cql_elm_translation/data/RequestData.java index f0f61183..f452a44a 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/data/RequestData.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/data/RequestData.java @@ -9,7 +9,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; -@Builder +@Builder(toBuilder = true) public class RequestData { @Getter String cqlData; diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/dto/SourceDataCriteria.java b/src/main/java/gov/cms/mat/cql_elm_translation/dto/SourceDataCriteria.java new file mode 100644 index 00000000..a74705e1 --- /dev/null +++ b/src/main/java/gov/cms/mat/cql_elm_translation/dto/SourceDataCriteria.java @@ -0,0 +1,14 @@ +package gov.cms.mat.cql_elm_translation.dto; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class SourceDataCriteria { + private String codeListId; + private String qdmTitle; + private String description; + private String type; + private boolean drc; +} diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/service/DataCriteriaService.java b/src/main/java/gov/cms/mat/cql_elm_translation/service/DataCriteriaService.java index e03e9635..961620de 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/service/DataCriteriaService.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/service/DataCriteriaService.java @@ -3,11 +3,17 @@ import gov.cms.mat.cql_elm_translation.cql_translator.MadieLibrarySourceProvider; import gov.cms.mat.cql_elm_translation.data.DataCriteria; import gov.cms.mat.cql_elm_translation.data.RequestData; +import gov.cms.mat.cql_elm_translation.dto.SourceDataCriteria; import gov.cms.mat.cql_elm_translation.utils.cql.CQLTools; import gov.cms.mat.cql_elm_translation.utils.cql.parsing.CqlParserListener; +import gov.cms.mat.cql_elm_translation.utils.cql.parsing.model.CQLCode; import gov.cms.mat.cql_elm_translation.utils.cql.parsing.model.CQLModel; +import gov.cms.mat.cql_elm_translation.utils.cql.parsing.model.CQLValueSet; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.cqframework.cql.cql2elm.CqlTranslator; import org.cqframework.cql.cql2elm.LibraryBuilder; import org.cqframework.cql.cql2elm.model.CompiledLibrary; @@ -15,9 +21,12 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; @Slf4j @Service @@ -27,17 +36,17 @@ public class DataCriteriaService { private final CqlConversionService cqlConversionService; public DataCriteria parseDataCriteriaFromCql(String cql, String accessToken) { - //Run Translator to compile libraries + // Run Translator to compile libraries MadieLibrarySourceProvider librarySourceProvider = new MadieLibrarySourceProvider(); cqlConversionService.setUpLibrarySourceProvider(cql, accessToken); CqlTranslator cqlTranslator = runTranslator(cql); - CQLTools cqlTools = new CQLTools( - cql, - getIncludedLibrariesCql(librarySourceProvider, cqlTranslator), - getParentExpressions(cql), - cqlTranslator - ); + CQLTools cqlTools = + new CQLTools( + cql, + getIncludedLibrariesCql(librarySourceProvider, cqlTranslator), + getParentExpressions(cql), + cqlTranslator); try { cqlTools.generate(); @@ -47,13 +56,64 @@ public DataCriteria parseDataCriteriaFromCql(String cql, String accessToken) { return cqlTools.getDataCriteria(); } - private Map getIncludedLibrariesCql(MadieLibrarySourceProvider librarySourceProvider, - CqlTranslator cqlTranslator) { + public List getSourceDataCriteria(String cql, String accessToken) { + DataCriteria dataCriteria = parseDataCriteriaFromCql(cql, accessToken); + Map> criteriaWithValueSet = + dataCriteria.getDataCriteriaWithValueSets(); + if (MapUtils.isEmpty(criteriaWithValueSet)) { + return Collections.emptyList(); + } + // data criteria from value sets + List valueSetCriteria = + criteriaWithValueSet.entrySet().stream() + .map( + criteria -> + buildSourceDataCriteriaForValueSet(criteria.getKey(), criteria.getValue())) + .collect(Collectors.toList()); + + // data criteria from direct reference codes + Map> criteriaWithCodes = dataCriteria.getDataCriteriaWithCodes(); + List codeCriteria = + criteriaWithCodes.entrySet().stream() + .map(criteria -> buildSourceDataCriteriaForCode(criteria.getKey(), criteria.getValue())) + .toList(); + + valueSetCriteria.addAll(codeCriteria); + return valueSetCriteria; + } + + private SourceDataCriteria buildSourceDataCriteriaForCode(CQLCode code, Set dataTypes) { + String dataType = dataTypes.stream().findFirst().orElse(null); + // e.g "Encounter, Performed" becomes "EncounterPerformed" + String type = dataType.replace(",", "").replace(" ", ""); + return SourceDataCriteria.builder() + // generate fake code list id for drc, as it doesn't have one + .codeListId("drc-" + DigestUtils.md5Hex(type)) + .qdmTitle(code.getName()) + .description(dataType + ": " + code.getName()) + .type(type) + .drc(true) + .build(); + } + + private SourceDataCriteria buildSourceDataCriteriaForValueSet( + CQLValueSet valueSet, Set dataTypes) { + String dataType = dataTypes.stream().findFirst().orElse(null); + return SourceDataCriteria.builder() + .codeListId(valueSet.getOid()) + .qdmTitle(valueSet.getName()) + .description(dataType + ": " + valueSet.getName()) + .type(dataType.replace(",", "").replace(" ", "")) + .build(); + } + + private Map getIncludedLibrariesCql( + MadieLibrarySourceProvider librarySourceProvider, CqlTranslator cqlTranslator) { Map includedLibrariesCql = new HashMap<>(); for (CompiledLibrary l : cqlTranslator.getTranslatedLibraries().values()) { try { includedLibrariesCql.putIfAbsent( - l.getIdentifier().getId() +"-"+l.getIdentifier().getVersion(), + l.getIdentifier().getId() + "-" + l.getIdentifier().getVersion(), new String( librarySourceProvider .getLibrarySource(l.getLibrary().getIdentifier()) diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/service/HumanReadableService.java b/src/main/java/gov/cms/mat/cql_elm_translation/service/HumanReadableService.java index 5081d0b4..f3c8c555 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/service/HumanReadableService.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/service/HumanReadableService.java @@ -29,6 +29,7 @@ public class HumanReadableService { /** * Transforms MADiE Measure to the QDM HumanReadable data model, then generates the HR HTML. + * * @param measure MADiE Measure * @return String QDM Human Readable HTML * @throws TemplateException bad end @@ -50,6 +51,7 @@ public String generate(Measure measure) throws TemplateException, IOException { /** * Full HR Generation. + * * @param model * @return * @throws IOException @@ -59,40 +61,51 @@ public String generate(HumanReadable model) throws IOException, TemplateExceptio Map paramsMap = new HashMap<>(); paramsMap.put("model", model); setMeasurementPeriodForQdm(model.getMeasureInformation()); - return FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerConfiguration.getTemplate("humanreadable/human_readable.ftl"), paramsMap); + return FreeMarkerTemplateUtils.processTemplateIntoString( + freemarkerConfiguration.getTemplate("humanreadable/human_readable.ftl"), paramsMap); } - public String generateSinglePopulation(HumanReadablePopulationModel population) throws IOException, TemplateException { + public String generateSinglePopulation(HumanReadablePopulationModel population) + throws IOException, TemplateException { Map paramsMap = new HashMap<>(); paramsMap.put("population", population); - return FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerConfiguration.getTemplate("humanreadable/population_human_readable.ftl"), paramsMap); + return FreeMarkerTemplateUtils.processTemplateIntoString( + freemarkerConfiguration.getTemplate("humanreadable/population_human_readable.ftl"), + paramsMap); } /** * Truncated HR originally displayed on MAT's Measure Details page. + * * @param measureInformationModel * @param measureModel * @return * @throws IOException * @throws TemplateException */ - public String generate(HumanReadableMeasureInformationModel measureInformationModel, String measureModel) throws IOException, TemplateException { + public String generate( + HumanReadableMeasureInformationModel measureInformationModel, String measureModel) + throws IOException, TemplateException { HumanReadable model = new HumanReadable(); model.setMeasureInformation(measureInformationModel); Map paramsMap = new HashMap<>(); paramsMap.put("model", model); - return FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerConfiguration.getTemplate("humanreadable/human_readable_measuredetails.ftl"), paramsMap); + return FreeMarkerTemplateUtils.processTemplateIntoString( + freemarkerConfiguration.getTemplate("humanreadable/human_readable_measuredetails.ftl"), + paramsMap); } private void setMeasurementPeriodForQdm(HumanReadableMeasureInformationModel model) { boolean isCalendarYear = model.isCalendarYear(); String measurementPeriodStartDate = model.getMeasurementPeriodStartDate(); String measurementPeriodEndDate = model.getMeasurementPeriodEndDate(); - model.setMeasurementPeriod(HumanReadableDateUtil.getFormattedMeasurementPeriod(isCalendarYear, measurementPeriodStartDate, measurementPeriodEndDate)); + model.setMeasurementPeriod( + HumanReadableDateUtil.getFormattedMeasurementPeriod( + isCalendarYear, measurementPeriodStartDate, measurementPeriodEndDate)); } private HumanReadableMeasureInformationModel buildMeasureInfo(Measure measure) { - //TODO Needs safety checks + // TODO Needs safety checks return HumanReadableMeasureInformationModel.builder() .qdmVersion(5.6) // TODO Replace hardcode .ecqmTitle(measure.getEcqmTitle()) @@ -106,7 +119,8 @@ private HumanReadableMeasureInformationModel buildMeasureInfo(Measure measure) { DateFormat.getDateInstance().format(measure.getMeasurementPeriodStart())) .measurementPeriodEndDate( DateFormat.getDateInstance().format(measure.getMeasurementPeriodEnd())) - .measureScoring(measure.getGroups().get(0).getScoring()) //All groups expected to have same scoring + .measureScoring( + measure.getGroups().get(0).getScoring()) // All groups expected to have same scoring .description(measure.getMeasureMetaData().getDescription()) .copyright(measure.getMeasureMetaData().getCopyright()) .disclaimer(measure.getMeasureMetaData().getDisclaimer()) @@ -117,23 +131,27 @@ private HumanReadableMeasureInformationModel buildMeasureInfo(Measure measure) { private List buildPopCriteria(Measure measure) { return measure.getGroups().stream() - .map(group -> HumanReadablePopulationCriteriaModel.builder() - .id(group.getId()) - .name(group.getGroupDescription()) - .populations(buildPopulations(group)) - .build()) + .map( + group -> + HumanReadablePopulationCriteriaModel.builder() + .id(group.getId()) + .name(group.getGroupDescription()) + .populations(buildPopulations(group)) + .build()) .collect(Collectors.toList()); } private List buildPopulations(Group group) { return group.getPopulations().stream() - .map(population -> HumanReadablePopulationModel.builder() - .name(population.getName().name()) - .id(population.getId()) - .display(population.getName().getDisplay()) - .logic(population.getDefinition()) - .expressionName(population.getDefinition()) - .build()) + .map( + population -> + HumanReadablePopulationModel.builder() + .name(population.getName().name()) + .id(population.getId()) + .display(population.getName().getDisplay()) + .logic(population.getDefinition()) + .expressionName(population.getDefinition()) + .build()) .collect(Collectors.toList()); } @@ -144,5 +162,4 @@ private List buildDefinitions(Measure measure) { private List buildValueSetCriteriaList(Measure measure) { return List.of(new HumanReadableValuesetModel()); } - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/HumanReadableDateUtil.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/HumanReadableDateUtil.java index 0f9caa22..79185411 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/HumanReadableDateUtil.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/HumanReadableDateUtil.java @@ -2,12 +2,13 @@ public class HumanReadableDateUtil { - public static String getFormattedMeasurementPeriod(boolean isCalendarYear, String startDate, String endDate) { + public static String getFormattedMeasurementPeriod( + boolean isCalendarYear, String startDate, String endDate) { String formattedStartDate = " "; String formattedEndDate = " "; String through = " through "; // if start or end are not null format the date - if(!isCalendarYear){ + if (!isCalendarYear) { if (!" ".equals(startDate)) { formattedStartDate = formatDate(startDate); } @@ -88,9 +89,11 @@ public static String getFormattedMeasurementPeriodForFhir(String startDate, Stri String[] startDateMonth = startDate.split("/"); String[] endDateMonth = endDate.split("/"); - String formattedStartDate = getMonth(startDateMonth[0]) + " " + startDateMonth[1] + ", " + startDateMonth[2]; - String formattedEndDate = getMonth(endDateMonth[0]) + " " + endDateMonth[1] + ", " + endDateMonth[2]; + String formattedStartDate = + getMonth(startDateMonth[0]) + " " + startDateMonth[1] + ", " + startDateMonth[2]; + String formattedEndDate = + getMonth(endDateMonth[0]) + " " + endDateMonth[1] + ", " + endDateMonth[2]; - return formattedStartDate + " through "+ formattedEndDate; + return formattedStartDate + " through " + formattedEndDate; } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLTools.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLTools.java index 0fa9b1b3..d0589bec 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLTools.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLTools.java @@ -32,498 +32,544 @@ public class CQLTools { - private String parentLibraryString; - private Map childrenLibraries; - private CompiledLibrary library; - private CqlTranslator translator; - - /** - * Maps a valueset identifier to the datatypes it is using. - */ - private Map> valuesetDataTypeMap = new HashMap<>(); - - /** - * Maps a code identifier to the datatypes it is using - */ - private Map> codeDataTypeMap = new HashMap<>(); - - /** - * Maps an expression, to it's internal valueset - datatype map - */ - private Map>> expressionNameToValuesetDataTypeMap = new HashMap<>(); - - /** - * Maps an expression, to it's internal code - datatype map - */ - private Map>> expressionNameToCodeDataTypeMap = new HashMap<>(); - - - /** - * Maps an expression name to its return type (only function and definitions) - */ - private Map nameToReturnTypeMap = new HashMap<>(); - - /** - * The list of parent expressions. Often times, these are populations from MAT. Anything that can be reached from - * this node in the graph should be considered used. - */ - private List parentExpressions = new ArrayList<>(); - - private Map qdmTypeInfoMap = new HashMap<>(); - - private Map CompiledLibraryMap; - - /** - * Map in the form of >. - */ - private Map> allNamesToReturnTypeMap = new HashMap<>(); - - private Map expressionToReturnTypeMap = new HashMap<>(); - - // used expression sets - Set usedLibraries = new HashSet<>(); - Set usedCodes = new HashSet<>(); - Set usedValuesets = new HashSet<>(); - Set usedParameters = new HashSet<>(); - Set usedDefinitions = new HashSet<>(); - Set usedFunctions = new HashSet<>(); - Set usedCodeSystems = new HashSet<>(); - DataCriteria dataCriteria = new DataCriteria(); - - - public CQLTools( - String parentLibraryString, - Map childrenLibraries, - List parentExpressions, - CqlTranslator translator - ) { - this( - parentLibraryString, - childrenLibraries, - parentExpressions, - translator, - translator.getTranslatedLibraries()); - } - public CQLTools( - String parentLibraryString, - Map childrenLibraries, - List parentExpressions, - CqlTranslator translator, - Map translatedLibraries) { - - this.parentLibraryString = parentLibraryString; - this.translator = translator; - this.library = translator.getTranslatedLibrary(); - this.childrenLibraries = childrenLibraries; - this.CompiledLibraryMap = translatedLibraries; - this.parentExpressions = parentExpressions; - } - - /** - * The CQL Filter Entry Point. - *

- * This function will find all of the used CQL expressions, create a valueset - datatype map and code - datatype map, - * and find return types for each expression. - * - * @throws IOException - */ - public void generate() throws IOException { - InputStream stream = new ByteArrayInputStream(this.parentLibraryString.getBytes(StandardCharsets.UTF_8)); - cqlLexer lexer = new cqlLexer(CharStreams.fromStream(stream)); - CommonTokenStream tokens = new CommonTokenStream(lexer); - cqlParser parser = new cqlParser(tokens); - - CQLGraph graph = new CQLGraph(); - Cql2ElmListener listener = new Cql2ElmListener(graph, library, CompiledLibraryMap, childrenLibraries); - ParseTree tree = parser.library(); - CqlPreprocessorVisitor preprocessor = new CqlPreprocessorVisitor(); - preprocessor.setTokenStream(tokens); - preprocessor.visit(tree); - ParseTreeWalker walker = new ParseTreeWalker(); - walker.walk(listener, tree); - - Set librariesSet = new HashSet<>(listener.getLibraries()); - Set valuesetsSet = new HashSet<>(listener.getValuesets()); - Set codesSet = new HashSet<>(listener.getCodes()); - Set codesystemsSet = new HashSet<>(listener.getCodesystems()); - Set parametersSet = new HashSet<>(listener.getParameters()); - Set definitionsSet = new HashSet<>(listener.getDefinitions()); - Set functionsSet = new HashSet<>(listener.getFunctions()); - Map>> valuesetMap = new HashMap<>(listener.getValueSetDataTypeMap()); - Map>> codeMap = new HashMap<>(listener.getCodeDataTypeMap()); - Map valueSetOids = new HashMap<>(listener.getValueSetOids()); - - collectUsedExpressions(graph, librariesSet, valuesetsSet, codesSet, codesystemsSet, parametersSet, definitionsSet, functionsSet); - collectValueSetCodeDataType(valuesetMap, codeMap); - collectReturnTypeMap(); - collectDataCriteria(valueSetOids); - } - private void collectDataCriteria(Map valueSetOids) { - valuesetDataTypeMap.keySet().forEach(vs -> - dataCriteria.getDataCriteriaWithValueSets().put( - CQLValueSet.builder() - .name(vs) - .oid(valueSetOids.get(vs)) - .build(), - valuesetDataTypeMap.get(vs))); - - codeDataTypeMap.keySet().forEach(code -> - dataCriteria.getDataCriteriaWithCodes().put( - CQLCode.builder() - .codeName(code) - //TODO lookup code & code system details - .codeOID("shrug") - .codeSystemName("shrug") - .codeSystemOID("shrug") - .build(), - codeDataTypeMap.get(code))); - } - - private void collectUsedExpressions(CQLGraph graph, Set librariesSet, Set valuesetsSet, Set codesSet, - Set codesystemsSet, Set parametersSet, Set definitionsSet, - Set functionsSet) { - List libraries = new ArrayList<>(librariesSet); - List valuesets = new ArrayList<>(valuesetsSet); - List codes = new ArrayList<>(codesSet); - List codesystems = new ArrayList<>(codesystemsSet); - List parameters = new ArrayList<>(parametersSet); - List definitions = new ArrayList<>(definitionsSet); - List functions = new ArrayList<>(functionsSet); - - for (String parentExpression : parentExpressions) { - collectUsedLibraries(graph, libraries, parentExpression); - collectUsedValuesets(graph, valuesets, parentExpression); - collectUsedCodes(graph, codes, parentExpression); - collectUsedCodeSystems(graph, codesystems, parentExpression); - collectUsedParameters(graph, parameters, parentExpression); - collectUsedDefinitions(graph, definitions, parentExpression); - collectUsedFunctions(graph, functions, parentExpression); - } - } - - /** - * For every function reference from the listener, checks if the parent expression and the function make a path. - * If it does make a path, that means the function is used and should therefore be added to the used functions list. - * - * @param graph the graph - * @param functions the function references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedFunctions(CQLGraph graph, List functions, String parentExpression) { - for (String function : functions) { - if (graph.isPath(parentExpression, function)) { - usedFunctions.add(function); - } - } - } - - /** - * For every definition reference from the listener, checks if the parent expression and the definition make a path. - * If it does make a path, that means the definition is used and should therefore be added to the used definitions list. - * - * @param graph the graph - * @param definitions the definition references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedDefinitions(CQLGraph graph, List definitions, String parentExpression) { - for (String definition : definitions) { - if (graph.isPath(parentExpression, definition) && !definition.equalsIgnoreCase("Patient") && !definition.equalsIgnoreCase("Population")) { - usedDefinitions.add(definition); - } - } - } - - /** - * For every parameter reference from the listener, checks if the parent expression and the parameter make a path. - * If it does make a path, that means the parameter is used and should therefore be added to the used parameters list. - * - * @param graph the graph - * @param parameters the parameter references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedParameters(CQLGraph graph, List parameters, String parentExpression) { - for (String parameter : parameters) { - if (graph.isPath(parentExpression, parameter)) { - usedParameters.add(parameter); - } - } - } - - /** - * For every code reference from the listener, checks if the parent expression and the code make a path. - * If it does make a path, that means the code is used and should therefore be added to the used codes list. - * - * @param graph the graph - * @param codes the code references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedCodes(CQLGraph graph, List codes, String parentExpression) { - for (String code : codes) { - if (graph.isPath(parentExpression, code)) { - usedCodes.add(code); - } - } - } - - /** - * For every codesystem reference from the listener, checks if the parent expression and the codesystem make a path. - * If it does make a path, that means the codesystem is used and should therefore be added to the used codesystems list. - * - * @param graph the graph - * @param codesystems the code references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedCodeSystems(CQLGraph graph, List codesystems, String parentExpression) { - for (String codesystem : codesystems) { - if (graph.isPath(parentExpression, codesystem)) { - usedCodeSystems.add(codesystem); - } - } - } - - /** - * For every valueset reference from the listener, checks if the parent expression and the valueset make a path. - * If it does make a path, that means the valueset is used and should therefore be added to the used valuesets list. - * - * @param graph the graph - * @param valuesets the valueset references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedValuesets(CQLGraph graph, List valuesets, String parentExpression) { - for (String valueset : valuesets) { - if (graph.isPath(parentExpression, valueset)) { - usedValuesets.add(valueset); - } + private String parentLibraryString; + private Map childrenLibraries; + private CompiledLibrary library; + private CqlTranslator translator; + + /** Maps a valueset identifier to the datatypes it is using. */ + private Map> valuesetDataTypeMap = new HashMap<>(); + + /** Maps a code identifier to the datatypes it is using */ + private Map> codeDataTypeMap = new HashMap<>(); + + /** Maps an expression, to it's internal valueset - datatype map */ + private Map>> expressionNameToValuesetDataTypeMap = + new HashMap<>(); + + /** Maps an expression, to it's internal code - datatype map */ + private Map>> expressionNameToCodeDataTypeMap = new HashMap<>(); + + /** Maps an expression name to its return type (only function and definitions) */ + private Map nameToReturnTypeMap = new HashMap<>(); + + /** + * The list of parent expressions. Often times, these are populations from MAT. Anything that can + * be reached from this node in the graph should be considered used. + */ + private List parentExpressions = new ArrayList<>(); + + private Map qdmTypeInfoMap = new HashMap<>(); + + private Map CompiledLibraryMap; + + /** Map in the form of >. */ + private Map> allNamesToReturnTypeMap = new HashMap<>(); + + private Map expressionToReturnTypeMap = new HashMap<>(); + + // used expression sets + Set usedLibraries = new HashSet<>(); + Set usedCodes = new HashSet<>(); + Set usedValuesets = new HashSet<>(); + Set usedParameters = new HashSet<>(); + Set usedDefinitions = new HashSet<>(); + Set usedFunctions = new HashSet<>(); + Set usedCodeSystems = new HashSet<>(); + DataCriteria dataCriteria = new DataCriteria(); + + public CQLTools( + String parentLibraryString, + Map childrenLibraries, + List parentExpressions, + CqlTranslator translator) { + this( + parentLibraryString, + childrenLibraries, + parentExpressions, + translator, + translator.getTranslatedLibraries()); + } + + public CQLTools( + String parentLibraryString, + Map childrenLibraries, + List parentExpressions, + CqlTranslator translator, + Map translatedLibraries) { + + this.parentLibraryString = parentLibraryString; + this.translator = translator; + this.library = translator.getTranslatedLibrary(); + this.childrenLibraries = childrenLibraries; + this.CompiledLibraryMap = translatedLibraries; + this.parentExpressions = parentExpressions; + } + + /** + * The CQL Filter Entry Point. + * + *

This function will find all of the used CQL expressions, create a valueset - datatype map + * and code - datatype map, and find return types for each expression. + * + * @throws IOException + */ + public void generate() throws IOException { + InputStream stream = + new ByteArrayInputStream(this.parentLibraryString.getBytes(StandardCharsets.UTF_8)); + cqlLexer lexer = new cqlLexer(CharStreams.fromStream(stream)); + CommonTokenStream tokens = new CommonTokenStream(lexer); + cqlParser parser = new cqlParser(tokens); + + CQLGraph graph = new CQLGraph(); + Cql2ElmListener listener = + new Cql2ElmListener(graph, library, CompiledLibraryMap, childrenLibraries); + ParseTree tree = parser.library(); + CqlPreprocessorVisitor preprocessor = new CqlPreprocessorVisitor(); + preprocessor.setTokenStream(tokens); + preprocessor.visit(tree); + ParseTreeWalker walker = new ParseTreeWalker(); + walker.walk(listener, tree); + + Set librariesSet = new HashSet<>(listener.getLibraries()); + Set valuesetsSet = new HashSet<>(listener.getValuesets()); + Set codesSet = new HashSet<>(listener.getCodes()); + Set codesystemsSet = new HashSet<>(listener.getCodesystems()); + Set parametersSet = new HashSet<>(listener.getParameters()); + Set definitionsSet = new HashSet<>(listener.getDefinitions()); + Set functionsSet = new HashSet<>(listener.getFunctions()); + Map>> valuesetMap = + new HashMap<>(listener.getValueSetDataTypeMap()); + Map>> codeMap = new HashMap<>(listener.getCodeDataTypeMap()); + Map valueSetOids = new HashMap<>(listener.getValueSetOids()); + + collectUsedExpressions( + graph, + librariesSet, + valuesetsSet, + codesSet, + codesystemsSet, + parametersSet, + definitionsSet, + functionsSet); + collectValueSetCodeDataType(valuesetMap, codeMap); + collectReturnTypeMap(); + collectDataCriteria(valueSetOids); + } + + private void collectDataCriteria(Map valueSetOids) { + valuesetDataTypeMap + .keySet() + .forEach( + vs -> + dataCriteria + .getDataCriteriaWithValueSets() + .put( + CQLValueSet.builder().name(vs).oid(valueSetOids.get(vs)).build(), + valuesetDataTypeMap.get(vs))); + + codeDataTypeMap + .keySet() + .forEach( + code -> + dataCriteria + .getDataCriteriaWithCodes() + .put( + CQLCode.builder() + .codeName(code) + // TODO lookup code & code system details + .codeOID("shrug") + .codeSystemName("shrug") + .codeSystemOID("shrug") + .build(), + codeDataTypeMap.get(code))); + } + + private void collectUsedExpressions( + CQLGraph graph, + Set librariesSet, + Set valuesetsSet, + Set codesSet, + Set codesystemsSet, + Set parametersSet, + Set definitionsSet, + Set functionsSet) { + List libraries = new ArrayList<>(librariesSet); + List valuesets = new ArrayList<>(valuesetsSet); + List codes = new ArrayList<>(codesSet); + List codesystems = new ArrayList<>(codesystemsSet); + List parameters = new ArrayList<>(parametersSet); + List definitions = new ArrayList<>(definitionsSet); + List functions = new ArrayList<>(functionsSet); + + for (String parentExpression : parentExpressions) { + collectUsedLibraries(graph, libraries, parentExpression); + collectUsedValuesets(graph, valuesets, parentExpression); + collectUsedCodes(graph, codes, parentExpression); + collectUsedCodeSystems(graph, codesystems, parentExpression); + collectUsedParameters(graph, parameters, parentExpression); + collectUsedDefinitions(graph, definitions, parentExpression); + collectUsedFunctions(graph, functions, parentExpression); + } + } + + /** + * For every function reference from the listener, checks if the parent expression and the + * function make a path. If it does make a path, that means the function is used and should + * therefore be added to the used functions list. + * + * @param graph the graph + * @param functions the function references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedFunctions( + CQLGraph graph, List functions, String parentExpression) { + for (String function : functions) { + if (graph.isPath(parentExpression, function)) { + usedFunctions.add(function); + } + } + } + + /** + * For every definition reference from the listener, checks if the parent expression and the + * definition make a path. If it does make a path, that means the definition is used and should + * therefore be added to the used definitions list. + * + * @param graph the graph + * @param definitions the definition references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedDefinitions( + CQLGraph graph, List definitions, String parentExpression) { + for (String definition : definitions) { + if (graph.isPath(parentExpression, definition) + && !definition.equalsIgnoreCase("Patient") + && !definition.equalsIgnoreCase("Population")) { + usedDefinitions.add(definition); + } + } + } + + /** + * For every parameter reference from the listener, checks if the parent expression and the + * parameter make a path. If it does make a path, that means the parameter is used and should + * therefore be added to the used parameters list. + * + * @param graph the graph + * @param parameters the parameter references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedParameters( + CQLGraph graph, List parameters, String parentExpression) { + for (String parameter : parameters) { + if (graph.isPath(parentExpression, parameter)) { + usedParameters.add(parameter); + } + } + } + + /** + * For every code reference from the listener, checks if the parent expression and the code make a + * path. If it does make a path, that means the code is used and should therefore be added to the + * used codes list. + * + * @param graph the graph + * @param codes the code references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedCodes(CQLGraph graph, List codes, String parentExpression) { + for (String code : codes) { + if (graph.isPath(parentExpression, code)) { + usedCodes.add(code); + } + } + } + + /** + * For every codesystem reference from the listener, checks if the parent expression and the + * codesystem make a path. If it does make a path, that means the codesystem is used and should + * therefore be added to the used codesystems list. + * + * @param graph the graph + * @param codesystems the code references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedCodeSystems( + CQLGraph graph, List codesystems, String parentExpression) { + for (String codesystem : codesystems) { + if (graph.isPath(parentExpression, codesystem)) { + usedCodeSystems.add(codesystem); + } + } + } + + /** + * For every valueset reference from the listener, checks if the parent expression and the + * valueset make a path. If it does make a path, that means the valueset is used and should + * therefore be added to the used valuesets list. + * + * @param graph the graph + * @param valuesets the valueset references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedValuesets( + CQLGraph graph, List valuesets, String parentExpression) { + for (String valueset : valuesets) { + if (graph.isPath(parentExpression, valueset)) { + usedValuesets.add(valueset); + } + } + } + + /** + * For every library reference from the listener, checks if the parent expression and the library + * make a path. If it does make a path, that means the library is used and should therefore be + * added to the used libraries list. + * + * @param graph the graph + * @param libraries the library references from the listener + * @param parentExpression the parent expression to check + */ + private void collectUsedLibraries( + CQLGraph graph, List libraries, String parentExpression) { + for (String library : libraries) { + if (graph.isPath(parentExpression, library)) { + usedLibraries.add(library); + } + } + } + + /** Collects and creates a mapping of expression names to return types. */ + private void collectReturnTypeMap() { + // the following makes an assumption that a library can not have any duplicate libraries + // declared in it. + + // statements contain all function and definitions. + Library.Statements statements = this.library.getLibrary().getStatements(); + Library.Parameters parameters = this.library.getLibrary().getParameters(); + String libraryName = this.library.getIdentifier().getId(); + String libraryVersion = this.library.getIdentifier().getVersion(); + this.allNamesToReturnTypeMap.put(libraryName + "-" + libraryVersion, new HashMap<>()); + + for (ExpressionDef expression : statements.getDef()) { + this.allNamesToReturnTypeMap + .get(libraryName + "-" + libraryVersion) + .put(expression.getName(), expression.getResultType().toString()); + this.nameToReturnTypeMap.put(expression.getName(), expression.getResultType().toString()); + this.expressionToReturnTypeMap.put( + expression.getName(), expression.getResultType().toString()); + } + + if (parameters != null) { + for (ParameterDef parameter : parameters.getDef()) { + this.allNamesToReturnTypeMap + .get(libraryName + "-" + libraryVersion) + .put(parameter.getName(), parameter.getResultType().toString()); + this.nameToReturnTypeMap.put(parameter.getName(), parameter.getResultType().toString()); + this.expressionToReturnTypeMap.put( + parameter.getName(), parameter.getResultType().toString()); + } + } + + if (null != this.library.getLibrary().getIncludes()) { + for (IncludeDef include : this.library.getLibrary().getIncludes().getDef()) { + // CompiledLibrary lib = this.CompiledLibraryMap.get(include.getPath() + "-" + // + include.getVersion()); + CompiledLibrary lib = this.CompiledLibraryMap.get(include.getPath()); + + Library.Statements statementsFromIncludedLibrary = lib.getLibrary().getStatements(); + Library.Parameters parametersFromIncludedLibrary = lib.getLibrary().getParameters(); + String includedLibraryName = lib.getIdentifier().getId(); + String includedLibraryVersion = lib.getIdentifier().getVersion(); + this.allNamesToReturnTypeMap.put( + includedLibraryName + "-" + includedLibraryVersion, new HashMap<>()); + + for (ExpressionDef expression : statementsFromIncludedLibrary.getDef()) { + this.allNamesToReturnTypeMap + .get(includedLibraryName + "-" + includedLibraryVersion) + .put(expression.getName(), expression.getResultType().toString()); + this.expressionToReturnTypeMap.put( + include.getLocalIdentifier() + "." + expression.getName(), + expression.getResultType().toString()); } - } - /** - * For every library reference from the listener, checks if the parent expression and the library make a path. - * If it does make a path, that means the library is used and should therefore be added to the used libraries list. - * - * @param graph the graph - * @param libraries the library references from the listener - * @param parentExpression the parent expression to check - */ - private void collectUsedLibraries(CQLGraph graph, List libraries, String parentExpression) { - for (String library : libraries) { - if (graph.isPath(parentExpression, library)) { - usedLibraries.add(library); - } + if (parametersFromIncludedLibrary != null) { + for (ParameterDef parameter : parametersFromIncludedLibrary.getDef()) { + this.allNamesToReturnTypeMap + .get(includedLibraryName + "-" + includedLibraryVersion) + .put(parameter.getName(), parameter.getResultType().toString()); + this.expressionToReturnTypeMap.put( + include.getLocalIdentifier() + "." + parameter.getName(), + parameter.getResultType().toString()); + } } + } } + } - /** - * Collects and creates a mapping of expression names to return types. - */ - private void collectReturnTypeMap() { - // the following makes an assumption that a library can not have any duplicate libraries declared in it. - - // statements contain all function and definitions. - Library.Statements statements = this.library.getLibrary().getStatements(); - Library.Parameters parameters = this.library.getLibrary().getParameters(); - String libraryName = this.library.getIdentifier().getId(); - String libraryVersion = this.library.getIdentifier().getVersion(); - this.allNamesToReturnTypeMap.put(libraryName + "-" + libraryVersion, new HashMap<>()); - - for (ExpressionDef expression : statements.getDef()) { - this.allNamesToReturnTypeMap.get(libraryName + "-" + libraryVersion).put(expression.getName(), expression.getResultType().toString()); - this.nameToReturnTypeMap.put(expression.getName(), expression.getResultType().toString()); - this.expressionToReturnTypeMap.put(expression.getName(), expression.getResultType().toString()); - } + /** + * Collects the valueset - datatype map and code - datatype map. + * + *

It loos through each translator object from the parser, and then for each translator it + * loops through the retrieves. It then puts the valueset/code and it's corresponding data type + * into the correct map. + */ + private void collectValueSetCodeDataType( + Map>> valuesetMap, + Map>> codeMap) { + this.expressionNameToValuesetDataTypeMap = valuesetMap; + this.expressionNameToCodeDataTypeMap = codeMap; + this.valuesetDataTypeMap = flattenMap(valuesetMap); + this.codeDataTypeMap = flattenMap(codeMap); + } - if (parameters != null) { - for (ParameterDef parameter : parameters.getDef()) { - this.allNamesToReturnTypeMap.get(libraryName + "-" + libraryVersion).put(parameter.getName(), parameter.getResultType().toString()); - this.nameToReturnTypeMap.put(parameter.getName(), parameter.getResultType().toString()); - this.expressionToReturnTypeMap.put(parameter.getName(), parameter.getResultType().toString()); - } - } + /** + * The valueset/code - datatype map will come to us in a format of >. We want to also have a flattened map which will be in the format of + * + * + * @return a map in the above format + */ + private Map> flattenMap(Map>> mapToFlatten) { + Map> flattenedMap = new HashMap<>(); - if (null != this.library.getLibrary().getIncludes()) { - for (IncludeDef include : this.library.getLibrary().getIncludes().getDef()) { -// CompiledLibrary lib = this.CompiledLibraryMap.get(include.getPath() + "-" + include.getVersion()); - CompiledLibrary lib = this.CompiledLibraryMap.get(include.getPath()); - - Library.Statements statementsFromIncludedLibrary = lib.getLibrary().getStatements(); - Library.Parameters parametersFromIncludedLibrary = lib.getLibrary().getParameters(); - String includedLibraryName = lib.getIdentifier().getId(); - String includedLibraryVersion = lib.getIdentifier().getVersion(); - this.allNamesToReturnTypeMap.put(includedLibraryName + "-" + includedLibraryVersion, new HashMap<>()); - - for (ExpressionDef expression : statementsFromIncludedLibrary.getDef()) { - this.allNamesToReturnTypeMap.get(includedLibraryName + "-" + includedLibraryVersion).put(expression.getName(), expression.getResultType().toString()); - this.expressionToReturnTypeMap.put(include.getLocalIdentifier() + "." + expression.getName(), expression.getResultType().toString()); - } - - if (parametersFromIncludedLibrary != null) { - for (ParameterDef parameter : parametersFromIncludedLibrary.getDef()) { - this.allNamesToReturnTypeMap.get(includedLibraryName + "-" + includedLibraryVersion).put(parameter.getName(), parameter.getResultType().toString()); - this.expressionToReturnTypeMap.put(include.getLocalIdentifier() + "." + parameter.getName(), parameter.getResultType().toString()); - } - } - } - } - } + Set keys = mapToFlatten.keySet(); + for (String key : keys) { + Map> innerMap = mapToFlatten.get(key); - /** - * Collects the valueset - datatype map and code - datatype map. - *

- * It loos through each translator object from the parser, and then for each translator it loops through the retrieves. - * It then puts the valueset/code and it's corresponding data type into the correct map. - */ - private void collectValueSetCodeDataType(Map>> valuesetMap, - Map>> codeMap) { - this.expressionNameToValuesetDataTypeMap = valuesetMap; - this.expressionNameToCodeDataTypeMap = codeMap; - this.valuesetDataTypeMap = flattenMap(valuesetMap); - this.codeDataTypeMap = flattenMap(codeMap); + Set innerKeys = innerMap.keySet(); + for (String innerKey : innerKeys) { + flattenedMap.computeIfAbsent(innerKey, k -> new HashSet<>(innerMap.get(innerKey))); + } } - /** - * The valueset/code - datatype map will come to us in a format of >. - * We want to also have a flattened map which will be in the format of - * - * @return a map in the above format - */ - private Map> flattenMap(Map>> mapToFlatten) { - Map> flattenedMap = new HashMap<>(); - - Set keys = mapToFlatten.keySet(); - for (String key : keys) { - Map> innerMap = mapToFlatten.get(key); - - Set innerKeys = innerMap.keySet(); - for (String innerKey : innerKeys) { - flattenedMap.computeIfAbsent(innerKey, k -> new HashSet<>(innerMap.get(innerKey))); - } - } - - return flattenedMap; - } - - public Map> getValuesetDataTypeMap() { - Map> valuesetDataTypeMapWithList = new HashMap<>(); - - List keySet = new ArrayList<>(valuesetDataTypeMap.keySet()); - - for (String key : keySet) { - List dataTypes = new ArrayList<>(valuesetDataTypeMap.get(key)); - valuesetDataTypeMapWithList.put(key, dataTypes); - } - - return valuesetDataTypeMapWithList; - } + return flattenedMap; + } - public Map> getCodeDataTypeMap() { - Map> codeDataTypeMapWithList = new HashMap<>(); + public Map> getValuesetDataTypeMap() { + Map> valuesetDataTypeMapWithList = new HashMap<>(); + + List keySet = new ArrayList<>(valuesetDataTypeMap.keySet()); + + for (String key : keySet) { + List dataTypes = new ArrayList<>(valuesetDataTypeMap.get(key)); + valuesetDataTypeMapWithList.put(key, dataTypes); + } + + return valuesetDataTypeMapWithList; + } + + public Map> getCodeDataTypeMap() { + Map> codeDataTypeMapWithList = new HashMap<>(); + + List keySet = new ArrayList<>(codeDataTypeMap.keySet()); + + for (String key : keySet) { + List dataTypes = new ArrayList<>(codeDataTypeMap.get(key)); + codeDataTypeMapWithList.put(key, dataTypes); + } + + return codeDataTypeMapWithList; + } + + public Map getNameToReturnTypeMap() { + return nameToReturnTypeMap; + } + + public void setNameToReturnTypeMap(Map nameToReturnTypeMap) { + this.nameToReturnTypeMap = nameToReturnTypeMap; + } + + public List getUsedLibraries() { + return new ArrayList<>(usedLibraries); + } + + private List formatUsedLibraries() { + Set usedLibraryFormatted = new HashSet<>(); + for (String usedLibrary : usedLibraries) { + IncludeDef def = (IncludeDef) this.library.resolve(usedLibrary); + usedLibraryFormatted.add(def.getPath() + "-" + def.getVersion() + "|" + usedLibrary); + } + + return new ArrayList<>(usedLibraryFormatted); + } + + public List getUsedCodes() { + return new ArrayList<>(usedCodes); + } + + public List getUsedCodeSystems() { + return new ArrayList<>(usedCodeSystems); + } + + public List getUsedValuesets() { + return new ArrayList<>(usedValuesets); + } + + public List getUsedParameters() { + return new ArrayList<>(usedParameters); + } + + public List getUsedDefinitions() { + return new ArrayList<>(usedDefinitions); + } + + public List getUsedFunctions() { + return new ArrayList<>(usedFunctions); + } + + public Map>> getExpressionNameToValuesetDataTypeMap() { + return expressionNameToValuesetDataTypeMap; + } + + public Map>> getExpressionNameToCodeDataTypeMap() { + return expressionNameToCodeDataTypeMap; + } + + public DataCriteria getDataCriteria() { + return dataCriteria; + } - List keySet = new ArrayList<>(codeDataTypeMap.keySet()); + @Override + public String toString() { - for (String key : keySet) { - List dataTypes = new ArrayList<>(codeDataTypeMap.get(key)); - codeDataTypeMapWithList.put(key, dataTypes); - } - - return codeDataTypeMapWithList; - } - - public Map getNameToReturnTypeMap() { - return nameToReturnTypeMap; - } - - public void setNameToReturnTypeMap(Map nameToReturnTypeMap) { - this.nameToReturnTypeMap = nameToReturnTypeMap; - } - - public List getUsedLibraries() { - return new ArrayList<>(usedLibraries); - } - - private List formatUsedLibraries() { - Set usedLibraryFormatted = new HashSet<>(); - for (String usedLibrary : usedLibraries) { - IncludeDef def = (IncludeDef) this.library.resolve(usedLibrary); - usedLibraryFormatted.add(def.getPath() + "-" + def.getVersion() + "|" + usedLibrary); - } - - return new ArrayList<>(usedLibraryFormatted); - } - - public List getUsedCodes() { - return new ArrayList<>(usedCodes); - } - - public List getUsedCodeSystems() { - return new ArrayList<>(usedCodeSystems); - } - - public List getUsedValuesets() { - return new ArrayList<>(usedValuesets); - } - - public List getUsedParameters() { - return new ArrayList<>(usedParameters); - } - - public List getUsedDefinitions() { - return new ArrayList<>(usedDefinitions); - } - - public List getUsedFunctions() { - return new ArrayList<>(usedFunctions); - } - - public Map>> getExpressionNameToValuesetDataTypeMap() { - return expressionNameToValuesetDataTypeMap; - } - - public Map>> getExpressionNameToCodeDataTypeMap() { - return expressionNameToCodeDataTypeMap; - } - - public DataCriteria getDataCriteria() { - return dataCriteria; - } - - @Override - public String toString() { - - StringBuilder builder = new StringBuilder(); - - builder.append("RETURN TYPE MAP: " + this.getAllNamesToReturnTypeMap()); - builder.append("\n"); - builder.append("VALUSET-DATATYPE MAP: " + this.getValuesetDataTypeMap()); - builder.append("\n"); - builder.append("CODE-DATATYPE MAP: " + this.getCodeDataTypeMap()); - builder.append("\n"); - builder.append("EXPRESSION NAME - VALUSET-DATATYPE MAP: " + this.getExpressionNameToValuesetDataTypeMap()); - builder.append("\n"); - builder.append("EXPRESSION NAME - CODE-DATATYPE MAP: " + this.getExpressionNameToCodeDataTypeMap()); - builder.append("\n"); - builder.append("USED LIBRARIES: " + this.getUsedLibraries()); - builder.append("\n"); - builder.append("USED VALUESETS: " + this.getUsedValuesets()); - builder.append("\n"); - builder.append("USED CODESYSTEMS: " + this.getUsedCodeSystems()); - builder.append("\n"); - builder.append("USED CODES: " + this.getUsedCodes()); - builder.append("\n"); - builder.append("USED PARAMETERS: " + this.getUsedParameters()); - builder.append("\n"); - builder.append("USED DEFINITIONS: " + this.getUsedDefinitions()); - builder.append("\n"); - builder.append("USED FUNCTIONS " + this.getUsedFunctions()); - - return builder.toString(); - } - - public Map> getAllNamesToReturnTypeMap() { - return allNamesToReturnTypeMap; - } - - public Map getExpressionToReturnTypeMap() { - return expressionToReturnTypeMap; - } + StringBuilder builder = new StringBuilder(); + builder.append("RETURN TYPE MAP: " + this.getAllNamesToReturnTypeMap()); + builder.append("\n"); + builder.append("VALUSET-DATATYPE MAP: " + this.getValuesetDataTypeMap()); + builder.append("\n"); + builder.append("CODE-DATATYPE MAP: " + this.getCodeDataTypeMap()); + builder.append("\n"); + builder.append( + "EXPRESSION NAME - VALUSET-DATATYPE MAP: " + this.getExpressionNameToValuesetDataTypeMap()); + builder.append("\n"); + builder.append( + "EXPRESSION NAME - CODE-DATATYPE MAP: " + this.getExpressionNameToCodeDataTypeMap()); + builder.append("\n"); + builder.append("USED LIBRARIES: " + this.getUsedLibraries()); + builder.append("\n"); + builder.append("USED VALUESETS: " + this.getUsedValuesets()); + builder.append("\n"); + builder.append("USED CODESYSTEMS: " + this.getUsedCodeSystems()); + builder.append("\n"); + builder.append("USED CODES: " + this.getUsedCodes()); + builder.append("\n"); + builder.append("USED PARAMETERS: " + this.getUsedParameters()); + builder.append("\n"); + builder.append("USED DEFINITIONS: " + this.getUsedDefinitions()); + builder.append("\n"); + builder.append("USED FUNCTIONS " + this.getUsedFunctions()); + + return builder.toString(); + } + + public Map> getAllNamesToReturnTypeMap() { + return allNamesToReturnTypeMap; + } + + public Map getExpressionToReturnTypeMap() { + return expressionToReturnTypeMap; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLUtilityClass.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLUtilityClass.java index b3eba14f..86c939b2 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLUtilityClass.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/CQLUtilityClass.java @@ -3,586 +3,621 @@ import java.util.Scanner; public final class CQLUtilityClass { - private static final String PATIENT = "Patient"; + private static final String PATIENT = "Patient"; - private static final String POPULATION = "Population"; + private static final String POPULATION = "Population"; - public static final String VERSION = " version "; + public static final String VERSION = " version "; - private CQLUtilityClass() { - throw new IllegalStateException("CQL Utility class"); - } - - public static String replaceFirstWhitespaceInLineForExpression(String expression) { - Scanner scanner = new Scanner(expression); - StringBuilder builder = new StringBuilder(); + private CQLUtilityClass() { + throw new IllegalStateException("CQL Utility class"); + } - // go through and rebuild the the format - // this will remove the first whitespace in a line so - // it properly displays in the ace editor. - // without doing this, the the ace editor display - // would be indented one too many - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); + public static String replaceFirstWhitespaceInLineForExpression(String expression) { + Scanner scanner = new Scanner(expression); + StringBuilder builder = new StringBuilder(); - if (!line.isEmpty()) { - if (line.startsWith(CQLUtilityClass.getWhiteSpaceString(true, 2))) { - line = line.replaceFirst(CQLUtilityClass.getWhiteSpaceString(true, 2), ""); - } - } + // go through and rebuild the the format + // this will remove the first whitespace in a line so + // it properly displays in the ace editor. + // without doing this, the the ace editor display + // would be indented one too many + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); - builder.append(line).append("\n"); + if (!line.isEmpty()) { + if (line.startsWith(CQLUtilityClass.getWhiteSpaceString(true, 2))) { + line = line.replaceFirst(CQLUtilityClass.getWhiteSpaceString(true, 2), ""); } + } - scanner.close(); - return builder.toString(); + builder.append(line).append("\n"); } - public static String getWhiteSpaceString(boolean isSpaces, int indentSize) { - StringBuilder whiteSpaceString = new StringBuilder(); - for (int i = 0; i < indentSize; i++) { - if (isSpaces) { - whiteSpaceString.append(" "); - } else { - whiteSpaceString.append("\t"); - } - } + scanner.close(); + return builder.toString(); + } - return whiteSpaceString.toString(); + public static String getWhiteSpaceString(boolean isSpaces, int indentSize) { + StringBuilder whiteSpaceString = new StringBuilder(); + for (int i = 0; i < indentSize; i++) { + if (isSpaces) { + whiteSpaceString.append(" "); + } else { + whiteSpaceString.append("\t"); + } } -// public static Pair getCqlString(CQLModel cqlModel, String toBeInserted) { -// return getCqlString(cqlModel, toBeInserted, true, 2); -// } -// -// public static Pair getCqlString(CQLModel cqlModel, String toBeInserted, boolean isSpaces, int indentSize) { -// AtomicInteger size = new AtomicInteger(0); -// StringBuilder cqlStr = new StringBuilder(); -// // library Name and Using -// cqlStr.append(CQLUtilityClass.createLibraryNameSection(cqlModel)); -// -// //includes -// cqlStr.append(CQLUtilityClass.createIncludesSection(cqlModel.getCqlIncludeLibrarys())); -// -// //CodeSystems -// // Not very clean but they use the code list instead of the code system section for codes. -// // This adds all kinds of complexity but is needed for backwards compatibility. -// cqlStr.append(CQLUtilityClass.createCodeSystemsSection(cqlModel.getCodeList())); -// -// //Valuesets -// cqlStr.append(CQLUtilityClass.createValueSetsSection(cqlModel.getValueSetList(), cqlModel.isFhir())); -// -// //Codes -// cqlStr.append(CQLUtilityClass.createCodesSection(cqlModel.getCodeList())); -// -// // parameters -// CQLUtilityClass.createParameterSection(cqlModel.getCqlParameters(), cqlStr, toBeInserted, size); -// -// // Definitions and Functions by Context -// if (!cqlModel.getDefinitionList().isEmpty() || !cqlModel.getCqlFunctions().isEmpty()) { -// getDefineAndFunctionsByContext(cqlModel.getDefinitionList(), -// cqlModel.getCqlFunctions(), -// cqlStr, -// toBeInserted, -// isSpaces, -// indentSize, -// size, -// cqlModel.isFhir()); -// } else { -// cqlStr.append("context").append(" " + PATIENT).append("\n\n"); -// } -// return Pair.of(cqlStr.toString(), size.get()); -// } -// -// private static String createLibraryNameSection(CQLModel cqlModel) { -// StringBuilder sb = new StringBuilder(); -// -// if (StringUtils.isNotBlank(cqlModel.getLibraryName())) { -// -// sb.append("library ").append(cqlModel.getLibraryName()); -// sb.append(VERSION).append("'" + cqlModel.getVersionUsed()).append("'"); -// sb.append(System.lineSeparator()).append(System.lineSeparator()); -// -// if (StringUtils.isNotBlank(cqlModel.getLibraryComment())) { -// sb.append(createCommentString(cqlModel.getLibraryComment())); -// sb.append(System.lineSeparator()).append(System.lineSeparator()); -// } -// -// sb.append("using ").append(cqlModel.getUsingModel()); -// sb.append(VERSION); -// sb.append("'").append(cqlModel.getUsingModelVersion()).append("'"); -// sb.append("\n\n"); -// } -// -// return sb.toString(); -// } -// -// /** -// * Gets the define and funcs by context. -// * -// * @param defineList the define list -// * @param functionsList the functions list -// * @param cqlStr the cql str -// * @param indentSize -// * @param isSpaces -// * @return the define and funcs by context -// */ -// private static StringBuilder getDefineAndFunctionsByContext( -// List defineList, -// List functionsList, -// StringBuilder cqlStr, -// String toBeInserted, -// boolean isSpaces, -// int indentSize, -// AtomicInteger size, -// boolean isFhir) { -// Map> contextToDefMap = new HashMap<>(); -// Map> funcToContextMap = new HashMap<>(); -// -// if (!CollectionUtils.isEmpty(defineList)) { -// defineList.forEach(d -> { -// if (isFhir) { -// addToListMap(contextToDefMap, StringUtils.defaultString(d.getContext()), d); -// } else { -// //For some reason in QDM it defaults to population. -// if (StringUtils.equalsIgnoreCase(d.getContext(), PATIENT)) { -// addToListMap(contextToDefMap, PATIENT, d); -// } else { -// addToListMap(contextToDefMap, POPULATION, d); -// } -// } -// }); -// } -// if (!CollectionUtils.isEmpty(functionsList)) { -// functionsList.forEach(f -> { -// if (isFhir) { -// addToListMap(funcToContextMap, StringUtils.defaultString(f.getContext()), f); -// } else { -// //For some reason in QDM it defaults to population. -// if (StringUtils.equalsIgnoreCase(f.getContext(), PATIENT)) { -// addToListMap(funcToContextMap, PATIENT, f); -// } else { -// addToListMap(funcToContextMap, POPULATION, f); -// -// } -// } -// }); -// } -// -// Set keys = new HashSet<>(); -// keys.addAll(contextToDefMap.keySet()); -// keys.addAll(funcToContextMap.keySet()); -// -// keys.forEach(k -> { -// getDefineAndFunctionsByContext(contextToDefMap.get(k), funcToContextMap.get(k), k, cqlStr, toBeInserted, isSpaces, indentSize, size); -// }); -// -// return cqlStr; -// } -// -// /** -// * Gets the define and functions by context. -// * -// * @param definitionList the definition list -// * @param functionsList the functions list -// * @param context the context -// * @param cqlStr the cql str -// * @param indentSize -// * @param isSpaces -// * @return the define and functions by context -// */ -// private static StringBuilder getDefineAndFunctionsByContext( -// List definitionList, -// List functionsList, String context, -// final StringBuilder cqlStr, String toBeInserted, boolean isSpaces, int indentSize, AtomicInteger size) { -// -// if (StringUtils.isNotBlank(context)) { -// cqlStr.append("context").append(" " + context).append("\n\n"); -// } -// -// if (!CollectionUtils.isEmpty(definitionList)) { -// definitionList.forEach(definition -> { -// if (StringUtils.isNotBlank(definition.getCommentString())) { -// cqlStr.append(createCommentString(definition.getCommentString())); -// cqlStr.append(System.lineSeparator()); -// } -// -// String def = "define " + "\"" + definition.getName() + "\""; -// -// cqlStr.append(def + ":\n"); -// cqlStr.append(getWhiteSpaceString(isSpaces, indentSize) + definition.getLogic().replaceAll("\\n", "\n" + getWhiteSpaceString(isSpaces, indentSize))); -// cqlStr.append("\n\n"); -// -// // if the the def we just appended is the current one, then -// // find the size of the file at that time. ;- -// // This will give us the end line of the definition we are trying to insert. -// if (def.equalsIgnoreCase(toBeInserted)) { -// size.set(getEndLine(cqlStr.toString())); -// } -// }); -// } -// if (!CollectionUtils.isEmpty(functionsList)) { -// functionsList.forEach(function -> { -// if (StringUtils.isNotBlank(function.getCommentString())) { -// cqlStr.append(createCommentString(function.getCommentString())); -// cqlStr.append(System.lineSeparator()); -// } -// -// String func = "define function " + "\"" + function.getName() + "\""; -// -// cqlStr.append(func + "("); -// if (function.getArgumentList() != null && !function.getArgumentList().isEmpty()) { -// for (CQLFunctionArgument argument : function.getArgumentList()) { -// StringBuilder argumentType = new StringBuilder(); -// if (argument.getArgumentType().equalsIgnoreCase("QDM Datatype")) { -// argumentType = argumentType.append("\"").append(argument.getQdmDataType()); -// if (argument.getAttributeName() != null) { -// argumentType = argumentType.append(".").append(argument.getAttributeName()); -// } -// argumentType = argumentType.append("\""); -// } else if (argument.getArgumentType().equalsIgnoreCase("FHIR Datatype")) { -// argumentType = argumentType.append(argument.getQdmDataType()); -// } else if (argument.getArgumentType().equalsIgnoreCase( -// CQLWorkSpaceConstants.CQL_OTHER_DATA_TYPE)) { -// argumentType = argumentType.append(argument.getOtherType()); -// } else { -// argumentType = argumentType.append(argument.getArgumentType()); -// } -// cqlStr.append(argument.getArgumentName() + " " + argumentType + ", "); -// } -// cqlStr.deleteCharAt(cqlStr.length() - 2); -// } -// -// cqlStr.append("):\n" + getWhiteSpaceString(isSpaces, indentSize) + function.getLogic().replaceAll("\\n", "\n" + getWhiteSpaceString(isSpaces, indentSize))); -// cqlStr.append("\n\n"); -// -// // if the the func we just appended is the current one, then -// // find the size of the file at that time. -// // This will give us the end line of the function we are trying to insert. -// if (func.equalsIgnoreCase(toBeInserted)) { -// size.set(getEndLine(cqlStr.toString())); -// } -// }); -// } -// return cqlStr; -// } -// -// -// public static CQLModel getCQLModelFromXML(String xmlString) { -// CQLModel cqlModel = new CQLModel(); -// XmlProcessor measureXMLProcessor = new XmlProcessor(xmlString); -// String cqlLookUpXMLString = measureXMLProcessor.getXmlByTagName("cqlLookUp"); -// -// if (StringUtils.isNotBlank(cqlLookUpXMLString)) { -// try { -// XMLMarshalUtil xmlMarshalUtil = new XMLMarshalUtil(); -// cqlModel = (CQLModel) xmlMarshalUtil.convertXMLToObject("CQLModelMapping.xml", cqlLookUpXMLString, CQLModel.class); -// } catch (Exception e) { -// logger.error("Error parsing CQL model from XML: " + e.getMessage(), e); -// } -// } -// -// if (!cqlModel.getValueSetList().isEmpty()) { -// cqlModel.setValueSetList(filterValuesets(cqlModel.getValueSetList())); -// ArrayList valueSetsList = new ArrayList<>(); -// valueSetsList.addAll(cqlModel.getValueSetList()); -// cqlModel.setAllValueSetAndCodeList(valueSetsList); -// } -// -// if (!cqlModel.getCodeList().isEmpty()) { -// sortCQLCodeDTO(cqlModel.getCodeList()); -// //Combine Codes and Value sets in allValueSetList for UI -// List dtoList = convertCodesToQualityDataSetDTO(cqlModel.getCodeList()); -// if (!dtoList.isEmpty()) { -// cqlModel.getAllValueSetAndCodeList().addAll(dtoList); -// } -// } -// return cqlModel; -// } -// -// public static String getXMLFromCQLModel(CQLModel cqlModel) { -// String xml = ""; -// -// try (ByteArrayOutputStream stream = new ByteArrayOutputStream();) { -// Mapping mapping = new Mapping(); -// mapping.loadMapping(new ResourceLoader().getResourceAsURL("CQLModelMapping.xml")); -// Marshaller marshaller = new Marshaller(new OutputStreamWriter(stream)); -// marshaller.setMapping(mapping); -// marshaller.marshal(cqlModel); -// xml = stream.toString(); -// } catch (MarshalException | ValidationException | IOException | MappingException e) { -// logger.error("Error in getXMLFromCQLModel: " + e.getMessage(), e); -// } -// -// -// return xml; -// } -// -// public static void getValueSet(CQLModel cqlModel, String cqlLookUpXMLString) { -// CQLQualityDataModelWrapper valuesetWrapper; -// try { -// XMLMarshalUtil xmlMarshalUtil = new XMLMarshalUtil(); -// valuesetWrapper = (CQLQualityDataModelWrapper) xmlMarshalUtil.convertXMLToObject("ValueSetsMapping.xml", cqlLookUpXMLString, CQLQualityDataModelWrapper.class); -// if (!valuesetWrapper.getQualityDataDTO().isEmpty()) { -// cqlModel.setValueSetList(filterValuesets(valuesetWrapper.getQualityDataDTO())); -// } -// } catch (Exception e) { -// logger.error("Error while getting valueset :" + e.getMessage(), e); -// } -// -// } -// -// -// private static List convertCodesToQualityDataSetDTO(List codeList) { -// List convertedCQLDataSetList = new ArrayList(); -// for (CQLCode tempDataSet : codeList) { -// CQLQualityDataSetDTO convertedCQLDataSet = new CQLQualityDataSetDTO(); -// convertedCQLDataSet.setName(tempDataSet.getName()); -// convertedCQLDataSet.setCodeSystemName(tempDataSet.getCodeSystemName()); -// convertedCQLDataSet.setCodeSystemOID(tempDataSet.getCodeSystemOID()); -// -// convertedCQLDataSet.setCodeIdentifier(tempDataSet.getCodeIdentifier()); -// convertedCQLDataSet.setId(tempDataSet.getId()); -// convertedCQLDataSet.setOid(tempDataSet.getCodeOID()); -// convertedCQLDataSet.setVersion(tempDataSet.getCodeSystemVersion()); -// convertedCQLDataSet.setDisplayName(tempDataSet.getDisplayName()); -// convertedCQLDataSet.setSuffix(tempDataSet.getSuffix()); -// -// convertedCQLDataSet.setReadOnly(tempDataSet.isReadOnly()); -// -// convertedCQLDataSet.setType("code"); -// convertedCQLDataSetList.add(convertedCQLDataSet); -// -// -// } -// return convertedCQLDataSetList; -// -// } -// -// private static int getEndLine(String cqlString) { -// -// Scanner scanner = new Scanner(cqlString); -// -// int endLine = -1; -// while (scanner.hasNextLine()) { -// endLine++; -// scanner.nextLine(); -// } -// -// scanner.close(); -// return endLine; -// } -// -// public static List sortCQLQualityDataSetDto(List cqlQualityDataSetDTOs) { -// -// cqlQualityDataSetDTOs.sort((c1, c2) -> c1.getName().compareToIgnoreCase(c2.getName())); -// return cqlQualityDataSetDTOs; -// } -// -// public static List sortCQLCodeDTO(List cqlCodes) { -// -// cqlCodes.sort((c1, c2) -> c1.getName().compareToIgnoreCase(c2.getName())); -// return cqlCodes; -// } -// -// private static List filterValuesets(List cqlValuesets) { -// -// cqlValuesets.removeIf(c -> c.getDataType() != null && -// (c.getDataType().equalsIgnoreCase("Patient characteristic Birthdate") -// || c.getDataType().equalsIgnoreCase("Patient characteristic Expired"))); -// -// sortCQLQualityDataSetDto(cqlValuesets); -// -// return cqlValuesets; -// } -// -// private static String createIncludesSection(List includeLibList) { -// StringBuilder sb = new StringBuilder(); -// if (!CollectionUtils.isEmpty(includeLibList)) { -// for (CQLIncludeLibrary includeLib : includeLibList) { -// sb.append("include ").append(includeLib.getCqlLibraryName()); -// sb.append(VERSION).append("'").append(MeasureUtility.formatVersionText(includeLib.getVersion())).append("' "); -// sb.append("called ").append(includeLib.getAliasName()); -// sb.append("\n"); -// } -// sb.append("\n"); -// } -// return sb.toString(); -// } -// -// private static String createCodeSystemsSection(List codeSystemList) { -// StringBuilder sb = new StringBuilder(); -// -// //Use a set to prevent duplicate entries automatically. -// Set codeSystemAlreadyUsed = new HashSet<>(); -// -// if (!CollectionUtils.isEmpty(codeSystemList)) { -// for (CQLCode code : codeSystemList) { -// if (code.getCodeSystemOID() != null && !code.getCodeSystemOID().isEmpty() && !"null".equals(code.getCodeSystemOID())) { -// boolean isUrlCodeSystem = StringUtils.startsWith(code.getCodeSystemOID(), "http"); -// if (isUrlCodeSystem) { -// String csName = code.getCodeSystemName(); -// String csVersionUri = code.getCodeSystemVersionUri(); -// if (code.isIsCodeSystemVersionIncluded()) { -// csName = csName + ":" + code.getCodeSystemVersion(); -// } -// if (!codeSystemAlreadyUsed.contains(csName)) { -// // Fhir4 code system -// // codesystem "SNOMEDCT:2017-09": 'http://snomed.info/sct/731000124108' version 'http://snomed.info/sct/731000124108/version/201709' -// // or -// // codesystem "SNOMEDCT:2017-09": 'http://snomed.info/sct/731000124108' -// String csUri = code.getCodeSystemOID(); -// sb.append("codesystem \"").append(csName).append('"').append(": "). -// append("'").append(csUri).append("' "); -// if (StringUtils.isNotBlank(csVersionUri)) { -// sb.append("version '" + csVersionUri + "'"); -// } -// sb.append("\n"); -// codeSystemAlreadyUsed.add(csName); -// } -// } else { -// // Legacy OID system. -// String codeSysStr = code.getCodeSystemName(); -// String codeSysVersion = ""; -// -// if (code.isIsCodeSystemVersionIncluded()) { -// codeSysStr = codeSysStr + ":" + code.getCodeSystemVersion().replaceAll(" ", "%20"); -// codeSysVersion = "version 'urn:hl7:version:" + code.getCodeSystemVersion() + "'"; -// } -// -// if (!codeSystemAlreadyUsed.contains(codeSysStr)) { -// sb.append("codesystem \"").append(codeSysStr).append('"').append(": "); -// if(code.getCodeSystemOID().startsWith("urn:oid:")) { -// sb.append('\''); -// } else { -// sb.append("'urn:oid:"); -// } -// sb.append(code.getCodeSystemOID()).append("' "); -// sb.append(codeSysVersion); -// sb.append("\n"); -// -// codeSystemAlreadyUsed.add(codeSysStr); -// } -// } -// } -// } -// -// sb.append("\n"); -// } -// -// return sb.toString(); -// } -// -// private static String createValueSetsSection(List valueSetList, boolean isFhir) { -// StringBuilder sb = new StringBuilder(); -// -// List valueSetAlreadyUsed = new ArrayList<>(); -// -// if (!CollectionUtils.isEmpty(valueSetList)) { -// -// for (CQLQualityDataSetDTO valueset : valueSetList) { -// -// if (!valueSetAlreadyUsed.contains(valueset.getName())) { -// if (isFhir) { -// sb.append("valueset ").append('"').append(valueset.getName()).append('"'); -// sb.append(": '").append(valueset.getOid()).append("' "); -// } else { -// String version = valueset.getVersion().replaceAll(" ", "%20"); -// sb.append("valueset ").append('"').append(valueset.getName()).append('"'); -// sb.append(": 'urn:oid:").append(valueset.getOid()).append("' "); -// //Check if QDM has expansion identifier or not. -// if (StringUtils.isNotBlank(version) && !version.equals("1.0")) { -// sb.append("version 'urn:hl7:version:").append(version).append("' "); -// } -// } -// sb.append("\n"); -// valueSetAlreadyUsed.add(valueset.getName()); -// } -// } -// sb.append("\n"); -// } -// return sb.toString(); -// } -// -// private static String createCodesSection(List codeList) { -// -// StringBuilder sb = new StringBuilder(); -// -// List codeAlreadyUsed = new ArrayList<>(); -// -// if (!CollectionUtils.isEmpty(codeList)) { -// -// for (CQLCode code : codeList) { -// String codeStr = '"' + code.getCodeName() + '"' + ": " + "'" + code.getCodeOID() + "'"; -// String codeSysStr = code.getCodeSystemName(); -// if (code.isIsCodeSystemVersionIncluded()) { -// codeSysStr = codeSysStr + ":" + code.getCodeSystemVersion().replaceAll(" ", "%20"); -// } -// -// if (!codeAlreadyUsed.contains(codeStr)) { -// sb.append("code ").append(codeStr).append(" ").append("from "); -// sb.append('"').append(codeSysStr).append('"').append(" "); -// if (StringUtils.isNotEmpty(code.getDisplayName())) { -// sb.append("display " + "'" + code.getDisplayName() + "'"); -// } -// sb.append("\n"); -// codeAlreadyUsed.add(codeStr); -// } -// } -// -// sb.append("\n"); -// } -// -// return sb.toString(); -// } -// -// private static StringBuilder createParameterSection(List paramList, -// StringBuilder cqlStr, -// String toBeInserted, -// AtomicInteger size) { -// if (!CollectionUtils.isEmpty(paramList)) { -// -// for (CQLParameter parameter : paramList) { -// -// String param = "parameter " + "\"" + parameter.getName() + "\""; -// -// if (StringUtils.isNotBlank(parameter.getCommentString())) { -// cqlStr.append(createCommentString(parameter.getCommentString())); -// cqlStr.append(System.lineSeparator()); -// } -// -// cqlStr.append(param + " " + parameter.getLogic()); -// cqlStr.append("\n"); -// -// // if the the param we just appended is the current one, then -// // find the size of the file at that time. -// // This will give us the end line of the parameter we are trying to insert. -// if (param.equalsIgnoreCase(toBeInserted)) { -// size.set(getEndLine(cqlStr.toString())); -// } -// -// } -// -// cqlStr.append("\n"); -// } -// -// return cqlStr; -// } -// -// public static String createCommentString(String comment) { -// StringBuilder sb = new StringBuilder(); -// sb.append("/*").append(comment).append("*/"); -// return sb.toString(); -// } -// -// private static void addToListMap(Map> map, O key, T newElem) { -// if (map != null) { -// List l = map.get(key); -// if (CollectionUtils.isEmpty(l)) { -// l = new ArrayList(); -// map.put(key, l); -// } -// l.add(newElem); -// } -// } + return whiteSpaceString.toString(); + } + + // public static Pair getCqlString(CQLModel cqlModel, String toBeInserted) { + // return getCqlString(cqlModel, toBeInserted, true, 2); + // } + // + // public static Pair getCqlString(CQLModel cqlModel, String toBeInserted, + // boolean isSpaces, int indentSize) { + // AtomicInteger size = new AtomicInteger(0); + // StringBuilder cqlStr = new StringBuilder(); + // // library Name and Using + // cqlStr.append(CQLUtilityClass.createLibraryNameSection(cqlModel)); + // + // //includes + // cqlStr.append(CQLUtilityClass.createIncludesSection(cqlModel.getCqlIncludeLibrarys())); + // + // //CodeSystems + // // Not very clean but they use the code list instead of the code system section for + // codes. + // // This adds all kinds of complexity but is needed for backwards compatibility. + // cqlStr.append(CQLUtilityClass.createCodeSystemsSection(cqlModel.getCodeList())); + // + // //Valuesets + // cqlStr.append(CQLUtilityClass.createValueSetsSection(cqlModel.getValueSetList(), + // cqlModel.isFhir())); + // + // //Codes + // cqlStr.append(CQLUtilityClass.createCodesSection(cqlModel.getCodeList())); + // + // // parameters + // CQLUtilityClass.createParameterSection(cqlModel.getCqlParameters(), cqlStr, + // toBeInserted, size); + // + // // Definitions and Functions by Context + // if (!cqlModel.getDefinitionList().isEmpty() || !cqlModel.getCqlFunctions().isEmpty()) { + // getDefineAndFunctionsByContext(cqlModel.getDefinitionList(), + // cqlModel.getCqlFunctions(), + // cqlStr, + // toBeInserted, + // isSpaces, + // indentSize, + // size, + // cqlModel.isFhir()); + // } else { + // cqlStr.append("context").append(" " + PATIENT).append("\n\n"); + // } + // return Pair.of(cqlStr.toString(), size.get()); + // } + // + // private static String createLibraryNameSection(CQLModel cqlModel) { + // StringBuilder sb = new StringBuilder(); + // + // if (StringUtils.isNotBlank(cqlModel.getLibraryName())) { + // + // sb.append("library ").append(cqlModel.getLibraryName()); + // sb.append(VERSION).append("'" + cqlModel.getVersionUsed()).append("'"); + // sb.append(System.lineSeparator()).append(System.lineSeparator()); + // + // if (StringUtils.isNotBlank(cqlModel.getLibraryComment())) { + // sb.append(createCommentString(cqlModel.getLibraryComment())); + // sb.append(System.lineSeparator()).append(System.lineSeparator()); + // } + // + // sb.append("using ").append(cqlModel.getUsingModel()); + // sb.append(VERSION); + // sb.append("'").append(cqlModel.getUsingModelVersion()).append("'"); + // sb.append("\n\n"); + // } + // + // return sb.toString(); + // } + // + // /** + // * Gets the define and funcs by context. + // * + // * @param defineList the define list + // * @param functionsList the functions list + // * @param cqlStr the cql str + // * @param indentSize + // * @param isSpaces + // * @return the define and funcs by context + // */ + // private static StringBuilder getDefineAndFunctionsByContext( + // List defineList, + // List functionsList, + // StringBuilder cqlStr, + // String toBeInserted, + // boolean isSpaces, + // int indentSize, + // AtomicInteger size, + // boolean isFhir) { + // Map> contextToDefMap = new HashMap<>(); + // Map> funcToContextMap = new HashMap<>(); + // + // if (!CollectionUtils.isEmpty(defineList)) { + // defineList.forEach(d -> { + // if (isFhir) { + // addToListMap(contextToDefMap, StringUtils.defaultString(d.getContext()), d); + // } else { + // //For some reason in QDM it defaults to population. + // if (StringUtils.equalsIgnoreCase(d.getContext(), PATIENT)) { + // addToListMap(contextToDefMap, PATIENT, d); + // } else { + // addToListMap(contextToDefMap, POPULATION, d); + // } + // } + // }); + // } + // if (!CollectionUtils.isEmpty(functionsList)) { + // functionsList.forEach(f -> { + // if (isFhir) { + // addToListMap(funcToContextMap, StringUtils.defaultString(f.getContext()), + // f); + // } else { + // //For some reason in QDM it defaults to population. + // if (StringUtils.equalsIgnoreCase(f.getContext(), PATIENT)) { + // addToListMap(funcToContextMap, PATIENT, f); + // } else { + // addToListMap(funcToContextMap, POPULATION, f); + // + // } + // } + // }); + // } + // + // Set keys = new HashSet<>(); + // keys.addAll(contextToDefMap.keySet()); + // keys.addAll(funcToContextMap.keySet()); + // + // keys.forEach(k -> { + // getDefineAndFunctionsByContext(contextToDefMap.get(k), funcToContextMap.get(k), k, + // cqlStr, toBeInserted, isSpaces, indentSize, size); + // }); + // + // return cqlStr; + // } + // + // /** + // * Gets the define and functions by context. + // * + // * @param definitionList the definition list + // * @param functionsList the functions list + // * @param context the context + // * @param cqlStr the cql str + // * @param indentSize + // * @param isSpaces + // * @return the define and functions by context + // */ + // private static StringBuilder getDefineAndFunctionsByContext( + // List definitionList, + // List functionsList, String context, + // final StringBuilder cqlStr, String toBeInserted, boolean isSpaces, int indentSize, + // AtomicInteger size) { + // + // if (StringUtils.isNotBlank(context)) { + // cqlStr.append("context").append(" " + context).append("\n\n"); + // } + // + // if (!CollectionUtils.isEmpty(definitionList)) { + // definitionList.forEach(definition -> { + // if (StringUtils.isNotBlank(definition.getCommentString())) { + // cqlStr.append(createCommentString(definition.getCommentString())); + // cqlStr.append(System.lineSeparator()); + // } + // + // String def = "define " + "\"" + definition.getName() + "\""; + // + // cqlStr.append(def + ":\n"); + // cqlStr.append(getWhiteSpaceString(isSpaces, indentSize) + + // definition.getLogic().replaceAll("\\n", "\n" + getWhiteSpaceString(isSpaces, indentSize))); + // cqlStr.append("\n\n"); + // + // // if the the def we just appended is the current one, then + // // find the size of the file at that time. ;- + // // This will give us the end line of the definition we are trying to insert. + // if (def.equalsIgnoreCase(toBeInserted)) { + // size.set(getEndLine(cqlStr.toString())); + // } + // }); + // } + // if (!CollectionUtils.isEmpty(functionsList)) { + // functionsList.forEach(function -> { + // if (StringUtils.isNotBlank(function.getCommentString())) { + // cqlStr.append(createCommentString(function.getCommentString())); + // cqlStr.append(System.lineSeparator()); + // } + // + // String func = "define function " + "\"" + function.getName() + "\""; + // + // cqlStr.append(func + "("); + // if (function.getArgumentList() != null && !function.getArgumentList().isEmpty()) + // { + // for (CQLFunctionArgument argument : function.getArgumentList()) { + // StringBuilder argumentType = new StringBuilder(); + // if (argument.getArgumentType().equalsIgnoreCase("QDM Datatype")) { + // argumentType = + // argumentType.append("\"").append(argument.getQdmDataType()); + // if (argument.getAttributeName() != null) { + // argumentType = + // argumentType.append(".").append(argument.getAttributeName()); + // } + // argumentType = argumentType.append("\""); + // } else if (argument.getArgumentType().equalsIgnoreCase("FHIR Datatype")) + // { + // argumentType = argumentType.append(argument.getQdmDataType()); + // } else if (argument.getArgumentType().equalsIgnoreCase( + // CQLWorkSpaceConstants.CQL_OTHER_DATA_TYPE)) { + // argumentType = argumentType.append(argument.getOtherType()); + // } else { + // argumentType = argumentType.append(argument.getArgumentType()); + // } + // cqlStr.append(argument.getArgumentName() + " " + argumentType + ", "); + // } + // cqlStr.deleteCharAt(cqlStr.length() - 2); + // } + // + // cqlStr.append("):\n" + getWhiteSpaceString(isSpaces, indentSize) + + // function.getLogic().replaceAll("\\n", "\n" + getWhiteSpaceString(isSpaces, indentSize))); + // cqlStr.append("\n\n"); + // + // // if the the func we just appended is the current one, then + // // find the size of the file at that time. + // // This will give us the end line of the function we are trying to insert. + // if (func.equalsIgnoreCase(toBeInserted)) { + // size.set(getEndLine(cqlStr.toString())); + // } + // }); + // } + // return cqlStr; + // } + // + // + // public static CQLModel getCQLModelFromXML(String xmlString) { + // CQLModel cqlModel = new CQLModel(); + // XmlProcessor measureXMLProcessor = new XmlProcessor(xmlString); + // String cqlLookUpXMLString = measureXMLProcessor.getXmlByTagName("cqlLookUp"); + // + // if (StringUtils.isNotBlank(cqlLookUpXMLString)) { + // try { + // XMLMarshalUtil xmlMarshalUtil = new XMLMarshalUtil(); + // cqlModel = (CQLModel) xmlMarshalUtil.convertXMLToObject("CQLModelMapping.xml", + // cqlLookUpXMLString, CQLModel.class); + // } catch (Exception e) { + // logger.error("Error parsing CQL model from XML: " + e.getMessage(), e); + // } + // } + // + // if (!cqlModel.getValueSetList().isEmpty()) { + // cqlModel.setValueSetList(filterValuesets(cqlModel.getValueSetList())); + // ArrayList valueSetsList = new ArrayList<>(); + // valueSetsList.addAll(cqlModel.getValueSetList()); + // cqlModel.setAllValueSetAndCodeList(valueSetsList); + // } + // + // if (!cqlModel.getCodeList().isEmpty()) { + // sortCQLCodeDTO(cqlModel.getCodeList()); + // //Combine Codes and Value sets in allValueSetList for UI + // List dtoList = + // convertCodesToQualityDataSetDTO(cqlModel.getCodeList()); + // if (!dtoList.isEmpty()) { + // cqlModel.getAllValueSetAndCodeList().addAll(dtoList); + // } + // } + // return cqlModel; + // } + // + // public static String getXMLFromCQLModel(CQLModel cqlModel) { + // String xml = ""; + // + // try (ByteArrayOutputStream stream = new ByteArrayOutputStream();) { + // Mapping mapping = new Mapping(); + // mapping.loadMapping(new ResourceLoader().getResourceAsURL("CQLModelMapping.xml")); + // Marshaller marshaller = new Marshaller(new OutputStreamWriter(stream)); + // marshaller.setMapping(mapping); + // marshaller.marshal(cqlModel); + // xml = stream.toString(); + // } catch (MarshalException | ValidationException | IOException | MappingException e) { + // logger.error("Error in getXMLFromCQLModel: " + e.getMessage(), e); + // } + // + // + // return xml; + // } + // + // public static void getValueSet(CQLModel cqlModel, String cqlLookUpXMLString) { + // CQLQualityDataModelWrapper valuesetWrapper; + // try { + // XMLMarshalUtil xmlMarshalUtil = new XMLMarshalUtil(); + // valuesetWrapper = (CQLQualityDataModelWrapper) + // xmlMarshalUtil.convertXMLToObject("ValueSetsMapping.xml", cqlLookUpXMLString, + // CQLQualityDataModelWrapper.class); + // if (!valuesetWrapper.getQualityDataDTO().isEmpty()) { + // cqlModel.setValueSetList(filterValuesets(valuesetWrapper.getQualityDataDTO())); + // } + // } catch (Exception e) { + // logger.error("Error while getting valueset :" + e.getMessage(), e); + // } + // + // } + // + // + // private static List convertCodesToQualityDataSetDTO(List + // codeList) { + // List convertedCQLDataSetList = new + // ArrayList(); + // for (CQLCode tempDataSet : codeList) { + // CQLQualityDataSetDTO convertedCQLDataSet = new CQLQualityDataSetDTO(); + // convertedCQLDataSet.setName(tempDataSet.getName()); + // convertedCQLDataSet.setCodeSystemName(tempDataSet.getCodeSystemName()); + // convertedCQLDataSet.setCodeSystemOID(tempDataSet.getCodeSystemOID()); + // + // convertedCQLDataSet.setCodeIdentifier(tempDataSet.getCodeIdentifier()); + // convertedCQLDataSet.setId(tempDataSet.getId()); + // convertedCQLDataSet.setOid(tempDataSet.getCodeOID()); + // convertedCQLDataSet.setVersion(tempDataSet.getCodeSystemVersion()); + // convertedCQLDataSet.setDisplayName(tempDataSet.getDisplayName()); + // convertedCQLDataSet.setSuffix(tempDataSet.getSuffix()); + // + // convertedCQLDataSet.setReadOnly(tempDataSet.isReadOnly()); + // + // convertedCQLDataSet.setType("code"); + // convertedCQLDataSetList.add(convertedCQLDataSet); + // + // + // } + // return convertedCQLDataSetList; + // + // } + // + // private static int getEndLine(String cqlString) { + // + // Scanner scanner = new Scanner(cqlString); + // + // int endLine = -1; + // while (scanner.hasNextLine()) { + // endLine++; + // scanner.nextLine(); + // } + // + // scanner.close(); + // return endLine; + // } + // + // public static List sortCQLQualityDataSetDto(List + // cqlQualityDataSetDTOs) { + // + // cqlQualityDataSetDTOs.sort((c1, c2) -> c1.getName().compareToIgnoreCase(c2.getName())); + // return cqlQualityDataSetDTOs; + // } + // + // public static List sortCQLCodeDTO(List cqlCodes) { + // + // cqlCodes.sort((c1, c2) -> c1.getName().compareToIgnoreCase(c2.getName())); + // return cqlCodes; + // } + // + // private static List filterValuesets(List + // cqlValuesets) { + // + // cqlValuesets.removeIf(c -> c.getDataType() != null && + // (c.getDataType().equalsIgnoreCase("Patient characteristic Birthdate") + // || c.getDataType().equalsIgnoreCase("Patient characteristic Expired"))); + // + // sortCQLQualityDataSetDto(cqlValuesets); + // + // return cqlValuesets; + // } + // + // private static String createIncludesSection(List includeLibList) { + // StringBuilder sb = new StringBuilder(); + // if (!CollectionUtils.isEmpty(includeLibList)) { + // for (CQLIncludeLibrary includeLib : includeLibList) { + // sb.append("include ").append(includeLib.getCqlLibraryName()); + // + // sb.append(VERSION).append("'").append(MeasureUtility.formatVersionText(includeLib.getVersion())).append("' "); + // sb.append("called ").append(includeLib.getAliasName()); + // sb.append("\n"); + // } + // sb.append("\n"); + // } + // return sb.toString(); + // } + // + // private static String createCodeSystemsSection(List codeSystemList) { + // StringBuilder sb = new StringBuilder(); + // + // //Use a set to prevent duplicate entries automatically. + // Set codeSystemAlreadyUsed = new HashSet<>(); + // + // if (!CollectionUtils.isEmpty(codeSystemList)) { + // for (CQLCode code : codeSystemList) { + // if (code.getCodeSystemOID() != null && !code.getCodeSystemOID().isEmpty() && + // !"null".equals(code.getCodeSystemOID())) { + // boolean isUrlCodeSystem = StringUtils.startsWith(code.getCodeSystemOID(), + // "http"); + // if (isUrlCodeSystem) { + // String csName = code.getCodeSystemName(); + // String csVersionUri = code.getCodeSystemVersionUri(); + // if (code.isIsCodeSystemVersionIncluded()) { + // csName = csName + ":" + code.getCodeSystemVersion(); + // } + // if (!codeSystemAlreadyUsed.contains(csName)) { + // // Fhir4 code system + // // codesystem "SNOMEDCT:2017-09": + // 'http://snomed.info/sct/731000124108' version + // 'http://snomed.info/sct/731000124108/version/201709' + // // or + // // codesystem "SNOMEDCT:2017-09": + // 'http://snomed.info/sct/731000124108' + // String csUri = code.getCodeSystemOID(); + // sb.append("codesystem \"").append(csName).append('"').append(": "). + // append("'").append(csUri).append("' "); + // if (StringUtils.isNotBlank(csVersionUri)) { + // sb.append("version '" + csVersionUri + "'"); + // } + // sb.append("\n"); + // codeSystemAlreadyUsed.add(csName); + // } + // } else { + // // Legacy OID system. + // String codeSysStr = code.getCodeSystemName(); + // String codeSysVersion = ""; + // + // if (code.isIsCodeSystemVersionIncluded()) { + // codeSysStr = codeSysStr + ":" + + // code.getCodeSystemVersion().replaceAll(" ", "%20"); + // codeSysVersion = "version 'urn:hl7:version:" + + // code.getCodeSystemVersion() + "'"; + // } + // + // if (!codeSystemAlreadyUsed.contains(codeSysStr)) { + // sb.append("codesystem \"").append(codeSysStr).append('"').append(": + // "); + // if(code.getCodeSystemOID().startsWith("urn:oid:")) { + // sb.append('\''); + // } else { + // sb.append("'urn:oid:"); + // } + // sb.append(code.getCodeSystemOID()).append("' "); + // sb.append(codeSysVersion); + // sb.append("\n"); + // + // codeSystemAlreadyUsed.add(codeSysStr); + // } + // } + // } + // } + // + // sb.append("\n"); + // } + // + // return sb.toString(); + // } + // + // private static String createValueSetsSection(List valueSetList, + // boolean isFhir) { + // StringBuilder sb = new StringBuilder(); + // + // List valueSetAlreadyUsed = new ArrayList<>(); + // + // if (!CollectionUtils.isEmpty(valueSetList)) { + // + // for (CQLQualityDataSetDTO valueset : valueSetList) { + // + // if (!valueSetAlreadyUsed.contains(valueset.getName())) { + // if (isFhir) { + // sb.append("valueset + // ").append('"').append(valueset.getName()).append('"'); + // sb.append(": '").append(valueset.getOid()).append("' "); + // } else { + // String version = valueset.getVersion().replaceAll(" ", "%20"); + // sb.append("valueset + // ").append('"').append(valueset.getName()).append('"'); + // sb.append(": 'urn:oid:").append(valueset.getOid()).append("' "); + // //Check if QDM has expansion identifier or not. + // if (StringUtils.isNotBlank(version) && !version.equals("1.0")) { + // sb.append("version 'urn:hl7:version:").append(version).append("' "); + // } + // } + // sb.append("\n"); + // valueSetAlreadyUsed.add(valueset.getName()); + // } + // } + // sb.append("\n"); + // } + // return sb.toString(); + // } + // + // private static String createCodesSection(List codeList) { + // + // StringBuilder sb = new StringBuilder(); + // + // List codeAlreadyUsed = new ArrayList<>(); + // + // if (!CollectionUtils.isEmpty(codeList)) { + // + // for (CQLCode code : codeList) { + // String codeStr = '"' + code.getCodeName() + '"' + ": " + "'" + code.getCodeOID() + // + "'"; + // String codeSysStr = code.getCodeSystemName(); + // if (code.isIsCodeSystemVersionIncluded()) { + // codeSysStr = codeSysStr + ":" + code.getCodeSystemVersion().replaceAll(" ", + // "%20"); + // } + // + // if (!codeAlreadyUsed.contains(codeStr)) { + // sb.append("code ").append(codeStr).append(" ").append("from "); + // sb.append('"').append(codeSysStr).append('"').append(" "); + // if (StringUtils.isNotEmpty(code.getDisplayName())) { + // sb.append("display " + "'" + code.getDisplayName() + "'"); + // } + // sb.append("\n"); + // codeAlreadyUsed.add(codeStr); + // } + // } + // + // sb.append("\n"); + // } + // + // return sb.toString(); + // } + // + // private static StringBuilder createParameterSection(List paramList, + // StringBuilder cqlStr, + // String toBeInserted, + // AtomicInteger size) { + // if (!CollectionUtils.isEmpty(paramList)) { + // + // for (CQLParameter parameter : paramList) { + // + // String param = "parameter " + "\"" + parameter.getName() + "\""; + // + // if (StringUtils.isNotBlank(parameter.getCommentString())) { + // cqlStr.append(createCommentString(parameter.getCommentString())); + // cqlStr.append(System.lineSeparator()); + // } + // + // cqlStr.append(param + " " + parameter.getLogic()); + // cqlStr.append("\n"); + // + // // if the the param we just appended is the current one, then + // // find the size of the file at that time. + // // This will give us the end line of the parameter we are trying to insert. + // if (param.equalsIgnoreCase(toBeInserted)) { + // size.set(getEndLine(cqlStr.toString())); + // } + // + // } + // + // cqlStr.append("\n"); + // } + // + // return cqlStr; + // } + // + // public static String createCommentString(String comment) { + // StringBuilder sb = new StringBuilder(); + // sb.append("/*").append(comment).append("*/"); + // return sb.toString(); + // } + // + // private static void addToListMap(Map> map, O key, T newElem) { + // if (map != null) { + // List l = map.get(key); + // if (CollectionUtils.isEmpty(l)) { + // l = new ArrayList(); + // map.put(key, l); + // } + // l.add(newElem); + // } + // } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/ModelTypeHelper.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/ModelTypeHelper.java index 5d315044..c5e82103 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/ModelTypeHelper.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/ModelTypeHelper.java @@ -25,6 +25,4 @@ public static boolean isFhir(String type) { public static boolean isQdm(String type) { return QDM.equalsIgnoreCase(defaultTypeIfBlank(type)); } - - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CQLParserUtil.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CQLParserUtil.java index 95c2fc34..c51b36b7 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CQLParserUtil.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CQLParserUtil.java @@ -10,15 +10,17 @@ private CQLParserUtil() { public static String parseString(String identifier) { - if(StringUtils.isEmpty(identifier)) { + if (StringUtils.isEmpty(identifier)) { return identifier; } - if(Character.toString(identifier.charAt(0)).equals("\"") || Character.toString(identifier.charAt(0)).equals("'")) { + if (Character.toString(identifier.charAt(0)).equals("\"") + || Character.toString(identifier.charAt(0)).equals("'")) { return identifier.substring(1, identifier.length() - 1); } - if(Character.toString(identifier.charAt(identifier.length() - 1)).equals("\"") || Character.toString(identifier.charAt(0)).equals("'")) { + if (Character.toString(identifier.charAt(identifier.length() - 1)).equals("\"") + || Character.toString(identifier.charAt(0)).equals("'")) { return identifier.substring(0, identifier.length() - 2); } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/Cql2ElmListener.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/Cql2ElmListener.java index aa1108bc..37d21d7b 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/Cql2ElmListener.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/Cql2ElmListener.java @@ -38,487 +38,518 @@ public class Cql2ElmListener extends cqlBaseListener { - /** - * The child CQL strings - */ - private Map childrenLibraries = new HashMap<>(); - - /** - * The identifier of the current library, relative to the library that brought us here. Will be in the form of - * libraryName|alias - */ - private String libraryIdentifier; - - /** - * The include def object which we are current parsing, relative to the library that brought us here. - */ - IncludeDef libraryAccessor = null; - - /** - * The current library object from the parser - */ - private CompiledLibrary library; - - /** - * The map of the other libraries in the current library - */ - Map translatedLibraryMap; - - /** - * The current context, aka which expression are we currently in. - */ - private String currentContext; - - private Set libraries = new HashSet<>(); - private Set valuesets = new HashSet<>(); - private Set codes = new HashSet<>(); - private Set codesystems = new HashSet<>(); - private Set parameters = new HashSet<>(); - private Set definitions = new HashSet<>(); - private Set functions = new HashSet<>(); - private HashMap valueSetOids = new HashMap<>(); - private Map>> valueSetDataTypeMap = new HashMap<>(); - private Map>> codeDataTypeMap = new HashMap<>(); - - private Stack namespace = new Stack<>(); - - private CQLGraph graph; - - public Cql2ElmListener(CQLGraph graph, CompiledLibrary library, Map translatedLibraryMap, - Map childrenLibraries) { - this.graph = graph; - this.library = library; - this.translatedLibraryMap = translatedLibraryMap; - this.libraryIdentifier = ""; - this.childrenLibraries = childrenLibraries; - } - - public Cql2ElmListener(String libraryIdentifier, CQLGraph graph, - CompiledLibrary library, - Map translatedLibraryMap, - Map childrenLibraries) { - this.graph = graph; - this.library = library; - this.translatedLibraryMap = translatedLibraryMap; - this.libraryIdentifier = libraryIdentifier; - this.childrenLibraries = childrenLibraries; - } - - private CompiledLibrary getCurrentLibraryContext() { - if (libraryAccessor != null) { -// return this.translatedLibraryMap.get(libraryAccessor.getPath() + "-" + libraryAccessor.getVersion()); - return this.translatedLibraryMap.get(libraryAccessor.getPath()); - } - - return this.library; - } - - @Override - public void enterQualifiedFunction(QualifiedFunctionContext ctx) { - if (ctx.identifierOrFunctionIdentifier() != null - && ctx.identifierOrFunctionIdentifier().identifier() != null) { - String identifier = parseString(ctx.identifierOrFunctionIdentifier().identifier().getText()); - - if (shouldResolve(identifier)) { - resolve(identifier, getCurrentLibraryContext()); - } - } - - } - - @Override - public void enterQualifiedIdentifierExpression(QualifiedIdentifierExpressionContext ctx) { - String identifier = parseString(ctx.referentialIdentifier().getText()); - String qualifier = ""; - - if (shouldResolve(identifier)) { - // a qualified identifier can take on the form (qualifier) '.')* identifier. If there is only one qualifier, - // then that could be a library. Resolve the qualifier to check if it's a library. - if (CollectionUtils.isNotEmpty(ctx.qualifierExpression()) && ctx.qualifierExpression().get(0) != null) { - qualifier = parseString(ctx.qualifierExpression().get(0).getText()); - if (shouldResolve(qualifier)) { - resolve(qualifier, getCurrentLibraryContext()); - } - } - resolve(identifier, getCurrentLibraryContext()); - } - } - - @Override - public void enterReferentialIdentifier(ReferentialIdentifierContext ctx) { - String identifier = parseString(ctx.getText()); - if (shouldResolve(identifier)) { - resolve(identifier, getCurrentLibraryContext()); - } - } - - @Override - public void enterQualifiedIdentifier(@NotNull cqlParser.QualifiedIdentifierContext ctx) { - String identifier = parseString(ctx.identifier().getText()); - String qualifier = ""; - - if (shouldResolve(identifier)) { - // a qualified identifier can take on the form (qualifier) '.')* identifier. If there is only one qualifier, - // then that could be a library. Resolve the qualifier to check if it's a library. - if (ctx.qualifier(0) != null) { - qualifier = parseString(ctx.qualifier(0).getText()); - if (shouldResolve(qualifier)) { - resolve(qualifier, getCurrentLibraryContext()); - } - } - - resolve(identifier, getCurrentLibraryContext()); - } - } - - private boolean shouldResolve(String identifier) { - // if the namespace contains the identifier, that means it's a local identifier and should not be treated - // as an identifier for an expression. - - // an identifier can also not be equal to patient. - return !namespace.contains(identifier) && !identifier.equalsIgnoreCase("patient"); - } - - @Override - public void enterFunction(@NotNull cqlParser.FunctionContext ctx) { - String identifier = parseString(ctx.referentialIdentifier().getText()); + /** The child CQL strings */ + private Map childrenLibraries = new HashMap<>(); + + /** + * The identifier of the current library, relative to the library that brought us here. Will be in + * the form of libraryName|alias + */ + private String libraryIdentifier; + + /** + * The include def object which we are current parsing, relative to the library that brought us + * here. + */ + IncludeDef libraryAccessor = null; + + /** The current library object from the parser */ + private CompiledLibrary library; + + /** The map of the other libraries in the current library */ + Map translatedLibraryMap; + + /** The current context, aka which expression are we currently in. */ + private String currentContext; + + private Set libraries = new HashSet<>(); + private Set valuesets = new HashSet<>(); + private Set codes = new HashSet<>(); + private Set codesystems = new HashSet<>(); + private Set parameters = new HashSet<>(); + private Set definitions = new HashSet<>(); + private Set functions = new HashSet<>(); + private HashMap valueSetOids = new HashMap<>(); + private Map>> valueSetDataTypeMap = new HashMap<>(); + private Map>> codeDataTypeMap = new HashMap<>(); + + private Stack namespace = new Stack<>(); + + private CQLGraph graph; + + public Cql2ElmListener( + CQLGraph graph, + CompiledLibrary library, + Map translatedLibraryMap, + Map childrenLibraries) { + this.graph = graph; + this.library = library; + this.translatedLibraryMap = translatedLibraryMap; + this.libraryIdentifier = ""; + this.childrenLibraries = childrenLibraries; + } + + public Cql2ElmListener( + String libraryIdentifier, + CQLGraph graph, + CompiledLibrary library, + Map translatedLibraryMap, + Map childrenLibraries) { + this.graph = graph; + this.library = library; + this.translatedLibraryMap = translatedLibraryMap; + this.libraryIdentifier = libraryIdentifier; + this.childrenLibraries = childrenLibraries; + } + + private CompiledLibrary getCurrentLibraryContext() { + if (libraryAccessor != null) { + // return this.translatedLibraryMap.get(libraryAccessor.getPath() + "-" + + // libraryAccessor.getVersion()); + return this.translatedLibraryMap.get(libraryAccessor.getPath()); + } + + return this.library; + } + + @Override + public void enterQualifiedFunction(QualifiedFunctionContext ctx) { + if (ctx.identifierOrFunctionIdentifier() != null + && ctx.identifierOrFunctionIdentifier().identifier() != null) { + String identifier = parseString(ctx.identifierOrFunctionIdentifier().identifier().getText()); + + if (shouldResolve(identifier)) { resolve(identifier, getCurrentLibraryContext()); - libraryAccessor = null; - } - - @Override - public void enterExpressionDefinition(@NotNull cqlParser.ExpressionDefinitionContext ctx) { - String identifier = parseString(ctx.identifier().getText()); - this.currentContext = libraryIdentifier + identifier; - graph.addNode(currentContext); - } - - @Override - public void enterFunctionDefinition(@NotNull cqlParser.FunctionDefinitionContext ctx) { - String identifier = parseString(ctx.identifierOrFunctionIdentifier().getText()); - this.currentContext = libraryIdentifier + identifier; - for (cqlParser.OperandDefinitionContext operand : ctx.operandDefinition()) { - namespace.push(operand.referentialIdentifier().getText()); - } - - graph.addNode(currentContext); - } - - @Override - public void exitFunctionDefinition(@NotNull cqlParser.FunctionDefinitionContext ctx) { - for (cqlParser.OperandDefinitionContext operand : ctx.operandDefinition()) { - namespace.pop(); - } - } - - @Override - public void enterParameterDefinition(@NotNull cqlParser.ParameterDefinitionContext ctx) { - String identifier = parseString(ctx.identifier().getText()); - this.currentContext = libraryIdentifier + identifier; - graph.addNode(currentContext); - } - - @Override - public void enterRetrieve(@NotNull cqlParser.RetrieveContext ctx) { - - // we only care about entering a retrieve if it has a terminology - if (ctx.terminology() == null || ctx.codePath() != null) { - return; - } - - // if the valueset is in the form alias.name, get the alias and resolve it so we can switch to the other - // libraries context - String identifier = ""; - if (CollectionUtils.isNotEmpty(ctx.terminology().qualifiedIdentifierExpression().qualifierExpression()) && ctx.terminology().qualifiedIdentifierExpression().qualifierExpression().get(0) != null) { - resolve(ctx.terminology().qualifiedIdentifierExpression().qualifierExpression().get(0).getText(), getCurrentLibraryContext()); - identifier = parseString(ctx.terminology().qualifiedIdentifierExpression().referentialIdentifier().getText()); - } else { - identifier = parseString(ctx.terminology().getText()); - } - - String formattedIdentifier = formatIdentifier(identifier); - - // we need to resolve based on the identifier since it will be looking in the proper library but we need - // to put the formatted identifier into the maps since this is the format MAT is looking for - String dataType = parseString(ctx.namedTypeSpecifier().referentialOrTypeNameIdentifier().getText()); - Element element = resolve(identifier, getCurrentLibraryContext()); - if (element instanceof ValueSetDef) { - Map> current = valueSetDataTypeMap.get(currentContext); - if (current == null) { - valueSetDataTypeMap.put(currentContext, new HashMap<>()); - } - - current = valueSetDataTypeMap.get(currentContext); - Set currentSet = current.get(formattedIdentifier); - if (currentSet == null) { - currentSet = new HashSet<>(); - current.put(formattedIdentifier, currentSet); - } - - current.get(formattedIdentifier).add(dataType); - valueSetOids.putIfAbsent(formattedIdentifier, ((ValueSetDef) element).getId().substring("urn:oid:".length())); - } else if (element instanceof CodeDef) { - Map> current = codeDataTypeMap.get(currentContext); - if (current == null) { - codeDataTypeMap.put(currentContext, new HashMap<>()); - } - - current = codeDataTypeMap.get(currentContext); - Set currentSet = current.get(formattedIdentifier); - if (currentSet == null) { - currentSet = new HashSet<>(); - current.put(formattedIdentifier, currentSet); - } - - current.get(formattedIdentifier).add(dataType); - } - } - - private void pushAliasesOntoStackForQueries(cqlParser.QueryContext ctx) { - for (AliasedQuerySourceContext source : ctx.sourceClause().aliasedQuerySource()) { - namespace.push(source.alias().getText()); - } - } - - private void popAliasesOffStackForQueries(cqlParser.QueryContext ctx) { - for (AliasedQuerySourceContext source : ctx.sourceClause().aliasedQuerySource()) { - namespace.pop(); - } - } - - @Override - public void enterWhereClause(WhereClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - } - - @Override - public void exitWhereClause(WhereClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - } - - @Override - public void enterWithClause(WithClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + } + + @Override + public void enterQualifiedIdentifierExpression(QualifiedIdentifierExpressionContext ctx) { + String identifier = parseString(ctx.referentialIdentifier().getText()); + String qualifier = ""; + + if (shouldResolve(identifier)) { + // a qualified identifier can take on the form (qualifier) '.')* identifier. If there is only + // one qualifier, + // then that could be a library. Resolve the qualifier to check if it's a library. + if (CollectionUtils.isNotEmpty(ctx.qualifierExpression()) + && ctx.qualifierExpression().get(0) != null) { + qualifier = parseString(ctx.qualifierExpression().get(0).getText()); + if (shouldResolve(qualifier)) { + resolve(qualifier, getCurrentLibraryContext()); } - - namespace.push(ctx.aliasedQuerySource().alias().getText()); - } - - @Override - public void exitWithClause(WithClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - - namespace.pop(); - } - - @Override - public void enterWithoutClause(WithoutClauseContext ctx) { - namespace.push(ctx.aliasedQuerySource().alias().getText()); - } - - @Override - public void exitWithoutClause(WithoutClauseContext ctx) { - namespace.pop(); - } - - @Override - public void enterLetClause(LetClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - } - - @Override - public void exitLetClause(LetClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + resolve(identifier, getCurrentLibraryContext()); + } + } + + @Override + public void enterReferentialIdentifier(ReferentialIdentifierContext ctx) { + String identifier = parseString(ctx.getText()); + if (shouldResolve(identifier)) { + resolve(identifier, getCurrentLibraryContext()); + } + } + + @Override + public void enterQualifiedIdentifier(@NotNull cqlParser.QualifiedIdentifierContext ctx) { + String identifier = parseString(ctx.identifier().getText()); + String qualifier = ""; + + if (shouldResolve(identifier)) { + // a qualified identifier can take on the form (qualifier) '.')* identifier. If there is only + // one qualifier, + // then that could be a library. Resolve the qualifier to check if it's a library. + if (ctx.qualifier(0) != null) { + qualifier = parseString(ctx.qualifier(0).getText()); + if (shouldResolve(qualifier)) { + resolve(qualifier, getCurrentLibraryContext()); } - } - - @Override - public void enterReturnClause(ReturnClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + + resolve(identifier, getCurrentLibraryContext()); + } + } + + private boolean shouldResolve(String identifier) { + // if the namespace contains the identifier, that means it's a local identifier and should not + // be treated + // as an identifier for an expression. + + // an identifier can also not be equal to patient. + return !namespace.contains(identifier) && !identifier.equalsIgnoreCase("patient"); + } + + @Override + public void enterFunction(@NotNull cqlParser.FunctionContext ctx) { + String identifier = parseString(ctx.referentialIdentifier().getText()); + resolve(identifier, getCurrentLibraryContext()); + libraryAccessor = null; + } + + @Override + public void enterExpressionDefinition(@NotNull cqlParser.ExpressionDefinitionContext ctx) { + String identifier = parseString(ctx.identifier().getText()); + this.currentContext = libraryIdentifier + identifier; + graph.addNode(currentContext); + } + + @Override + public void enterFunctionDefinition(@NotNull cqlParser.FunctionDefinitionContext ctx) { + String identifier = parseString(ctx.identifierOrFunctionIdentifier().getText()); + this.currentContext = libraryIdentifier + identifier; + for (cqlParser.OperandDefinitionContext operand : ctx.operandDefinition()) { + namespace.push(operand.referentialIdentifier().getText()); + } + + graph.addNode(currentContext); + } + + @Override + public void exitFunctionDefinition(@NotNull cqlParser.FunctionDefinitionContext ctx) { + for (cqlParser.OperandDefinitionContext operand : ctx.operandDefinition()) { + namespace.pop(); + } + } + + @Override + public void enterParameterDefinition(@NotNull cqlParser.ParameterDefinitionContext ctx) { + String identifier = parseString(ctx.identifier().getText()); + this.currentContext = libraryIdentifier + identifier; + graph.addNode(currentContext); + } + + @Override + public void enterRetrieve(@NotNull cqlParser.RetrieveContext ctx) { + + // we only care about entering a retrieve if it has a terminology + if (ctx.terminology() == null || ctx.codePath() != null) { + return; + } + + // if the valueset is in the form alias.name, get the alias and resolve it so we can switch to + // the other + // libraries context + String identifier = ""; + if (CollectionUtils.isNotEmpty( + ctx.terminology().qualifiedIdentifierExpression().qualifierExpression()) + && ctx.terminology().qualifiedIdentifierExpression().qualifierExpression().get(0) != null) { + resolve( + ctx.terminology().qualifiedIdentifierExpression().qualifierExpression().get(0).getText(), + getCurrentLibraryContext()); + identifier = + parseString( + ctx.terminology().qualifiedIdentifierExpression().referentialIdentifier().getText()); + } else { + identifier = parseString(ctx.terminology().getText()); + } + + String formattedIdentifier = formatIdentifier(identifier); + + // we need to resolve based on the identifier since it will be looking in the proper library but + // we need + // to put the formatted identifier into the maps since this is the format MAT is looking for + String dataType = + parseString(ctx.namedTypeSpecifier().referentialOrTypeNameIdentifier().getText()); + Element element = resolve(identifier, getCurrentLibraryContext()); + if (element instanceof ValueSetDef) { + Map> current = valueSetDataTypeMap.get(currentContext); + if (current == null) { + valueSetDataTypeMap.put(currentContext, new HashMap<>()); + } + + current = valueSetDataTypeMap.get(currentContext); + Set currentSet = current.get(formattedIdentifier); + if (currentSet == null) { + currentSet = new HashSet<>(); + current.put(formattedIdentifier, currentSet); + } + + current.get(formattedIdentifier).add(dataType); + valueSetOids.putIfAbsent( + formattedIdentifier, ((ValueSetDef) element).getId().substring("urn:oid:".length())); + } else if (element instanceof CodeDef) { + Map> current = codeDataTypeMap.get(currentContext); + if (current == null) { + codeDataTypeMap.put(currentContext, new HashMap<>()); + } + + current = codeDataTypeMap.get(currentContext); + Set currentSet = current.get(formattedIdentifier); + if (currentSet == null) { + currentSet = new HashSet<>(); + current.put(formattedIdentifier, currentSet); + } + + current.get(formattedIdentifier).add(dataType); + } + } + + private void pushAliasesOntoStackForQueries(cqlParser.QueryContext ctx) { + for (AliasedQuerySourceContext source : ctx.sourceClause().aliasedQuerySource()) { + namespace.push(source.alias().getText()); + } + } + + private void popAliasesOffStackForQueries(cqlParser.QueryContext ctx) { + for (AliasedQuerySourceContext source : ctx.sourceClause().aliasedQuerySource()) { + namespace.pop(); + } + } + + @Override + public void enterWhereClause(WhereClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void exitWhereClause(WhereClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void enterWithClause(WithClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + + namespace.push(ctx.aliasedQuerySource().alias().getText()); + } + + @Override + public void exitWithClause(WithClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + + namespace.pop(); + } + + @Override + public void enterWithoutClause(WithoutClauseContext ctx) { + namespace.push(ctx.aliasedQuerySource().alias().getText()); + } + + @Override + public void exitWithoutClause(WithoutClauseContext ctx) { + namespace.pop(); + } + + @Override + public void enterLetClause(LetClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void exitLetClause(LetClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void enterReturnClause(ReturnClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void exitReturnClause(ReturnClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void enterSortClause(SortClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + @Override + public void exitSortClause(SortClauseContext ctx) { + if (ctx.parent instanceof cqlParser.QueryContext) { + popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); + } + } + + public String parseString(String s) { + return s.replace("\"", ""); + } + + /** + * Formats the identifier based on where it is relative to the parent library + * + * @param identifier the identifier to format + * @return + */ + private String formatIdentifier(String identifier) { + String formattedIdentifier = ""; + + // if we are looking at an expression from some child library (aka an expression alias.name) + // build the + // formatted expression based on the library it came from. + if (libraryAccessor != null) { + String path = libraryAccessor.getPath() + "-" + libraryAccessor.getVersion(); + String alias = libraryAccessor.getLocalIdentifier(); + formattedIdentifier = path + "|" + alias + "|" + identifier; + } else { + // if the expression is in a child library or grandchild library (relative to the parent) then + // format and + // then format that identifier with the details of the current library + if (this.libraryIdentifier != null) { + formattedIdentifier = libraryIdentifier + identifier; + } else { + // if the expression is in the parent library, then make the formatted identifier the + // current identifier. + formattedIdentifier = identifier; + } + } + + return formattedIdentifier; + } + + private Element resolve(String identifier, CompiledLibrary library) { + Element element = library.resolve(identifier); + String formattedIdentifier = formatIdentifier(identifier); + libraryAccessor = + null; // we've done all we need to do with the accessor, so set it equal to null so it can + // be + // updated again if need be. + if (element instanceof IncludeDef) { + IncludeDef def = (IncludeDef) element; + graph.addEdge( + currentContext, def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier()); + libraryAccessor = def; + if (!libraries.contains( + def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier())) { + try { + parseChildLibraries(def); + libraries.add(def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier()); + } catch (IOException e) { + e.printStackTrace(); } - } - - @Override - public void exitReturnClause(ReturnClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - } - - @Override - public void enterSortClause(SortClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - pushAliasesOntoStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - } - - @Override - public void exitSortClause(SortClauseContext ctx) { - if (ctx.parent instanceof cqlParser.QueryContext) { - popAliasesOffStackForQueries(((cqlParser.QueryContext) ctx.parent)); - } - } - - public String parseString(String s) { - return s.replace("\"", ""); - } - - /** - * Formats the identifier based on where it is relative to the parent library - * - * @param identifier the identifier to format - * @return - */ - private String formatIdentifier(String identifier) { - String formattedIdentifier = ""; - - // if we are looking at an expression from some child library (aka an expression alias.name) build the - // formatted expression based on the library it came from. - if (libraryAccessor != null) { - String path = libraryAccessor.getPath() + "-" + libraryAccessor.getVersion(); - String alias = libraryAccessor.getLocalIdentifier(); - formattedIdentifier = path + "|" + alias + "|" + identifier; - } else { - // if the expression is in a child library or grandchild library (relative to the parent) then format and - // then format that identifier with the details of the current library - if (this.libraryIdentifier != null) { - formattedIdentifier = libraryIdentifier + identifier; - } else { - // if the expression is in the parent library, then make the formatted identifier the current identifier. - formattedIdentifier = identifier; - } - } - - return formattedIdentifier; - } - - private Element resolve(String identifier, CompiledLibrary library) { - Element element = library.resolve(identifier); - String formattedIdentifier = formatIdentifier(identifier); - libraryAccessor = null; // we've done all we need to do with the accessor, so set it equal to null so it can be - // updated again if need be. - if (element instanceof IncludeDef) { - IncludeDef def = (IncludeDef) element; - graph.addEdge(currentContext, def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier()); - libraryAccessor = def; - if (!libraries.contains(def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier())) { - try { - parseChildLibraries(def); - libraries.add(def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier()); - } catch (IOException e) { - e.printStackTrace(); - } - } - } else if (element instanceof CodeDef) { - codes.add(formattedIdentifier); - graph.addEdge(currentContext, formattedIdentifier); - } else if (element instanceof CodeSystemDef) { - codesystems.add(identifier); - graph.addEdge(currentContext, formattedIdentifier); - } else if (element instanceof ValueSetDef) { - valuesets.add(formattedIdentifier); - graph.addEdge(currentContext, formattedIdentifier); - } else if (element instanceof ParameterDef) { - parameters.add(formattedIdentifier); - graph.addEdge(currentContext, formattedIdentifier); - } else if (element instanceof ExpressionDef) { - definitions.add(formattedIdentifier); - graph.addEdge(currentContext, formattedIdentifier); - } else { - final String finalFormattedIdentifier = formattedIdentifier; - library.getLibrary().getStatements().getDef().forEach((def) -> { + } + } else if (element instanceof CodeDef) { + codes.add(formattedIdentifier); + graph.addEdge(currentContext, formattedIdentifier); + } else if (element instanceof CodeSystemDef) { + codesystems.add(identifier); + graph.addEdge(currentContext, formattedIdentifier); + } else if (element instanceof ValueSetDef) { + valuesets.add(formattedIdentifier); + graph.addEdge(currentContext, formattedIdentifier); + } else if (element instanceof ParameterDef) { + parameters.add(formattedIdentifier); + graph.addEdge(currentContext, formattedIdentifier); + } else if (element instanceof ExpressionDef) { + definitions.add(formattedIdentifier); + graph.addEdge(currentContext, formattedIdentifier); + } else { + final String finalFormattedIdentifier = formattedIdentifier; + library + .getLibrary() + .getStatements() + .getDef() + .forEach( + (def) -> { if (def.getName().equals(identifier)) { - functions.add(finalFormattedIdentifier); - graph.addEdge(currentContext, finalFormattedIdentifier); + functions.add(finalFormattedIdentifier); + graph.addEdge(currentContext, finalFormattedIdentifier); } - }); - } - - return element; - } - - private void parseChildLibraries(IncludeDef def) throws IOException { - String childCQLString = this.childrenLibraries.get(def.getPath() + "-" + def.getVersion()); - - InputStream stream = new ByteArrayInputStream(childCQLString.getBytes(StandardCharsets.UTF_8)); - cqlLexer lexer = new cqlLexer(CharStreams.fromStream(stream)); - CommonTokenStream tokens = new CommonTokenStream(lexer); - cqlParser parser = new cqlParser(tokens); - -// CompiledLibrary childLibrary = this.translatedLibraryMap.get(def.getPath() + "-" + def.getVersion()); - CompiledLibrary childLibrary = this.translatedLibraryMap.get(def.getPath()); - Cql2ElmListener listener = new Cql2ElmListener(def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier() + "|", graph, childLibrary, translatedLibraryMap, childrenLibraries); - ParseTree tree = parser.library(); - CqlPreprocessorVisitor preprocessor = new CqlPreprocessorVisitor(); - preprocessor.setTokenStream(tokens); - preprocessor.visit(tree); - ParseTreeWalker walker = new ParseTreeWalker(); - walker.walk(listener, tree); - - libraries.addAll(listener.getLibraries()); - valuesets.addAll(listener.getValuesets()); - codes.addAll(listener.getCodes()); - codesystems.addAll(listener.getCodesystems()); - parameters.addAll(listener.getParameters()); - definitions.addAll(listener.getDefinitions()); - functions.addAll(listener.getFunctions()); - valueSetDataTypeMap.putAll(listener.getValueSetDataTypeMap()); - codeDataTypeMap.putAll(listener.getCodeDataTypeMap()); - valueSetOids.putAll(listener.getValueSetOids()); - } - - public Set getLibraries() { - return libraries; - } - - public Set getValuesets() { - return valuesets; - } - - public Set getCodes() { - return codes; - } - - public Set getCodesystems() { - return codesystems; - } - - public Set getParameters() { - return parameters; - } - - public Set getDefinitions() { - return definitions; - } - - public Set getFunctions() { - return functions; - } - - public Map>> getValueSetDataTypeMap() { - return valueSetDataTypeMap; - } - - public Map>> getCodeDataTypeMap() { - return codeDataTypeMap; - } - - public Map getValueSetOids() { - return valueSetOids; - } - - public CQLGraph getGraph() { - return graph; - } + }); + } + + return element; + } + + private void parseChildLibraries(IncludeDef def) throws IOException { + String childCQLString = this.childrenLibraries.get(def.getPath() + "-" + def.getVersion()); + + InputStream stream = new ByteArrayInputStream(childCQLString.getBytes(StandardCharsets.UTF_8)); + cqlLexer lexer = new cqlLexer(CharStreams.fromStream(stream)); + CommonTokenStream tokens = new CommonTokenStream(lexer); + cqlParser parser = new cqlParser(tokens); + + // CompiledLibrary childLibrary = this.translatedLibraryMap.get(def.getPath() + "-" + + // def.getVersion()); + CompiledLibrary childLibrary = this.translatedLibraryMap.get(def.getPath()); + Cql2ElmListener listener = + new Cql2ElmListener( + def.getPath() + "-" + def.getVersion() + "|" + def.getLocalIdentifier() + "|", + graph, + childLibrary, + translatedLibraryMap, + childrenLibraries); + ParseTree tree = parser.library(); + CqlPreprocessorVisitor preprocessor = new CqlPreprocessorVisitor(); + preprocessor.setTokenStream(tokens); + preprocessor.visit(tree); + ParseTreeWalker walker = new ParseTreeWalker(); + walker.walk(listener, tree); + + libraries.addAll(listener.getLibraries()); + valuesets.addAll(listener.getValuesets()); + codes.addAll(listener.getCodes()); + codesystems.addAll(listener.getCodesystems()); + parameters.addAll(listener.getParameters()); + definitions.addAll(listener.getDefinitions()); + functions.addAll(listener.getFunctions()); + valueSetDataTypeMap.putAll(listener.getValueSetDataTypeMap()); + codeDataTypeMap.putAll(listener.getCodeDataTypeMap()); + valueSetOids.putAll(listener.getValueSetOids()); + } + + public Set getLibraries() { + return libraries; + } + + public Set getValuesets() { + return valuesets; + } + + public Set getCodes() { + return codes; + } + + public Set getCodesystems() { + return codesystems; + } + + public Set getParameters() { + return parameters; + } + + public Set getDefinitions() { + return definitions; + } + + public Set getFunctions() { + return functions; + } + + public Map>> getValueSetDataTypeMap() { + return valueSetDataTypeMap; + } + + public Map>> getCodeDataTypeMap() { + return codeDataTypeMap; + } + + public Map getValueSetOids() { + return valueSetOids; + } + + public CQLGraph getGraph() { + return graph; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CqlParserListener.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CqlParserListener.java index cc19be3b..3de55dd3 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CqlParserListener.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/CqlParserListener.java @@ -22,15 +22,24 @@ import org.cqframework.cql.gen.cqlParser.OperandDefinitionContext; import org.cqframework.cql.gen.cqlParser.ParameterDefinitionContext; -/** - * MAT's ReverseEngineeringListener - */ +/** MAT's ReverseEngineeringListener */ public class CqlParserListener extends cqlBaseListener { private static final String DEFINE = "define"; private static final String CONTEXT = "context"; private static final String PARAMETER = "parameter"; - private static final List CQL_DATA_TYPES = List.of("Boolean", "Date", "DateTime", "Decimal", "Integer", "QDM Datatype", "Ratio", "String", "Time", "Others"); + private static final List CQL_DATA_TYPES = + List.of( + "Boolean", + "Date", + "DateTime", + "Decimal", + "Integer", + "QDM Datatype", + "Ratio", + "String", + "Time", + "Others"); private cqlParser parser; private CommonTokenStream tokens; private CQLModel cqlModel; @@ -42,8 +51,13 @@ private static class SyntaxErrorListener extends BaseErrorListener { private List errors = new ArrayList<>(); @Override - public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, - String msg, RecognitionException e) { + public void syntaxError( + Recognizer recognizer, + Object offendingSymbol, + int line, + int charPositionInLine, + String msg, + RecognitionException e) { CQLError error = new CQLError(); error.setErrorMessage(msg); error.setErrorInLine(line - 1); @@ -77,16 +91,16 @@ public CqlParserListener(String cql) throws IOException { private void initializeNewModel() { cqlModel = new CQLModel(); -// cqlModel.setLibraryName(previousModel.getLibraryName()); -// cqlModel.setVersionUsed(previousModel.getVersionUsed()); -// cqlModel.setLibraryComment(previousModel.getLibraryComment()); -// cqlModel.setUsingModel(previousModel.getUsingModel()); -// cqlModel.setUsingModelVersion(previousModel.getUsingModelVersion()); -// -// cqlModel.setCqlIncludeLibraries(previousModel.getCqlIncludeLibraries()); -// cqlModel.setCodeSystemList(previousModel.getCodeSystemList()); -// cqlModel.setCodeList(previousModel.getCodeList()); -// cqlModel.setValueSetList(previousModel.getValueSetList()); + // cqlModel.setLibraryName(previousModel.getLibraryName()); + // cqlModel.setVersionUsed(previousModel.getVersionUsed()); + // cqlModel.setLibraryComment(previousModel.getLibraryComment()); + // cqlModel.setUsingModel(previousModel.getUsingModel()); + // cqlModel.setUsingModelVersion(previousModel.getUsingModelVersion()); + // + // cqlModel.setCqlIncludeLibraries(previousModel.getCqlIncludeLibraries()); + // cqlModel.setCodeSystemList(previousModel.getCodeSystemList()); + // cqlModel.setCodeList(previousModel.getCodeList()); + // cqlModel.setValueSetList(previousModel.getValueSetList()); } @Override @@ -132,10 +146,15 @@ private String getParameterLogic(ParameterDefinitionContext ctx, String identifi builder.append(t.getText()); } - return builder.toString().replaceFirst(PARAMETER, "").replace("public", "").replace("private", "").replace(identifier, "").trim(); + return builder + .toString() + .replaceFirst(PARAMETER, "") + .replace("public", "") + .replace("private", "") + .replace(identifier, "") + .trim(); } - @Override public void enterExpressionDefinition(ExpressionDefinitionContext ctx) { String identifier = CQLParserUtil.parseString(getFullText(ctx.identifier())); @@ -146,7 +165,6 @@ public void enterExpressionDefinition(ExpressionDefinitionContext ctx) { definition.setId(UUID.nameUUIDFromBytes(identifier.getBytes()).toString()); definition.setName(identifier); - definition.setContext(currentContext); definition.setCommentString(comment); definition.setLogic(CQLUtilityClass.replaceFirstWhitespaceInLineForExpression(logic)); @@ -156,7 +174,8 @@ public void enterExpressionDefinition(ExpressionDefinitionContext ctx) { @Override public void enterFunctionDefinition(FunctionDefinitionContext ctx) { - String identifier = CQLParserUtil.parseString(getFullText(ctx.identifierOrFunctionIdentifier())); + String identifier = + CQLParserUtil.parseString(getFullText(ctx.identifierOrFunctionIdentifier())); String logic = getDefinitionAndFunctionLogic(ctx).trim(); String comment = getExpressionComment(ctx).trim(); @@ -203,9 +222,14 @@ public void enterFunctionDefinition(FunctionDefinitionContext ctx) { } private String getFullText(ParserRuleContext context) { - if (context.start == null || context.stop == null || context.start.getStartIndex() < 0 || context.stop.getStopIndex() < 0) - return context.getText(); - return context.start.getInputStream().getText(Interval.of(context.start.getStartIndex(), context.stop.getStopIndex())); + if (context.start == null + || context.stop == null + || context.start.getStartIndex() < 0 + || context.stop.getStopIndex() < 0) return context.getText(); + return context + .start + .getInputStream() + .getText(Interval.of(context.start.getStartIndex(), context.stop.getStopIndex())); } private String getExpressionComment(ParserRuleContext ctx) { @@ -249,8 +273,8 @@ public CQLModel getCQLModel() { } /** - * A definition or function body should be considered done when it reaches the next define statement - * or it reaches a comment for the next expression. + * A definition or function body should be considered done when it reaches the next define + * statement or it reaches a comment for the next expression. * * @param ctx the context to find the end of the body of * @return the index of the last token in the body @@ -262,7 +286,10 @@ private int findExpressionLogicStop(ParserRuleContext ctx) { // find the next define statement boolean startAdding = false; for (Token t : ts) { - if ((t.getText().equals(DEFINE) || t.getText().contentEquals(PARAMETER) || t.getText().equals(CONTEXT)) && startAdding) { + if ((t.getText().equals(DEFINE) + || t.getText().contentEquals(PARAMETER) + || t.getText().equals(CONTEXT)) + && startAdding) { index = t.getTokenIndex(); break; } @@ -273,7 +300,6 @@ private int findExpressionLogicStop(ParserRuleContext ctx) { } } - if (tokens.get(index).getText().equals(CONTEXT)) { return index - 1; } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMContainer.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMContainer.java index e09311ac..9ab05b39 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMContainer.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMContainer.java @@ -15,9 +15,7 @@ public class QDMContainer { private Map> datatypeToAttributesMap = new HashMap<>(); private Map> qdmAttributeToTypeMap = new HashMap<>(); - public QDMContainer() { - - } + public QDMContainer() {} public QDMContainer(final Map> datatypeToAttributesMap) { this.datatypeToAttributesMap = datatypeToAttributesMap; @@ -27,7 +25,7 @@ public Map> getDatatypeToAttributesMap() { return datatypeToAttributesMap; } - public void setDatatypeToAttributesMap(final Map> datatypeToAttributesMap ) { + public void setDatatypeToAttributesMap(final Map> datatypeToAttributesMap) { this.datatypeToAttributesMap = datatypeToAttributesMap; } @@ -41,6 +39,7 @@ public void setQdmAttributeToTypeMap(final Map> qdmAttribut /** * Gets the attributes for a given datatype + * * @param datatype the datatype to find by, e.g. Encounter, Performed * @return the list of attributes for that datatype */ @@ -48,9 +47,7 @@ public List getAttributesByDatatype(final String datatype) { return datatypeToAttributesMap.get(datatype); } - /** - * Gets a list of all distinct attributes - */ + /** Gets a list of all distinct attributes */ public List getAttributes() { final Set attributes = new HashSet<>(); datatypeToAttributesMap.forEach((k, v) -> attributes.addAll(v)); @@ -63,6 +60,7 @@ public List getAttributes() { /** * Gets a list of all distinct qdm datatypes + * * @return */ public List getDatatypes() { @@ -73,12 +71,24 @@ public List getCQLTypeByAttribute(final String attribute) { return qdmAttributeToTypeMap.get(attribute); } - private List getSubAttributesList(){ + private List getSubAttributesList() { qdmAttributeToTypeMap.put("locationPeriod", Arrays.asList("interval")); qdmAttributeToTypeMap.put("denominator", Arrays.asList(SYSTEM_QUANTITY)); qdmAttributeToTypeMap.put("numerator", Arrays.asList(SYSTEM_QUANTITY)); qdmAttributeToTypeMap.put("low", Arrays.asList(SYSTEM_QUANTITY)); qdmAttributeToTypeMap.put("high", Arrays.asList(SYSTEM_QUANTITY)); - return Arrays.asList("denominator", "high", "locationPeriod", "low", "namingSystem", "numerator", "unit", "value", "presentOnAdmissionIndicator", "specialty", "role", "qualification"); + return Arrays.asList( + "denominator", + "high", + "locationPeriod", + "low", + "namingSystem", + "numerator", + "unit", + "value", + "presentOnAdmissionIndicator", + "specialty", + "role", + "qualification"); } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMUtil.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMUtil.java index 3ec34f3b..d905850c 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMUtil.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/QDMUtil.java @@ -18,125 +18,134 @@ public class QDMUtil { - private static final QdmModelInfoProvider qdmModelInfoProvider = new QdmModelInfoProvider(); - - private QDMUtil() { - throw new IllegalStateException(); - } - - public static QDMContainer getQDMContainer() { - - QDMContainer qdmContainer = new QDMContainer(); - ModelIdentifier modelIdentifier = new ModelIdentifier(); - modelIdentifier.setId("QDM"); - modelIdentifier.setVersion("5.6"); - ModelInfo modelInfo = qdmModelInfoProvider.load(modelIdentifier); - - Map nameToProfileInfoMap = new HashMap<>(); - Map nameToClassInfoMap = new HashMap<>(); - - // pre-process this information to be more efficient - buildProfileAndClassInfoMaps(modelInfo, nameToProfileInfoMap, nameToClassInfoMap); - - Map> dataTypeToAttributeMap = new HashMap<>(); - Map> attributeToCQLTypeMap = new HashMap<>(); - // create the data type label --> attribute map - nameToProfileInfoMap.forEach((k, v) -> { - String label = ((ClassInfo) v).getLabel(); // e.g. Encounter, Performed - String baseType = v.getBaseType(); // e.g. QDM.EncounterPerformed - - // this accounts for elements that are not a profile - // for example QDM.CareGoal is not a profile and has a base type of QDM.QDMBaseType - // we still want to collect information about it, but we do not want attributes for the base type, but - // rather we want attributes for the current datatype so we will use it's name (QDM.CareGoal) so that - // we can look up information about the current datatypes attribute. - - // We only want to use base type information if it is a profile. For example, QDM.PositiveEncounterPerformed - // has a base type of QDM.EncounterPerformed. We can than use this base type to look up the attributes for - // that datatype. - if (baseType.equals("QDM.QDMBaseType")) { - baseType = ((ClassInfo) v).getName(); - } - - ClassInfo classInfo = nameToClassInfoMap.get(baseType); - if (!dataTypeToAttributeMap.containsKey(label)) { - dataTypeToAttributeMap.put(label, new ArrayList<>()); - } - - List attributesForDataType = new ArrayList<>(); - attributesForDataType.addAll(classInfo.getElement()); // adds data type specific attributes - attributesForDataType.addAll(nameToClassInfoMap.get("QDM.QDMBaseType").getElement()); // add base type attributes - - if (classInfo.getElement() != null) { - for (ClassInfoElement attribute : attributesForDataType) { - dataTypeToAttributeMap.get(label).add(attribute.getName()); - collectAttributeTypeInformation(attributeToCQLTypeMap, label, attribute); - } + private static final QdmModelInfoProvider qdmModelInfoProvider = new QdmModelInfoProvider(); + + private QDMUtil() { + throw new IllegalStateException(); + } + + public static QDMContainer getQDMContainer() { + + QDMContainer qdmContainer = new QDMContainer(); + ModelIdentifier modelIdentifier = new ModelIdentifier(); + modelIdentifier.setId("QDM"); + modelIdentifier.setVersion("5.6"); + ModelInfo modelInfo = qdmModelInfoProvider.load(modelIdentifier); + + Map nameToProfileInfoMap = new HashMap<>(); + Map nameToClassInfoMap = new HashMap<>(); + + // pre-process this information to be more efficient + buildProfileAndClassInfoMaps(modelInfo, nameToProfileInfoMap, nameToClassInfoMap); + + Map> dataTypeToAttributeMap = new HashMap<>(); + Map> attributeToCQLTypeMap = new HashMap<>(); + // create the data type label --> attribute map + nameToProfileInfoMap.forEach( + (k, v) -> { + String label = ((ClassInfo) v).getLabel(); // e.g. Encounter, Performed + String baseType = v.getBaseType(); // e.g. QDM.EncounterPerformed + + // this accounts for elements that are not a profile + // for example QDM.CareGoal is not a profile and has a base type of QDM.QDMBaseType + // we still want to collect information about it, but we do not want attributes for the + // base type, but + // rather we want attributes for the current datatype so we will use it's name + // (QDM.CareGoal) so that + // we can look up information about the current datatypes attribute. + + // We only want to use base type information if it is a profile. For example, + // QDM.PositiveEncounterPerformed + // has a base type of QDM.EncounterPerformed. We can than use this base type to look up + // the attributes for + // that datatype. + if (baseType.equals("QDM.QDMBaseType")) { + baseType = ((ClassInfo) v).getName(); + } + + ClassInfo classInfo = nameToClassInfoMap.get(baseType); + if (!dataTypeToAttributeMap.containsKey(label)) { + dataTypeToAttributeMap.put(label, new ArrayList<>()); + } + + List attributesForDataType = new ArrayList<>(); + attributesForDataType.addAll( + classInfo.getElement()); // adds data type specific attributes + attributesForDataType.addAll( + nameToClassInfoMap.get("QDM.QDMBaseType").getElement()); // add base type attributes + + if (classInfo.getElement() != null) { + for (ClassInfoElement attribute : attributesForDataType) { + dataTypeToAttributeMap.get(label).add(attribute.getName()); + collectAttributeTypeInformation(attributeToCQLTypeMap, label, attribute); } + } }); - qdmContainer.setDatatypeToAttributesMap(dataTypeToAttributeMap); - qdmContainer.setQdmAttributeToTypeMap(attributeToCQLTypeMap); - return qdmContainer; - } - - private static void buildProfileAndClassInfoMaps(ModelInfo modelInfo, Map nameToProfileInfoMap, - Map nameToClassInfoMap) { - List typeInfoList = modelInfo.getTypeInfo(); - for (TypeInfo typeInfo : typeInfoList) { - - if (typeInfo instanceof ProfileInfo) { - ProfileInfo currentProfileInfo = (ProfileInfo) typeInfo; - nameToProfileInfoMap.put(currentProfileInfo.getName(), currentProfileInfo); - } - - if (typeInfo instanceof ClassInfo) { - ClassInfo currentClassInfo = (ClassInfo) typeInfo; - nameToClassInfoMap.put(currentClassInfo.getName(), currentClassInfo); - - if (currentClassInfo.getLabel() != null) { - nameToProfileInfoMap.put(currentClassInfo.getName(), currentClassInfo); - } - } + qdmContainer.setDatatypeToAttributesMap(dataTypeToAttributeMap); + qdmContainer.setQdmAttributeToTypeMap(attributeToCQLTypeMap); + return qdmContainer; + } + + private static void buildProfileAndClassInfoMaps( + ModelInfo modelInfo, + Map nameToProfileInfoMap, + Map nameToClassInfoMap) { + List typeInfoList = modelInfo.getTypeInfo(); + for (TypeInfo typeInfo : typeInfoList) { + + if (typeInfo instanceof ProfileInfo) { + ProfileInfo currentProfileInfo = (ProfileInfo) typeInfo; + nameToProfileInfoMap.put(currentProfileInfo.getName(), currentProfileInfo); + } + + if (typeInfo instanceof ClassInfo) { + ClassInfo currentClassInfo = (ClassInfo) typeInfo; + nameToClassInfoMap.put(currentClassInfo.getName(), currentClassInfo); + + if (currentClassInfo.getLabel() != null) { + nameToProfileInfoMap.put(currentClassInfo.getName(), currentClassInfo); } + } } + } - private static void collectAttributeTypeInformation(Map> attributeToCQLTypeMap, String label, - ClassInfoElement attribute) { - if (!attributeToCQLTypeMap.containsKey(label)) { - attributeToCQLTypeMap.put(attribute.getName(), new ArrayList<>()); - } + private static void collectAttributeTypeInformation( + Map> attributeToCQLTypeMap, String label, ClassInfoElement attribute) { + if (!attributeToCQLTypeMap.containsKey(label)) { + attributeToCQLTypeMap.put(attribute.getName(), new ArrayList<>()); + } - if (attribute.getTypeSpecifier() != null) { - // handles the case where the attribute has a type of choice type specifier - getAttributesFromChoiceTypeSpecifier(attributeToCQLTypeMap, attribute); - } else { - // handle the case where it is a normal attribute - // we shouldn't put clarifying attributes for System.Code - attributeToCQLTypeMap.get(attribute.getName()).add(attribute.getType()); - } + if (attribute.getTypeSpecifier() != null) { + // handles the case where the attribute has a type of choice type specifier + getAttributesFromChoiceTypeSpecifier(attributeToCQLTypeMap, attribute); + } else { + // handle the case where it is a normal attribute + // we shouldn't put clarifying attributes for System.Code + attributeToCQLTypeMap.get(attribute.getName()).add(attribute.getType()); } + } - private static void getAttributesFromChoiceTypeSpecifier(Map> attributeToCQLTypeMap, - ClassInfoElement attribute) { + private static void getAttributesFromChoiceTypeSpecifier( + Map> attributeToCQLTypeMap, ClassInfoElement attribute) { - ChoiceTypeSpecifier choiceTypeSpecifier = getChoiceTypeSpecifier(attribute); - for (TypeSpecifier typeSpecifier : choiceTypeSpecifier.getChoice()) { - NamedTypeSpecifier namedTypeSpecifier = (NamedTypeSpecifier) typeSpecifier; - String formattedType = namedTypeSpecifier.getModelName() + "." + namedTypeSpecifier.getName(); + ChoiceTypeSpecifier choiceTypeSpecifier = getChoiceTypeSpecifier(attribute); + for (TypeSpecifier typeSpecifier : choiceTypeSpecifier.getChoice()) { + NamedTypeSpecifier namedTypeSpecifier = (NamedTypeSpecifier) typeSpecifier; + String formattedType = namedTypeSpecifier.getModelName() + "." + namedTypeSpecifier.getName(); - // we shouldn't put clarifying attributes for System.Code - attributeToCQLTypeMap.get(attribute.getName()).add(formattedType); - } + // we shouldn't put clarifying attributes for System.Code + attributeToCQLTypeMap.get(attribute.getName()).add(formattedType); } + } - private static ChoiceTypeSpecifier getChoiceTypeSpecifier(ClassInfoElement attribute) { + private static ChoiceTypeSpecifier getChoiceTypeSpecifier(ClassInfoElement attribute) { - if (attribute.getTypeSpecifier() instanceof ListTypeSpecifier) { - ListTypeSpecifier listTypeSpecifier = (ListTypeSpecifier) attribute.getTypeSpecifier(); - return (ChoiceTypeSpecifier) listTypeSpecifier.getElementTypeSpecifier(); - } else { - return (ChoiceTypeSpecifier) attribute.getTypeSpecifier(); - } + if (attribute.getTypeSpecifier() instanceof ListTypeSpecifier) { + ListTypeSpecifier listTypeSpecifier = (ListTypeSpecifier) attribute.getTypeSpecifier(); + return (ChoiceTypeSpecifier) listTypeSpecifier.getElementTypeSpecifier(); + } else { + return (ChoiceTypeSpecifier) attribute.getTypeSpecifier(); } + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCode.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCode.java index 6725f212..8c4ff8f8 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCode.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCode.java @@ -1,263 +1,263 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - import lombok.AllArgsConstructor; import lombok.Builder; import lombok.NoArgsConstructor; import java.util.Objects; -/** - * The Class CQLCode. - */ +/** The Class CQLCode. */ @Builder @NoArgsConstructor @AllArgsConstructor public class CQLCode implements CQLExpression { - /** - * The id. - */ - private String id; - - /** - * The code system. - */ - private String codeName; - - /** - * The code system name. - */ - private String codeSystemName; - - /** - * The code system version. - */ - private String codeSystemVersion; - - /** - * The code system version uri. - */ - private String codeSystemVersionUri; - - private String codeSystemOID; - - /** - * The OID. - */ - private String codeOID; - - /** - * The Display Name. - */ - private String displayName; - - - private String codeIdentifier; - - private boolean isUsed; - - private boolean readOnly; - - private String suffix; - - private boolean isCodeSystemVersionIncluded; - - - private String isValidatedWithVsac = "VALID"; - - - public boolean isIsCodeSystemVersionIncluded() { - return isCodeSystemVersionIncluded; - } - - - public void setIsCodeSystemVersionIncluded(boolean isCodeSystemVersionIncluded) { - this.isCodeSystemVersionIncluded = isCodeSystemVersionIncluded; - } - - /** - * Gets the code system name. - * - * @return the code system name - */ - public String getCodeSystemName() { - return codeSystemName; - } - - /** - * Sets the code system name. - * - * @param codeSystemName the new code system name - */ - public void setCodeSystemName(String codeSystemName) { - this.codeSystemName = codeSystemName; - } - - /** - * Gets the code system version. - * - * @return the code system version - */ - public String getCodeSystemVersion() { - return codeSystemVersion; - } - - /** - * Sets the code system version. - * - * @param codeSystemVersion the new code system version - */ - public void setCodeSystemVersion(String codeSystemVersion) { - this.codeSystemVersion = codeSystemVersion; - } - - public String getCodeOID() { - return codeOID; - } - - public void setCodeOID(String codeOID) { - this.codeOID = codeOID; - } - - /** - * @return the displayName - */ - public String getDisplayName() { - return displayName; - } - - /** - * @param displayName the displayName to set - */ - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public boolean isUsed() { - return isUsed; - } - - public void setUsed(boolean isUsed) { - this.isUsed = isUsed; - } - - public String getCodeIdentifier() { - return codeIdentifier; - } - - public void setCodeIdentifier(String codeIdentifier) { - this.codeIdentifier = codeIdentifier; - } - - public String getCodeSystemOID() { - return codeSystemOID; - } - - public void setCodeSystemOID(String codeSystemOID) { - this.codeSystemOID = codeSystemOID; - } - - public boolean isReadOnly() { - return readOnly; - } - - public void setReadOnly(boolean readOnly) { - this.readOnly = readOnly; - } - - public String getSuffix() { - return suffix; - } + /** The id. */ + private String id; - public void setSuffix(String suffix) { - this.suffix = suffix; - } + /** The code system. */ + private String codeName; - @Override - public boolean equals(final Object other) { - if (!(other instanceof CQLCode)) { - return false; - } - CQLCode castOther = (CQLCode) other; - return Objects.equals(codeName, castOther.codeName) && Objects.equals(codeSystemName, castOther.codeSystemName) - && Objects.equals(codeSystemVersion, castOther.codeSystemVersion) && Objects.equals(codeSystemOID, castOther.codeSystemOID) - && Objects.equals(codeOID, castOther.codeOID) && Objects.equals(codeIdentifier, castOther.codeIdentifier); - } + /** The code system name. */ + private String codeSystemName; - @Override - public int hashCode() { - return Objects.hash(codeName, codeSystemName, codeSystemVersion, codeSystemOID, codeOID, codeIdentifier); - } - - public String getCodeName() { - return this.codeName; - } - - public void setCodeName(String name) { - this.codeName = name; - } + /** The code system version. */ + private String codeSystemVersion; + /** The code system version uri. */ + private String codeSystemVersionUri; - @Override - public String getId() { - return id; - } + private String codeSystemOID; - @Override - public void setId(String id) { - this.id = id; - } + /** The OID. */ + private String codeOID; - @Override - public String getName() { - return getCodeName(); - } + /** The Display Name. */ + private String displayName; - @Override - public void setName(String name) { - setCodeName(name); - } + private String codeIdentifier; + private boolean isUsed; - @Override - public String getLogic() { - // TODO Auto-generated method stub - return null; - } + private boolean readOnly; + private String suffix; - @Override - public void setLogic(String logic) { - // TODO Auto-generated method stub + private boolean isCodeSystemVersionIncluded; - } + private String isValidatedWithVsac = "VALID"; - public String getCodeSystemVersionUri() { - return codeSystemVersionUri; - } + public boolean isIsCodeSystemVersionIncluded() { + return isCodeSystemVersionIncluded; + } - public void setCodeSystemVersionUri(String codeSystemVersionUri) { - this.codeSystemVersionUri = codeSystemVersionUri; - } + public void setIsCodeSystemVersionIncluded(boolean isCodeSystemVersionIncluded) { + this.isCodeSystemVersionIncluded = isCodeSystemVersionIncluded; + } - @Override - public String toString() { - return "CQLCode{" + - "id='" + id + '\'' + - ", codeName='" + codeName + '\'' + - ", codeSystemName='" + codeSystemName + '\'' + - ", codeSystemVersion='" + codeSystemVersion + '\'' + - ", codeSystemVersionUri='" + codeSystemVersionUri + '\'' + - ", codeSystemOID='" + codeSystemOID + '\'' + - ", codeOID='" + codeOID + '\'' + - ", displayName='" + displayName + '\'' + - ", codeIdentifier='" + codeIdentifier + '\'' + - ", isUsed=" + isUsed + - ", readOnly=" + readOnly + - ", suffix='" + suffix + '\'' + - ", isCodeSystemVersionIncluded=" + isCodeSystemVersionIncluded + - ", isValidatedWithVsac=" + isValidatedWithVsac + - '}'; - } + /** + * Gets the code system name. + * + * @return the code system name + */ + public String getCodeSystemName() { + return codeSystemName; + } + + /** + * Sets the code system name. + * + * @param codeSystemName the new code system name + */ + public void setCodeSystemName(String codeSystemName) { + this.codeSystemName = codeSystemName; + } + + /** + * Gets the code system version. + * + * @return the code system version + */ + public String getCodeSystemVersion() { + return codeSystemVersion; + } + + /** + * Sets the code system version. + * + * @param codeSystemVersion the new code system version + */ + public void setCodeSystemVersion(String codeSystemVersion) { + this.codeSystemVersion = codeSystemVersion; + } + + public String getCodeOID() { + return codeOID; + } + + public void setCodeOID(String codeOID) { + this.codeOID = codeOID; + } + + /** @return the displayName */ + public String getDisplayName() { + return displayName; + } + + /** @param displayName the displayName to set */ + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public boolean isUsed() { + return isUsed; + } + + public void setUsed(boolean isUsed) { + this.isUsed = isUsed; + } + + public String getCodeIdentifier() { + return codeIdentifier; + } + + public void setCodeIdentifier(String codeIdentifier) { + this.codeIdentifier = codeIdentifier; + } + + public String getCodeSystemOID() { + return codeSystemOID; + } + + public void setCodeSystemOID(String codeSystemOID) { + this.codeSystemOID = codeSystemOID; + } + + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + public String getSuffix() { + return suffix; + } + + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + @Override + public boolean equals(final Object other) { + if (!(other instanceof CQLCode)) { + return false; + } + CQLCode castOther = (CQLCode) other; + return Objects.equals(codeName, castOther.codeName) + && Objects.equals(codeSystemName, castOther.codeSystemName) + && Objects.equals(codeSystemVersion, castOther.codeSystemVersion) + && Objects.equals(codeSystemOID, castOther.codeSystemOID) + && Objects.equals(codeOID, castOther.codeOID) + && Objects.equals(codeIdentifier, castOther.codeIdentifier); + } + + @Override + public int hashCode() { + return Objects.hash( + codeName, codeSystemName, codeSystemVersion, codeSystemOID, codeOID, codeIdentifier); + } + + public String getCodeName() { + return this.codeName; + } + + public void setCodeName(String name) { + this.codeName = name; + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + @Override + public String getName() { + return getCodeName(); + } + + @Override + public void setName(String name) { + setCodeName(name); + } + + @Override + public String getLogic() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setLogic(String logic) { + // TODO Auto-generated method stub + + } + + public String getCodeSystemVersionUri() { + return codeSystemVersionUri; + } + + public void setCodeSystemVersionUri(String codeSystemVersionUri) { + this.codeSystemVersionUri = codeSystemVersionUri; + } + + @Override + public String toString() { + return "CQLCode{" + + "id='" + + id + + '\'' + + ", codeName='" + + codeName + + '\'' + + ", codeSystemName='" + + codeSystemName + + '\'' + + ", codeSystemVersion='" + + codeSystemVersion + + '\'' + + ", codeSystemVersionUri='" + + codeSystemVersionUri + + '\'' + + ", codeSystemOID='" + + codeSystemOID + + '\'' + + ", codeOID='" + + codeOID + + '\'' + + ", displayName='" + + displayName + + '\'' + + ", codeIdentifier='" + + codeIdentifier + + '\'' + + ", isUsed=" + + isUsed + + ", readOnly=" + + readOnly + + ", suffix='" + + suffix + + '\'' + + ", isCodeSystemVersionIncluded=" + + isCodeSystemVersionIncluded + + ", isValidatedWithVsac=" + + isValidatedWithVsac + + '}'; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCodeSystem.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCodeSystem.java index 8785c32e..71ab5ccb 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCodeSystem.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLCodeSystem.java @@ -1,119 +1,116 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - - // TODO: Auto-generated Javadoc -/** - * The Class CQLCodeSystem. - */ -public class CQLCodeSystem { - - /** The id. */ - private String id; - - /** The code system. */ - private String codeSystem; - - /** The code system name. */ - private String codeSystemName; - - /** The code system version. */ - private String codeSystemVersion; - - /** The value set OID. */ - private String valueSetOID; - - /** - * stores off the version uri. example: - * codesystem "SNOMEDCT:2017-09": 'http://snomed.info/sct/731000124108' version 'http://snomed.info/sct/731000124108/version/201709' - */ - private String versionUri; - - /** - * Gets the id. - * - * @return the id - */ - public String getId() { - return id; - } - - /** - * Sets the id. - * - * @param id the new id - */ - public void setId(String id) { - this.id = id; - } - - /** - * Gets the code system. - * - * @return the code system - */ - public String getCodeSystem() { - return codeSystem; - } - - /** - * Sets the code system. - * - * @param codeSystem the new code system - */ - public void setCodeSystem(String codeSystem) { - this.codeSystem = codeSystem; - } - - /** - * Gets the code system name. - * - * @return the code system name - */ - public String getCodeSystemName() { - return codeSystemName; - } - - /** - * Sets the code system name. - * - * @param codeSystemName the new code system name - */ - public void setCodeSystemName(String codeSystemName) { - this.codeSystemName = codeSystemName; - } - - /** - * Gets the code system version. - * - * @return the code system version - */ - public String getCodeSystemVersion() { - return codeSystemVersion; - } - - /** - * Sets the code system version. - * - * @param codeSystemVersion the new code system version - */ - public void setCodeSystemVersion(String codeSystemVersion) { - this.codeSystemVersion = codeSystemVersion; - } - - public String getVersionUri() { - return versionUri; - } - - public void setVersionUri(String versionUri) { - this.versionUri = versionUri; - } - - public String getValueSetOID() { - return valueSetOID; - } - - public void setValueSetOID(String valueSetOID) { - this.valueSetOID = valueSetOID; - } +/** The Class CQLCodeSystem. */ +public class CQLCodeSystem { + + /** The id. */ + private String id; + + /** The code system. */ + private String codeSystem; + + /** The code system name. */ + private String codeSystemName; + + /** The code system version. */ + private String codeSystemVersion; + + /** The value set OID. */ + private String valueSetOID; + + /** + * stores off the version uri. example: codesystem "SNOMEDCT:2017-09": + * 'http://snomed.info/sct/731000124108' version + * 'http://snomed.info/sct/731000124108/version/201709' + */ + private String versionUri; + + /** + * Gets the id. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the id. + * + * @param id the new id + */ + public void setId(String id) { + this.id = id; + } + + /** + * Gets the code system. + * + * @return the code system + */ + public String getCodeSystem() { + return codeSystem; + } + + /** + * Sets the code system. + * + * @param codeSystem the new code system + */ + public void setCodeSystem(String codeSystem) { + this.codeSystem = codeSystem; + } + + /** + * Gets the code system name. + * + * @return the code system name + */ + public String getCodeSystemName() { + return codeSystemName; + } + + /** + * Sets the code system name. + * + * @param codeSystemName the new code system name + */ + public void setCodeSystemName(String codeSystemName) { + this.codeSystemName = codeSystemName; + } + + /** + * Gets the code system version. + * + * @return the code system version + */ + public String getCodeSystemVersion() { + return codeSystemVersion; + } + + /** + * Sets the code system version. + * + * @param codeSystemVersion the new code system version + */ + public void setCodeSystemVersion(String codeSystemVersion) { + this.codeSystemVersion = codeSystemVersion; + } + + public String getVersionUri() { + return versionUri; + } + + public void setVersionUri(String versionUri) { + this.versionUri = versionUri; + } + + public String getValueSetOID() { + return valueSetOID; + } + + public void setValueSetOID(String valueSetOID) { + this.valueSetOID = valueSetOID; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLDefinition.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLDefinition.java index 8ccc472a..4ffb82ef 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLDefinition.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLDefinition.java @@ -10,18 +10,15 @@ public class CQLDefinition implements CQLExpression { private String commentString = ""; private String returnType; - public static class Comparator implements java.util.Comparator { /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override - public int compare(CQLDefinition o1, - CQLDefinition o2) { + public int compare(CQLDefinition o1, CQLDefinition o2) { return o1.getName().compareTo(o2.getName()); } - } @Override @@ -54,7 +51,6 @@ public void setLogic(String logic) { setDefinitionLogic(logic); } - public String getDefinitionName() { return definitionName.trim(); } @@ -115,6 +111,4 @@ public String getReturnType() { public void setReturnType(String returnType) { this.returnType = returnType; } - - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLError.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLError.java index ea7a2912..903c3afe 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLError.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLError.java @@ -18,7 +18,6 @@ public class CQLError implements Comparable { private String severity; - public String getSeverity() { return severity; } @@ -99,5 +98,4 @@ public int compareTo(CQLError o) { return 0; } - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLExpression.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLExpression.java index ec170dac..22d0529a 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLExpression.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLExpression.java @@ -13,5 +13,4 @@ public interface CQLExpression { public String getLogic(); public void setLogic(String logic); - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctionArgument.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctionArgument.java index 7b230c5a..d1c2ce9d 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctionArgument.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctionArgument.java @@ -1,7 +1,5 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - - public class CQLFunctionArgument implements Cloneable { private String id; private String argumentName; @@ -14,50 +12,63 @@ public class CQLFunctionArgument implements Cloneable { public boolean isValid() { return isValid; } + public void setValid(boolean isValid) { this.isValid = isValid; } + public String getArgumentName() { return argumentName.trim(); } + public void setArgumentName(String argumentName) { this.argumentName = argumentName.trim(); } + public String getArgumentType() { return argumentType; } + public void setArgumentType(String argumentType) { this.argumentType = argumentType; } + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getAttributeName() { return attributeName; } + public void setAttributeName(String attributeName) { this.attributeName = attributeName; } + public String getOtherType() { return otherType; } + public void setOtherType(String otherType) { this.otherType = otherType; } + public String getQdmDataType() { return qdmDataType; } + public void setQdmDataType(String qdmDataType) { this.qdmDataType = qdmDataType; } public String getReturnType() { - if(this.qdmDataType != null) { + if (this.qdmDataType != null) { return this.qdmDataType; - } else if(this.otherType != null) { + } else if (this.otherType != null) { return this.otherType; } else { return this.argumentType; @@ -74,5 +85,4 @@ public CQLFunctionArgument clone() { argumentClone.setOtherType(this.getOtherType()); return argumentClone; } - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctions.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctions.java index 36f62b7b..60d05a85 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctions.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLFunctions.java @@ -1,144 +1,142 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - import java.util.List; public class CQLFunctions implements CQLExpression { - - private String aliasName; - - /** The id. */ - private String id; - - /** The function name. */ - private String functionName; - - /** The function logic. */ - private String functionLogic; - - /** The argument. */ - private List argument; - - /** The context. */ - private String context = "Patient"; - - private String commentString = ""; - - private String returnType; - - - /** - * Gets the argument list. - * - * @return the argument list - */ - public List getArgumentList() { - return argument; - } - - /** - * Sets the argument list. - * - * @param argumentList the new argument list - */ - public void setArgumentList(List argumentList) { - this.argument = argumentList; - } - - /** - * Gets the id. - * - * @return the id - */ - @Override - public String getId() { - return id; - } - - /** - * Sets the id. - * - * @param id the new id - */ - @Override - public void setId(String id) { - this.id = id; - } - - @Override - public String getName() { - return getFunctionName(); - } - - @Override - public void setName(String name) { - setFunctionName(name); - } - - @Override - public String getLogic() { - return getFunctionLogic(); - } - - @Override - public void setLogic(String logic) { - setFunctionLogic(logic); - } - - public String getFunctionName() { - return functionName.trim(); - } - - public void setFunctionName(String name) { - this.functionName = name.trim(); - } - - public String getFunctionLogic() { - return functionLogic.trim(); - } - - public void setFunctionLogic(String logic) { - this.functionLogic = logic.trim(); - } - /** - * Gets the context. - * - * @return the context - */ - public String getContext() { - return context; - } - - /** - * Sets the context. - * - * @param context the new context - */ - public void setContext(String context) { - this.context = context; - } - - public String getCommentString() { - return commentString; - } - - public void setCommentString(String commentString) { - this.commentString = commentString; - } - - public String getReturnType() { - return returnType; - } - - public void setReturnType(String returnType) { - this.returnType = returnType; - } - - public String getAliasName() { - return aliasName; - } - - public void setAliasName(String aliasName) { - this.aliasName = aliasName; - } + + private String aliasName; + + /** The id. */ + private String id; + + /** The function name. */ + private String functionName; + + /** The function logic. */ + private String functionLogic; + + /** The argument. */ + private List argument; + + /** The context. */ + private String context = "Patient"; + + private String commentString = ""; + + private String returnType; + + /** + * Gets the argument list. + * + * @return the argument list + */ + public List getArgumentList() { + return argument; + } + + /** + * Sets the argument list. + * + * @param argumentList the new argument list + */ + public void setArgumentList(List argumentList) { + this.argument = argumentList; + } + + /** + * Gets the id. + * + * @return the id + */ + @Override + public String getId() { + return id; + } + + /** + * Sets the id. + * + * @param id the new id + */ + @Override + public void setId(String id) { + this.id = id; + } + + @Override + public String getName() { + return getFunctionName(); + } + + @Override + public void setName(String name) { + setFunctionName(name); + } + + @Override + public String getLogic() { + return getFunctionLogic(); + } + + @Override + public void setLogic(String logic) { + setFunctionLogic(logic); + } + + public String getFunctionName() { + return functionName.trim(); + } + + public void setFunctionName(String name) { + this.functionName = name.trim(); + } + + public String getFunctionLogic() { + return functionLogic.trim(); + } + + public void setFunctionLogic(String logic) { + this.functionLogic = logic.trim(); + } + /** + * Gets the context. + * + * @return the context + */ + public String getContext() { + return context; + } + + /** + * Sets the context. + * + * @param context the new context + */ + public void setContext(String context) { + this.context = context; + } + + public String getCommentString() { + return commentString; + } + + public void setCommentString(String commentString) { + this.commentString = commentString; + } + + public String getReturnType() { + return returnType; + } + + public void setReturnType(String returnType) { + this.returnType = returnType; + } + + public String getAliasName() { + return aliasName; + } + + public void setAliasName(String aliasName) { + this.aliasName = aliasName; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLGraph.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLGraph.java index e3cfd15d..525e7245 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLGraph.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLGraph.java @@ -11,75 +11,76 @@ public class CQLGraph { - private final Map> graph = new HashMap<>(); + private final Map> graph = new HashMap<>(); - public void addNode(String identifier) { - Set set = new HashSet<>(); - this.graph.put(identifier, set); + public void addNode(String identifier) { + Set set = new HashSet<>(); + this.graph.put(identifier, set); + } + + public void addEdge(String parent, String child) { + // check to see if the nod exists yet. + if (this.graph.get(parent) == null) { + addNode(parent); } - public void addEdge(String parent, String child) { - // check to see if the nod exists yet. - if (this.graph.get(parent) == null) { - addNode(parent); - } + if (this.graph.get(child) == null) { + addNode(child); + } - if (this.graph.get(child) == null) { - addNode(child); - } + // create an edge between the parent to the child. + // parent ---> child + this.graph.get(parent).add(child); + } + + public boolean isPath(String source, String destination) { - // create an edge between the parent to the child. - // parent ---> child - this.graph.get(parent).add(child); + // if a node is itself, return false because an expression cannot call itself + if (source.equals(destination)) { + return false; } - public boolean isPath(String source, String destination) { + // if the String is in this set, it has been visited + Set visited = new HashSet<>(); - // if a node is itself, return false because an expression cannot call itself - if (source.equals(destination)) { - return false; - } + Queue queue = new ArrayDeque<>(); + visited.add(source); // mark source as visited. + queue.add(source); - // if the String is in this set, it has been visited - Set visited = new HashSet<>(); - - Queue queue = new ArrayDeque<>(); - visited.add(source); // mark source as visited. - queue.add(source); - - while (!queue.isEmpty()) { - String currentNode = queue.remove(); - List adjacentVerticies = new ArrayList<>(this.getAdjecencyList().get(currentNode)); - - for (String adjacentNode : adjacentVerticies) { - // we've found the destination node that we were looking for, so return true. - if (adjacentNode.equals(destination)) { - return true; - } - - // if it's not the destination node and the node hasn't been visited yet, add it to the queue to be visited. - if (!visited.contains(adjacentNode)) { - visited.add(adjacentNode); - queue.add(adjacentNode); - } - } + while (!queue.isEmpty()) { + String currentNode = queue.remove(); + List adjacentVerticies = new ArrayList<>(this.getAdjecencyList().get(currentNode)); + + for (String adjacentNode : adjacentVerticies) { + // we've found the destination node that we were looking for, so return true. + if (adjacentNode.equals(destination)) { + return true; } - // if we never find the destination node... - return false; + // if it's not the destination node and the node hasn't been visited yet, add it to the + // queue to be visited. + if (!visited.contains(adjacentNode)) { + visited.add(adjacentNode); + queue.add(adjacentNode); + } + } } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - for (String node : graph.keySet()) { - builder.append(node + " ---> " + graph.get(node) + "\n"); - } + // if we never find the destination node... + return false; + } - return builder.toString(); + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + for (String node : graph.keySet()) { + builder.append(node + " ---> " + graph.get(node) + "\n"); } - public Map> getAdjecencyList() { - return graph; - } + return builder.toString(); + } + + public Map> getAdjecencyList() { + return graph; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIdentifierObject.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIdentifierObject.java index 34669356..a3bac2b6 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIdentifierObject.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIdentifierObject.java @@ -17,9 +17,7 @@ public CQLIdentifierObject(String aliasName, String identifier) { this.identifier = identifier; } - public CQLIdentifierObject() { - - } + public CQLIdentifierObject() {} public String getAliasName() { return aliasName; @@ -29,7 +27,6 @@ public void setAliasName(String aliasName) { this.aliasName = aliasName; } - public String getIdentifier() { return identifier; } @@ -39,7 +36,7 @@ public void setIdentifier(String identifier) { } public String getDisplay() { - if(aliasName != null && !aliasName.isEmpty()) { + if (aliasName != null && !aliasName.isEmpty()) { return aliasName + "." + identifier; } else { return identifier; @@ -48,7 +45,7 @@ public String getDisplay() { @Override public String toString() { - if(aliasName != null && !aliasName.isEmpty()) { + if (aliasName != null && !aliasName.isEmpty()) { return aliasName + "." + "\"" + identifier + "\""; } else { return "\"" + identifier + "\""; @@ -70,5 +67,4 @@ public String getReturnType() { public void setReturnType(String returnType) { this.returnType = returnType; } - } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIncludeLibrary.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIncludeLibrary.java index f3f01aea..f896cb97 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIncludeLibrary.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLIncludeLibrary.java @@ -1,173 +1,181 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - import java.util.Objects; -/** - * The Class CQLIncludeLibrary. - */ +/** The Class CQLIncludeLibrary. */ public class CQLIncludeLibrary { - private String id; + private String id; - private String aliasName; + private String aliasName; - private String cqlLibraryId; + private String cqlLibraryId; - private String version; + private String version; - private String cqlLibraryName; + private String cqlLibraryName; - private String qdmVersion; + private String qdmVersion; - private String setId; + private String setId; - private String isComponent; + private String isComponent; - private String measureId; + private String measureId; - private String libraryModelType = "QDM"; + private String libraryModelType = "QDM"; - public String getSetId() { - return setId; - } + public String getSetId() { + return setId; + } - public void setSetId(String setId) { - this.setId = setId; - } + public void setSetId(String setId) { + this.setId = setId; + } - public CQLIncludeLibrary(CQLLibraryDataSetObject dto) { - this.cqlLibraryId = dto.getId(); - this.version = dto.getVersion().replace("v", "") + "." + dto.getRevisionNumber(); - this.cqlLibraryName = dto.getCqlName(); - this.qdmVersion = dto.getQdmVersion(); - this.setId = dto.getCqlSetId(); - this.libraryModelType = dto.getLibraryModelType(); - } + public CQLIncludeLibrary(CQLLibraryDataSetObject dto) { + this.cqlLibraryId = dto.getId(); + this.version = dto.getVersion().replace("v", "") + "." + dto.getRevisionNumber(); + this.cqlLibraryName = dto.getCqlName(); + this.qdmVersion = dto.getQdmVersion(); + this.setId = dto.getCqlSetId(); + this.libraryModelType = dto.getLibraryModelType(); + } - public CQLIncludeLibrary(CQLIncludeLibrary includeLibrary) { - this.aliasName = includeLibrary.getAliasName(); - this.id = includeLibrary.getId(); - this.cqlLibraryId = includeLibrary.getCqlLibraryId(); - this.version = includeLibrary.getVersion(); - this.cqlLibraryName = includeLibrary.getCqlLibraryName(); - this.qdmVersion = includeLibrary.getQdmVersion(); - this.setId = includeLibrary.getSetId(); - this.libraryModelType = includeLibrary.getLibraryModelType(); - } + public CQLIncludeLibrary(CQLIncludeLibrary includeLibrary) { + this.aliasName = includeLibrary.getAliasName(); + this.id = includeLibrary.getId(); + this.cqlLibraryId = includeLibrary.getCqlLibraryId(); + this.version = includeLibrary.getVersion(); + this.cqlLibraryName = includeLibrary.getCqlLibraryName(); + this.qdmVersion = includeLibrary.getQdmVersion(); + this.setId = includeLibrary.getSetId(); + this.libraryModelType = includeLibrary.getLibraryModelType(); + } - public CQLIncludeLibrary() { + public CQLIncludeLibrary() {} - } + public String getId() { + return id; + } - public String getId() { - return id; - } + public void setId(String id) { + this.id = id; + } - public void setId(String id) { - this.id = id; - } + public String getAliasName() { + return aliasName; + } - public String getAliasName() { - return aliasName; - } + public void setAliasName(String aliasName) { + this.aliasName = aliasName; + } - public void setAliasName(String aliasName) { - this.aliasName = aliasName; - } + public String getCqlLibraryId() { + return cqlLibraryId; + } - public String getCqlLibraryId() { - return cqlLibraryId; - } + public void setCqlLibraryId(String cqlLibraryId) { + this.cqlLibraryId = cqlLibraryId; + } - public void setCqlLibraryId(String cqlLibraryId) { - this.cqlLibraryId = cqlLibraryId; - } + public String getVersion() { + return version; + } - public String getVersion() { - return version; - } + public void setVersion(String version) { + this.version = version; + } - public void setVersion(String version) { - this.version = version; - } + public String getCqlLibraryName() { + return cqlLibraryName; + } - public String getCqlLibraryName() { - return cqlLibraryName; - } + public void setCqlLibraryName(String cqlLibraryName) { + this.cqlLibraryName = cqlLibraryName; + } - public void setCqlLibraryName(String cqlLibraryName) { - this.cqlLibraryName = cqlLibraryName; - } + public String getQdmVersion() { + return qdmVersion; + } - public String getQdmVersion() { - return qdmVersion; - } + public void setQdmVersion(String qdmVersion) { + this.qdmVersion = qdmVersion; + } - public void setQdmVersion(String qdmVersion) { - this.qdmVersion = qdmVersion; - } + public String getLibraryModelType() { + return libraryModelType; + } - public String getLibraryModelType() { - return libraryModelType; - } + public void setLibraryModelType(String libraryModelType) { + this.libraryModelType = libraryModelType; + } - public void setLibraryModelType(String libraryModelType) { - this.libraryModelType = libraryModelType; - } + @Override + public boolean equals(Object arg0) { + CQLIncludeLibrary cqlIncludeLibrary = (CQLIncludeLibrary) arg0; - @Override - public boolean equals(Object arg0) { - CQLIncludeLibrary cqlIncludeLibrary = (CQLIncludeLibrary) arg0; - - if (cqlIncludeLibrary == null) { - return false; - } - - // (cqlIncludeLibrary.libraryModelType == libraryModelType || libraryModelType != null && libraryModelType.equals(cqlIncludeLibrary.libraryModelType)) - if (Objects.equals(cqlIncludeLibrary.cqlLibraryId, cqlLibraryId) && - Objects.equals(cqlIncludeLibrary.aliasName, aliasName) && - Objects.equals(cqlIncludeLibrary.cqlLibraryName, cqlLibraryName) && - Objects.equals(cqlIncludeLibrary.version, version) && - Objects.equals(cqlIncludeLibrary.libraryModelType, libraryModelType)) { - return true; - } - return false; - } + if (cqlIncludeLibrary == null) { + return false; + } + + // (cqlIncludeLibrary.libraryModelType == libraryModelType || libraryModelType != null && + // libraryModelType.equals(cqlIncludeLibrary.libraryModelType)) + if (Objects.equals(cqlIncludeLibrary.cqlLibraryId, cqlLibraryId) + && Objects.equals(cqlIncludeLibrary.aliasName, aliasName) + && Objects.equals(cqlIncludeLibrary.cqlLibraryName, cqlLibraryName) + && Objects.equals(cqlIncludeLibrary.version, version) + && Objects.equals(cqlIncludeLibrary.libraryModelType, libraryModelType)) { + return true; + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash( + getAliasName(), + getCqlLibraryId(), + getVersion(), + getCqlLibraryName(), + getLibraryModelType()); + } + + public static class Comparator implements java.util.Comparator { @Override - public int hashCode() { - return Objects.hash(getAliasName(), getCqlLibraryId(), getVersion(), getCqlLibraryName(), getLibraryModelType()); - } - - public static class Comparator implements java.util.Comparator { - - @Override - public int compare(CQLIncludeLibrary o1, CQLIncludeLibrary o2) { - return o1.getAliasName().compareTo(o2.getAliasName()); - } - - } - - public String toString() { - return this.id + "|" + this.cqlLibraryId + "|" + this.cqlLibraryName + "|" + this.aliasName + "|" - + this.version + "|" + this.libraryModelType; - } - - public String getIsComponent() { - return isComponent; - } - - public void setIsComponent(String isComponent) { - this.isComponent = isComponent; - } - - public String getMeasureId() { - return measureId; - } - - public void setMeasureId(String measureId) { - this.measureId = measureId; - } - + public int compare(CQLIncludeLibrary o1, CQLIncludeLibrary o2) { + return o1.getAliasName().compareTo(o2.getAliasName()); + } + } + + public String toString() { + return this.id + + "|" + + this.cqlLibraryId + + "|" + + this.cqlLibraryName + + "|" + + this.aliasName + + "|" + + this.version + + "|" + + this.libraryModelType; + } + + public String getIsComponent() { + return isComponent; + } + + public void setIsComponent(String isComponent) { + this.isComponent = isComponent; + } + + public String getMeasureId() { + return measureId; + } + + public void setMeasureId(String measureId) { + this.measureId = measureId; + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLLibraryDataSetObject.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLLibraryDataSetObject.java index e82d3d42..c645cf59 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLLibraryDataSetObject.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLLibraryDataSetObject.java @@ -1,6 +1,5 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - import gov.cms.mat.cql_elm_translation.utils.cql.ModelTypeHelper; import java.sql.Timestamp; diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLModel.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLModel.java index a7a4e454..71b631e7 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLModel.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLModel.java @@ -21,24 +21,15 @@ public class CQLModel { private String usingModel; private String context; - @Builder.Default - private List valueSetList = new ArrayList<>(); - @Builder.Default - private List allValueSetAndCodeList = new ArrayList<>(); - @Builder.Default - private List cqlParameters = new ArrayList<>(); - @Builder.Default - private List cqlDefinitions = new ArrayList<>(); - @Builder.Default - private List cqlFunctions = new ArrayList<>(); - @Builder.Default - private List codeSystemList = new ArrayList<>(); - @Builder.Default - private List codeList = new ArrayList<>(); - @Builder.Default - private List cqlIncludeLibraries = new ArrayList<>(); - @Builder.Default - private Map includedLibraries = new HashMap<>(); + @Builder.Default private List valueSetList = new ArrayList<>(); + @Builder.Default private List allValueSetAndCodeList = new ArrayList<>(); + @Builder.Default private List cqlParameters = new ArrayList<>(); + @Builder.Default private List cqlDefinitions = new ArrayList<>(); + @Builder.Default private List cqlFunctions = new ArrayList<>(); + @Builder.Default private List codeSystemList = new ArrayList<>(); + @Builder.Default private List codeList = new ArrayList<>(); + @Builder.Default private List cqlIncludeLibraries = new ArrayList<>(); + @Builder.Default private Map includedLibraries = new HashMap<>(); private int lines; @@ -187,7 +178,8 @@ public List getCQLIdentifierDefinitions() { for (CQLIncludeLibrary lib : includedLibraries.keySet()) { CQLModel model = includedLibraries.get(lib); for (CQLDefinition def : model.getDefinitionList()) { - includedDefCQLIdentifierObject.add(new CQLIdentifierObject(lib.getAliasName(), def.getName())); + includedDefCQLIdentifierObject.add( + new CQLIdentifierObject(lib.getAliasName(), def.getName())); } } return includedDefCQLIdentifierObject; @@ -196,10 +188,11 @@ public List getCQLIdentifierDefinitions() { public List getIncludedFunc() { List includedFunctions = new ArrayList<>(); - includedLibraries.forEach((k, v) -> { - v.getCqlFunctions().forEach(f -> f.setAliasName(k.getAliasName())); - includedFunctions.addAll(v.getCqlFunctions()); - }); + includedLibraries.forEach( + (k, v) -> { + v.getCqlFunctions().forEach(f -> f.setAliasName(k.getAliasName())); + includedFunctions.addAll(v.getCqlFunctions()); + }); return includedFunctions; } @@ -209,7 +202,8 @@ public List getCQLIdentifierFunctions() { for (CQLIncludeLibrary lib : includedLibraries.keySet()) { CQLModel model = includedLibraries.get(lib); for (CQLFunctions fun : model.getCqlFunctions()) { - includedFuncCQLIdentifierObject.add(new CQLIdentifierObject(lib.getAliasName(), fun.getName())); + includedFuncCQLIdentifierObject.add( + new CQLIdentifierObject(lib.getAliasName(), fun.getName())); } } return includedFuncCQLIdentifierObject; @@ -228,7 +222,8 @@ public List getCQLIdentifierValueSet() { for (CQLIncludeLibrary lib : includedLibraries.keySet()) { CQLModel model = includedLibraries.get(lib); for (CQLQualityDataSetDTO value : model.getValueSetList()) { - includedValueSetCQLIdentifierObject.add(new CQLIdentifierObject(lib.getAliasName(), value.getName())); + includedValueSetCQLIdentifierObject.add( + new CQLIdentifierObject(lib.getAliasName(), value.getName())); } } return includedValueSetCQLIdentifierObject; @@ -247,13 +242,13 @@ public List getCQLIdentifierParam() { for (CQLIncludeLibrary lib : includedLibraries.keySet()) { CQLModel model = includedLibraries.get(lib); for (CQLParameter param : model.getCqlParameters()) { - includedParamCQLIdentifierObject.add(new CQLIdentifierObject(lib.getAliasName(), param.getName())); + includedParamCQLIdentifierObject.add( + new CQLIdentifierObject(lib.getAliasName(), param.getName())); } } return includedParamCQLIdentifierObject; } - public List getIncludedCode() { List includedCodeNames = new ArrayList<>(); for (CQLModel value : includedLibraries.values()) { @@ -267,7 +262,8 @@ public List getCQLIdentifierCode() { for (CQLIncludeLibrary lib : includedLibraries.keySet()) { CQLModel model = includedLibraries.get(lib); for (CQLCode code : model.getCodeList()) { - includedCodeCQLIdentifierObject.add(new CQLIdentifierObject(lib.getAliasName(), code.getDisplayName())); + includedCodeCQLIdentifierObject.add( + new CQLIdentifierObject(lib.getAliasName(), code.getDisplayName())); } } return includedCodeCQLIdentifierObject; @@ -276,7 +272,8 @@ public List getCQLIdentifierCode() { /** * Gets a valueset by name from the parent or any children * - * @param formattedCodeName the name in the format libraryname-x.x.xxx|alias|code identifier if from child, otherwise just code identifer + * @param formattedCodeName the name in the format libraryname-x.x.xxx|alias|code identifier if + * from child, otherwise just code identifer * @return the code found */ public CQLCode getCodeByName(String formattedCodeName) { @@ -291,13 +288,21 @@ public CQLCode getCodeByName(String formattedCodeName) { // if the library name version is null, then the code is in the parent if (libraryNameVersion == null) { for (CQLCode code : codeList) { - if (code.getDisplayName() == null ? code.getCodeName().equals(codeName) : code.getDisplayName().equals(codeName)) { + if (code.getDisplayName() == null + ? code.getCodeName().equals(codeName) + : code.getDisplayName().equals(codeName)) { return code; } } } else { final String nameVersion = libraryNameVersion; - List cqlIncludeLibrary = includedLibraries.keySet().stream().filter(lib -> createNameVersionString(lib.getCqlLibraryName(), lib.getVersion()).equals(nameVersion)).collect(Collectors.toList()); + List cqlIncludeLibrary = + includedLibraries.keySet().stream() + .filter( + lib -> + createNameVersionString(lib.getCqlLibraryName(), lib.getVersion()) + .equals(nameVersion)) + .collect(Collectors.toList()); if (!cqlIncludeLibrary.isEmpty()) { for (CQLCode code : includedLibraries.get(cqlIncludeLibrary.get(0)).getCodeList()) { if (code.getDisplayName().equals(codeName)) { @@ -317,7 +322,8 @@ private String createNameVersionString(String name, String version) { /** * Gets a code by name from the parent or any children * - * @param formattedValuesetName the name in the format libraryname-x.x.xxx|alias|valueset identifier + * @param formattedValuesetName the name in the format libraryname-x.x.xxx|alias|valueset + * identifier * @return the code found */ public CQLQualityDataSetDTO getValuesetByName(String formattedValuesetName) { @@ -338,9 +344,16 @@ public CQLQualityDataSetDTO getValuesetByName(String formattedValuesetName) { } } else { final String nameVersion = libraryNameVersion; - List cqlIncludeLibrary = includedLibraries.keySet().stream().filter(lib -> createNameVersionString(lib.getCqlLibraryName(), lib.getVersion()).equals(nameVersion)).collect(Collectors.toList()); + List cqlIncludeLibrary = + includedLibraries.keySet().stream() + .filter( + lib -> + createNameVersionString(lib.getCqlLibraryName(), lib.getVersion()) + .equals(nameVersion)) + .collect(Collectors.toList()); if (!cqlIncludeLibrary.isEmpty()) { - for (CQLQualityDataSetDTO valueset : includedLibraries.get(cqlIncludeLibrary.get(0)).getValueSetList()) { + for (CQLQualityDataSetDTO valueset : + includedLibraries.get(cqlIncludeLibrary.get(0)).getValueSetList()) { if (valueset.getName().equals(valuesetName)) { return valueset; } @@ -373,4 +386,4 @@ public List getExpressionListFromCqlModel() { public String getFormattedName() { return this.libraryName + "-" + this.versionUsed; } -} \ No newline at end of file +} diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLParameter.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLParameter.java index 2bdf30e6..ebff6761 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLParameter.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLParameter.java @@ -1,82 +1,89 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; +public class CQLParameter implements CQLExpression { + private String parameterName; + private String cqlType; + private String defaultValue; + private String parameterLogic; + private String id; + private boolean readOnly; + private String commentString = ""; + public String getCqlType() { + return cqlType; + } -public class CQLParameter implements CQLExpression{ - private String parameterName; - private String cqlType; - private String defaultValue; - private String parameterLogic; - private String id; - private boolean readOnly; - private String commentString = ""; - - - public String getCqlType() { - return cqlType; - } - public void setCqlType(String cqlType) { - this.cqlType = cqlType; - } - public String getDefaultValue() { - return defaultValue; - } - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - public boolean isReadOnly() { - return readOnly; - } - public void setReadOnly(boolean isReadOnly) { - this.readOnly = isReadOnly; - } - public String getCommentString() { - return commentString; - } - public void setCommentString(String commentString) { - this.commentString = commentString; - } - public String getParameterName() { - return parameterName.trim(); - } - - public void setParameterName(String name) { - this.parameterName = name.trim(); - } - - public String getParameterLogic() { - return parameterLogic.trim(); - } - - public void setParameterLogic(String logic) { - this.parameterLogic = logic.trim(); - } - - @Override - public String getId() { - return id; - } - @Override - public void setId(String id) { - this.id = id; - } - - @Override - public String getName() { - return getParameterName(); - } - @Override - public void setName(String name) { - setParameterName(name); - } - @Override - public String getLogic() { - return getParameterLogic(); - } - @Override - public void setLogic(String logic) { - setParameterLogic(logic); - } - - + public void setCqlType(String cqlType) { + this.cqlType = cqlType; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean isReadOnly) { + this.readOnly = isReadOnly; + } + + public String getCommentString() { + return commentString; + } + + public void setCommentString(String commentString) { + this.commentString = commentString; + } + + public String getParameterName() { + return parameterName.trim(); + } + + public void setParameterName(String name) { + this.parameterName = name.trim(); + } + + public String getParameterLogic() { + return parameterLogic.trim(); + } + + public void setParameterLogic(String logic) { + this.parameterLogic = logic.trim(); + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + @Override + public String getName() { + return getParameterName(); + } + + @Override + public void setName(String name) { + setParameterName(name); + } + + @Override + public String getLogic() { + return getParameterLogic(); + } + + @Override + public void setLogic(String logic) { + setParameterLogic(logic); + } } diff --git a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLQualityDataSetDTO.java b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLQualityDataSetDTO.java index 428483dc..b675f8f3 100644 --- a/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLQualityDataSetDTO.java +++ b/src/main/java/gov/cms/mat/cql_elm_translation/utils/cql/parsing/model/CQLQualityDataSetDTO.java @@ -1,18 +1,15 @@ package gov.cms.mat.cql_elm_translation.utils.cql.parsing.model; - - -/** - * The Class QualityDataSetDTO. - */ +/** The Class QualityDataSetDTO. */ public class CQLQualityDataSetDTO implements CQLExpression { - /** QDM Modified At VSAC. */ private boolean hasModifiedAtVSAC; + private boolean isUsed; /** QDM is not available in VSAC. */ private boolean notFoundInVSAC; + private String codeListName; private String suffix; private String originalCodeListName; @@ -39,7 +36,7 @@ public class CQLQualityDataSetDTO implements CQLExpression { * @see java.lang.Object#equals(java.lang.Object) */ @Override - public boolean equals (Object o) { + public boolean equals(Object o) { CQLQualityDataSetDTO temp = (CQLQualityDataSetDTO) o; if (temp.getId().equals(getId())) { return true; @@ -167,7 +164,6 @@ public int compare(CQLQualityDataSetDTO o1, CQLQualityDataSetDTO o2) { return o1.getUuid().compareTo(o2.getUuid()); } - public boolean isHasModifiedAtVSAC() { return hasModifiedAtVSAC; } @@ -180,7 +176,6 @@ public boolean isNotFoundInVSAC() { return notFoundInVSAC; } - public void setNotFoundInVSAC(boolean notFoundInVSAC) { this.notFoundInVSAC = notFoundInVSAC; } @@ -251,8 +246,7 @@ public String getLogic() { } @Override - public void setLogic(String logic) { - } + public void setLogic(String logic) {} public String getValueSetType() { return valueSetType; @@ -264,32 +258,73 @@ public void setValueSetType(String valueSetType) { @Override public String toString() { - return "CQLQualityDataSetDTO{" + - "isValidatedWithVsac=" + isValidatedWithVsac + - ", hasModifiedAtVSAC=" + hasModifiedAtVSAC + - ", isUsed=" + isUsed + - ", notFoundInVSAC=" + notFoundInVSAC + - ", codeListName='" + codeListName + '\'' + - ", suffix='" + suffix + '\'' + - ", originalCodeListName='" + originalCodeListName + '\'' + - ", codeSystemName='" + codeSystemName + '\'' + - ", dataType='" + dataType + '\'' + - ", id='" + id + '\'' + - ", displayName='" + displayName + '\'' + - ", oid='" + oid + '\'' + - ", codeSystemOID='" + codeSystemOID + '\'' + - ", codeIdentifier='" + codeIdentifier + '\'' + - ", isReadOnly=" + isReadOnly + - ", suppDataElement=" + suppDataElement + - ", taxonomy='" + taxonomy + '\'' + - ", type='" + type + '\'' + - ", uuid='" + uuid + '\'' + - ", version='" + version + '\'' + - ", release='" + release + '\'' + - ", program='" + program + '\'' + - ", dataTypeHasRemoved=" + dataTypeHasRemoved + - ", valueSetType='" + valueSetType + '\'' + - '}'; + return "CQLQualityDataSetDTO{" + + "isValidatedWithVsac=" + + isValidatedWithVsac + + ", hasModifiedAtVSAC=" + + hasModifiedAtVSAC + + ", isUsed=" + + isUsed + + ", notFoundInVSAC=" + + notFoundInVSAC + + ", codeListName='" + + codeListName + + '\'' + + ", suffix='" + + suffix + + '\'' + + ", originalCodeListName='" + + originalCodeListName + + '\'' + + ", codeSystemName='" + + codeSystemName + + '\'' + + ", dataType='" + + dataType + + '\'' + + ", id='" + + id + + '\'' + + ", displayName='" + + displayName + + '\'' + + ", oid='" + + oid + + '\'' + + ", codeSystemOID='" + + codeSystemOID + + '\'' + + ", codeIdentifier='" + + codeIdentifier + + '\'' + + ", isReadOnly=" + + isReadOnly + + ", suppDataElement=" + + suppDataElement + + ", taxonomy='" + + taxonomy + + '\'' + + ", type='" + + type + + '\'' + + ", uuid='" + + uuid + + '\'' + + ", version='" + + version + + '\'' + + ", release='" + + release + + '\'' + + ", program='" + + program + + '\'' + + ", dataTypeHasRemoved=" + + dataTypeHasRemoved + + ", valueSetType='" + + valueSetType + + '\'' + + '}'; } public static class Comparator implements java.util.Comparator { @@ -298,7 +333,5 @@ public static class Comparator implements java.util.Comparator sourceDataCriteria = dataCriteriaService.getSourceDataCriteria(cql, token); + + // source data criteria for value set + assertThat(sourceDataCriteria.size(), is(equalTo(2))); + assertThat(sourceDataCriteria.get(0).getCodeListId(), is(equalTo("2.16.840.1.113883.3.666.5.307"))); + assertThat(sourceDataCriteria.get(0).getQdmTitle(), is(equalTo("Encounter Inpatient"))); + assertThat(sourceDataCriteria.get(0).getType(), is(equalTo("EncounterPerformed"))); + assertThat(sourceDataCriteria.get(0).getDescription(), is(equalTo("Encounter, Performed: Encounter Inpatient"))); + assertFalse(sourceDataCriteria.get(0).isDrc()); + + // source data criteria for direct reference code + assertThat(sourceDataCriteria.size(), is(equalTo(2))); + assertTrue(sourceDataCriteria.get(1).isDrc()); + assertThat(sourceDataCriteria.get(1).getQdmTitle(), is(equalTo("Clinical Examples"))); + assertThat(sourceDataCriteria.get(1).getType(), is(equalTo("EncounterPerformed"))); + assertThat(sourceDataCriteria.get(1).getDescription(), is(equalTo("Encounter, Performed: Clinical Examples"))); + } + + @Test + void testGetSourceDataCriteriaWhenNoSourceCriteriaFound() { + String cql = "library DataCriteriaRetrivalTest version '0.0.000'\n" + + "using QDM version '5.6'\n" + + "valueset \"Encounter Inpatient\": 'urn:oid:2.16.840.1.113883.3.666.5.307'\n" + + "parameter \"Measurement Period\" Interval\n" + + "context Patient\n" + + "define \"Qualifying Encounters\":\n true"; + + RequestData data = requestData.toBuilder().cqlData(cql).build(); + CqlTranslator translator = TranslationResource.getInstance(false) + .buildTranslator(data.getCqlDataInputStream(), data.createMap()); + + Mockito.doNothing().when(cqlConversionService).setUpLibrarySourceProvider(anyString(), anyString()); + when(cqlConversionService.processCqlData(any(RequestData.class))) + .thenReturn(translator); + + List sourceDataCriteria = dataCriteriaService.getSourceDataCriteria(cql, token); + + // source data criteria for value set + assertThat(sourceDataCriteria.size(), is(equalTo(0))); + } +} diff --git a/src/test/resources/qdm_data_criteria_retrieval_test.cql b/src/test/resources/qdm_data_criteria_retrieval_test.cql new file mode 100644 index 00000000..618c8114 --- /dev/null +++ b/src/test/resources/qdm_data_criteria_retrieval_test.cql @@ -0,0 +1,20 @@ +library DataCriteriaRetrivalTest version '0.0.000' + +using QDM version '5.6' + +codesystem "LOINC": 'urn:oid:2.16.840.1.113883.6.1' +codesystem "CPT": 'urn:oid:2.16.840.1.113883.6.12' + +valueset "Encounter Inpatient": 'urn:oid:2.16.840.1.113883.3.666.5.307' + +code "Birth date": '21112-8' from "LOINC" display 'Birth date' +code "Clinical Examples": '1021859' from "CPT" display 'Clinical Examples' + +parameter "Measurement Period" Interval + +context Patient + +define "Qualifying Encounters": + ( ["Encounter, Performed": "Encounter Inpatient"] + union ["Encounter, Performed": "Clinical Examples"] ) Encounter + where Encounter.relevantPeriod ends during "Measurement Period" \ No newline at end of file