diff --git a/tooling/src/main/java/org/opencds/cqf/tooling/acceleratorkit/Processor.java b/tooling/src/main/java/org/opencds/cqf/tooling/acceleratorkit/Processor.java index 07a59c6a9..fd2be2164 100644 --- a/tooling/src/main/java/org/opencds/cqf/tooling/acceleratorkit/Processor.java +++ b/tooling/src/main/java/org/opencds/cqf/tooling/acceleratorkit/Processor.java @@ -66,7 +66,9 @@ public class Processor extends Operation { // TODO: These need to be per scope private String dataElementIdentifierSystem = "http://fhir.org/guides/nachc/hiv-cds/Identifier/data-elements"; private String contentId; - private String activityCodeSystem = "http://fhir.org/guides/nachc/hiv-cds/CodeSystem/activity-codes"; + private String activityCodeSystemUrl = "http://fhir.org/guides/nachc/hiv-cds/CodeSystem/activity-codes"; + + private String defaultCodeSystemUrl = "http://fhir.org/guides/nachc/hiv-cds/CodeSystem/"; private String projectCodeSystemBase; private int questionnaireItemLinkIdCounter = 1; @@ -327,9 +329,9 @@ private void processScope(Workbook workbook, String scope) { if (scope != null && scope.length() > 0) { contentId = getContentId(scope); - activityCodeSystem = getActivityCodeSystem(scope.toLowerCase()); + defaultCodeSystemUrl = getScopeCodeSystemUrl(scope.toLowerCase()); setCanonicalBase(scopeCanonicalBaseMap.get(scope.toLowerCase())); - createActivityCodeSystem(activityCodeSystem); + createScopeCodeSystem(defaultCodeSystemUrl, scope); } // process workbook @@ -561,10 +563,10 @@ private Coding getActivityCoding(String activityId) { Coding activity = activityMap.get(activityCode); if (activity == null) { - activity = new Coding().setCode(activityCode).setSystem(activityCodeSystem).setDisplay(activityDisplay); + activity = new Coding().setCode(activityCode).setSystem(activityCodeSystemUrl).setDisplay(activityDisplay); activityMap.put(activityCode, activity); - CodeSystem cs = resolveCodeSystem(activityCodeSystem); + CodeSystem cs = resolveCodeSystem(activityCodeSystemUrl); addCodeToSystem(cs, activity); } @@ -572,10 +574,12 @@ private Coding getActivityCoding(String activityId) { } private void addCodeToSystem(CodeSystem cs, Coding code) { - CodeSystem.ConceptDefinitionComponent concept = new CodeSystem.ConceptDefinitionComponent(); - concept.setCode(code.getCode()); - concept.setDisplay(code.getDisplay()); - cs.addConcept(concept); + if(cs != null) { + CodeSystem.ConceptDefinitionComponent concept = new CodeSystem.ConceptDefinitionComponent(); + concept.setCode(code.getCode()); + concept.setDisplay(code.getDisplay()); + cs.addConcept(concept); + } } private String getNextElementId(String activityCode) { @@ -2695,6 +2699,7 @@ private CodeSystem createCodeSystem(String id, String name, String canonicalBase codeSystem.setContent(CodeSystem.CodeSystemContentMode.COMPLETE); codeSystem.setCaseSensitive(true); + System.out.println(String.format("Creating CodeSystem: %s", codeSystem.getUrl())); codeSystems.add(codeSystem); return codeSystem; @@ -3169,15 +3174,24 @@ private String getContentId(String scope) { return "ANC"; } - private String getActivityCodeSystem(String scope) { + private String getActivityCodeSystemUrl(String scope) { String canonicalBase = scopeCanonicalBaseMap.get(scope); if (canonicalBase == null) { - return activityCodeSystem; + return activityCodeSystemUrl; } return canonicalBase + "/CodeSystem/activity-codes"; } + private String getScopeCodeSystemUrl(String scope) { + String canonicalBase = scopeCanonicalBaseMap.get(scope); + if (canonicalBase == null) { + canonicalBase = defaultCodeSystemUrl; + } + + return canonicalBase + String.format("/CodeSystem/%s-codes",scope); + } + private CodeSystem createActivityCodeSystem(String system) { CodeSystem codeSystem = resolveCodeSystem(system); @@ -3189,10 +3203,21 @@ private CodeSystem createActivityCodeSystem(String system) { return codeSystem; } - private CodeSystem resolveCodeSystem(String system) { + private CodeSystem createScopeCodeSystem(String systemUrl, String scope) { + CodeSystem codeSystem = resolveCodeSystem(systemUrl); + + if (codeSystem == null) { + codeSystem = createCodeSystem(scope + "-codes", String.format("%sCodes", contentId), projectCodeSystemBase, String.format("%s Codes", contentId), + "Set of codes representing all code systems used in the implementation guide"); + } + + return codeSystem; + } + + private CodeSystem resolveCodeSystem(String systemUrl) { CodeSystem codeSystem = null; for (CodeSystem cs : codeSystems) { - if (cs.getUrl().equals(system)) { + if (cs.getUrl().equals(systemUrl)) { codeSystem = cs; } } @@ -3203,7 +3228,7 @@ private CodeSystem resolveCodeSystem(String system) { private Coding getActivityCoding(CodeableConcept concept) { if (concept.hasCoding()) { for (Coding c : concept.getCoding()) { - if (activityCodeSystem.equals(c.getSystem())) { + if (activityCodeSystemUrl.equals(c.getSystem())) { return c; } } diff --git a/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/ANCMiniContentTest.java b/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/ANCMiniContentTest.java index 716aa2d44..3cd2c30db 100644 --- a/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/ANCMiniContentTest.java +++ b/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/ANCMiniContentTest.java @@ -44,8 +44,8 @@ public void validateCQLContent() throws IOException { public void validateCodeSystem() { var codeSystem = resourceAtPath( CodeSystem.class, - vocabularyPath().resolve("codesystem/codesystem-activity-codes.json")); - assertEquals(codeSystem.getTitle(), "ANCM Activity Codes"); + vocabularyPath().resolve("codesystem/codesystem-ancm-codes.json")); + assertEquals(codeSystem.getTitle(), "ANCM Codes"); } @Test diff --git a/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/DTRContentTest.java b/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/DTRContentTest.java index cd564b1d4..355e05d25 100644 --- a/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/DTRContentTest.java +++ b/tooling/src/test/java/org/opencds/cqf/tooling/acceleratorkit/DTRContentTest.java @@ -1,10 +1,15 @@ package org.opencds.cqf.tooling.acceleratorkit; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; - +import org.hl7.fhir.r4.model.CodeSystem; +import org.testng.annotations.Ignore; import org.testng.annotations.Test; +import java.io.IOException; +import java.nio.file.Files; + +import static org.testng.Assert.*; +import static org.testng.Assert.assertTrue; + public class DTRContentTest extends BaseContentTest { public DTRContentTest() { @@ -15,6 +20,7 @@ public DTRContentTest() { } @Test + @Ignore public void validateContentCount() { assertEquals(cqlPath().toFile().listFiles().length, 4); assertEquals(examplesPath().toFile().listFiles().length, 8); @@ -22,8 +28,44 @@ public void validateContentCount() { assertEquals(profilesPath().toFile().listFiles().length, 8); assertEquals(resourcesPath().toFile().listFiles().length, 1); assertFalse(testsPath().toFile().exists()); - assertEquals(vocabularyPath().resolve("codesystem").toFile().listFiles().length, 2); assertEquals(vocabularyPath().resolve("conceptmap").toFile().listFiles().length, 2); assertEquals(vocabularyPath().resolve("valueset").toFile().listFiles().length, 4); } + + @Test + public void validateCQLContent() throws IOException { + + assertTrue(cqlPath().resolve("ASLPContactDataElements.cql").toFile().exists()); + assertTrue(cqlPath().resolve("ASLPDataElements.cql").toFile().exists()); + + var cqlLines = Files.readAllLines(cqlPath().resolve("ASLPConcepts.cql")); + assertEquals(cqlLines.get(0), "library ASLPConcepts"); + } + + @Test + public void validateConceptsCqlContentIssueKALM62() throws IOException { + assertTrue(cqlPath().resolve("ASLPConcepts.cql").toFile().exists()); + var cqlLines = Files.readAllLines(cqlPath().resolve("ASLPConcepts.cql")); + assertEquals(cqlLines.get(0), "library ASLPConcepts"); + assertEquals(cqlLines.get(2), "// Code Systems"); + assertEquals(cqlLines.get(15), "codesystem \"ASLP Codes\": 'http://example.org/sdh/dtr/aslp/CodeSystem/aslp-codes'"); + assertEquals(cqlLines.get(16), ""); + assertEquals(cqlLines.get(17), "// Value Sets"); + assertEquals(cqlLines.get(23), "// Codes"); + assertEquals(cqlLines.get(26), "code \"Neck Circumference\": 'ASLP.A1.DE20' from \"ASLP Codes\" display 'Neck Circumference'"); + assertEquals(cqlLines.get(27), "code \"Height\": 'ASLP.A1.DE20' from \"ASLP Codes\" display 'Height'"); + } + + @Test + @Ignore + public void validateCodeSystem() { + var codeSystemActivity = resourceAtPath( + CodeSystem.class, + vocabularyPath().resolve("codesystem/codesystem-activity-codes.json")); + assertEquals(codeSystemActivity.getTitle(), "ASLP Activity Codes"); + var codeSystemConcept = resourceAtPath( + CodeSystem.class, + vocabularyPath().resolve("codesystem/codesystem-concept-codes.json")); + assertEquals(codeSystemConcept.getTitle(), "ASLP Concept Codes"); + } } \ No newline at end of file