diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu2.java index 8cc707f8b22..71265e45269 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/TermReadSvcDstu2.java @@ -47,18 +47,18 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl { @Autowired private IValidationSupport myValidationSupport; - private void addAllChildren(String theSystemString, org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent theCode, List theListToPopulate) { + private void addAllChildren(String theSystemString, ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept theCode, List theListToPopulate) { if (isNotBlank(theCode.getCode())) { theListToPopulate.add(new FhirVersionIndependentConcept(theSystemString, theCode.getCode())); } - for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent nextChild : theCode.getConcept()) { + for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept nextChild : theCode.getConcept()) { addAllChildren(theSystemString, nextChild, theListToPopulate); } } - private boolean addTreeIfItContainsCode(String theSystemString, org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent theNext, String theCode, List theListToPopulate) { + private boolean addTreeIfItContainsCode(String theSystemString, ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept theNext, String theCode, List theListToPopulate) { boolean foundCodeInChild = false; - for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent nextChild : theNext.getConcept()) { + for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept nextChild : theNext.getConcept()) { foundCodeInChild |= addTreeIfItContainsCode(theSystemString, nextChild, theCode, theListToPopulate); } @@ -95,9 +95,9 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl { throw new UnsupportedOperationException(); } - private void findCodesAbove(org.hl7.fhir.dstu2.model.ValueSet theSystem, String theSystemString, String theCode, List theListToPopulate) { - List conceptList = theSystem.getCodeSystem().getConcept(); - for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent next : conceptList) { + private void findCodesAbove(ca.uhn.fhir.model.dstu2.resource.ValueSet theSystem, String theSystemString, String theCode, List theListToPopulate) { + List conceptList = theSystem.getCodeSystem().getConcept(); + for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept next : conceptList) { addTreeIfItContainsCode(theSystemString, next, theCode, theListToPopulate); } } @@ -105,20 +105,20 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl { @Override public List findCodesAboveUsingBuiltInSystems(String theSystem, String theCode) { ArrayList retVal = new ArrayList<>(); - org.hl7.fhir.dstu2.model.ValueSet system = (org.hl7.fhir.dstu2.model.ValueSet) myValidationSupport.fetchCodeSystem(theSystem); + ca.uhn.fhir.model.dstu2.resource.ValueSet system = (ca.uhn.fhir.model.dstu2.resource.ValueSet) myValidationSupport.fetchCodeSystem(theSystem); if (system != null) { findCodesAbove(system, theSystem, theCode, retVal); } return retVal; } - private void findCodesBelow(org.hl7.fhir.dstu2.model.ValueSet theSystem, String theSystemString, String theCode, List theListToPopulate) { - List conceptList = theSystem.getCodeSystem().getConcept(); + private void findCodesBelow(ca.uhn.fhir.model.dstu2.resource.ValueSet theSystem, String theSystemString, String theCode, List theListToPopulate) { + List conceptList = theSystem.getCodeSystem().getConcept(); findCodesBelow(theSystemString, theCode, theListToPopulate, conceptList); } - private void findCodesBelow(String theSystemString, String theCode, List theListToPopulate, List conceptList) { - for (org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent next : conceptList) { + private void findCodesBelow(String theSystemString, String theCode, List theListToPopulate, List conceptList) { + for (ca.uhn.fhir.model.dstu2.resource.ValueSet.CodeSystemConcept next : conceptList) { if (theCode.equals(next.getCode())) { addAllChildren(theSystemString, next, theListToPopulate); } else { @@ -130,7 +130,7 @@ public class TermReadSvcDstu2 extends BaseTermReadSvcImpl { @Override public List findCodesBelowUsingBuiltInSystems(String theSystem, String theCode) { ArrayList retVal = new ArrayList<>(); - org.hl7.fhir.dstu2.model.ValueSet system = (org.hl7.fhir.dstu2.model.ValueSet) myValidationSupport.fetchCodeSystem(theSystem); + ca.uhn.fhir.model.dstu2.resource.ValueSet system = (ca.uhn.fhir.model.dstu2.resource.ValueSet) myValidationSupport.fetchCodeSystem(theSystem); if (system != null) { findCodesBelow(system, theSystem, theCode, retVal); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu2Test.java index 35a53442c9d..63fadfb48dd 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplDstu2Test.java @@ -1,13 +1,34 @@ package ca.uhn.fhir.jpa.term; +import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test; +import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.model.dstu2.composite.CodingDt; +import ca.uhn.fhir.model.dstu2.resource.ValueSet; +import ca.uhn.fhir.model.primitive.IdDt; +import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; +import ca.uhn.fhir.util.FhirVersionIndependentConcept; import org.hl7.fhir.instance.model.api.IBaseCoding; import org.hl7.fhir.r4.model.Coding; import org.junit.jupiter.api.Test; +import org.mockito.Answers; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import java.util.List; +import java.util.Set; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; import static org.junit.jupiter.api.Assertions.assertEquals; -public class TerminologySvcImplDstu2Test { +public class TerminologySvcImplDstu2Test extends BaseJpaDstu2Test { + + @Autowired + protected ITermReadSvc myTermReadSvc; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + protected ServletRequestDetails mySrd; @Test public void testToCanonicalCoding() { @@ -17,4 +38,70 @@ public class TerminologySvcImplDstu2Test { assertEquals("dstuCode", convertedCoding.getCode()); assertEquals("dstuSystem", convertedCoding.getSystem()); } + + @Test + public void testFindCodesBelowBuiltInCodeSystem() { + List concepts; + Set codes; + + ValueSet upload = new ValueSet(); + upload.setId(new IdDt("testVs")); + upload.setUrl("http://myVs"); + ValueSet.CodeSystem codeSystem = new ValueSet.CodeSystem().setSystem("http://myCs"); + codeSystem.addConcept(new ValueSet.CodeSystemConcept().setCode("codeA").addConcept(new ValueSet.CodeSystemConcept().setCode("codeAB"))); + upload.setCodeSystem(codeSystem); + myValueSetDao.update(upload, mySrd); + + concepts = myTermReadSvc.findCodesBelow("http://myVs", "codeA"); + codes = toCodes(concepts); + assertThat(codes, containsInAnyOrder("codeA", "codeAB")); + + concepts = myTermReadSvc.findCodesBelow("http://myVs", "codeAB"); + codes = toCodes(concepts); + assertThat(codes, containsInAnyOrder("codeAB")); + + // Unknown code + concepts = myTermReadSvc.findCodesBelow("http://myVs", "FOO"); + codes = toCodes(concepts); + assertThat(codes, empty()); + + // Unknown system + concepts = myTermReadSvc.findCodesBelow("http://myVs2222", "codeA"); + codes = toCodes(concepts); + assertThat(codes, empty()); + } + + @Test + public void testFindCodesAboveBuiltInCodeSystem() { + List concepts; + Set codes; + + ValueSet upload = new ValueSet(); + upload.setId(new IdDt("testVs")); + upload.setUrl("http://myVs"); + ValueSet.CodeSystem codeSystem = new ValueSet.CodeSystem().setSystem("http://myCs"); + codeSystem.addConcept(new ValueSet.CodeSystemConcept().setCode("codeA").addConcept(new ValueSet.CodeSystemConcept().setCode("codeAB"))); + upload.setCodeSystem(codeSystem); + myValueSetDao.update(upload, mySrd); + + concepts = myTermReadSvc.findCodesAbove("http://myVs", "codeA"); + codes = toCodes(concepts); + assertThat(codes, containsInAnyOrder("codeA")); + + concepts = myTermReadSvc.findCodesAbove("http://myVs", "codeAB"); + codes = toCodes(concepts); + assertThat(codes, containsInAnyOrder("codeA", "codeAB")); + + // Unknown code + concepts = myTermReadSvc.findCodesAbove("http://myVs", "FOO"); + codes = toCodes(concepts); + assertThat(codes, empty()); + + // Unknown system + concepts = myTermReadSvc.findCodesBelow("http://myVs2222", "codeA"); + codes = toCodes(concepts); + assertThat(codes, empty()); + } + + } diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java index 96136c55255..a081ec087df 100644 --- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java +++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/common/hapi/validation/support/InMemoryTerminologyServerValidationSupportTest.java @@ -5,11 +5,15 @@ import ca.uhn.fhir.context.support.ConceptValidationOptions; import ca.uhn.fhir.context.support.DefaultProfileValidationSupport; import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.context.support.ValidationSupportContext; +import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.r4.model.CodeType; import org.hl7.fhir.r4.model.ValueSet; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.HashMap; +import java.util.Map; + import static org.junit.jupiter.api.Assertions.*; class InMemoryTerminologyServerValidationSupportTest { @@ -54,5 +58,59 @@ class InMemoryTerminologyServerValidationSupportTest { } + @Test + public void testValidateCodeDstu2() { + FhirContext ctxDstu2 = FhirContext.forDstu2Hl7Org(); + PrePopulatedValidationSupportDstu2 dstu2PrePopulated = new PrePopulatedValidationSupportDstu2(ctxDstu2); + mySvc = new InMemoryTerminologyServerValidationSupport(ctxDstu2); + myDefaultSupport = new DefaultProfileValidationSupport(ctxDstu2); + myChain = new ValidationSupportChain(mySvc, dstu2PrePopulated, myDefaultSupport); + + org.hl7.fhir.dstu2.model.ValueSet vs = new org.hl7.fhir.dstu2.model.ValueSet(); + vs.setUrl("http://vs"); + vs + .getCompose() + .addInclude() + .setSystem("http://cs") + .addConcept(new org.hl7.fhir.dstu2.model.ValueSet.ConceptReferenceComponent(new org.hl7.fhir.dstu2.model.CodeType("code1"))) + .addConcept(new org.hl7.fhir.dstu2.model.ValueSet.ConceptReferenceComponent(new org.hl7.fhir.dstu2.model.CodeType("code2"))); + vs.getCodeSystem() + .addConcept(new org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent(new org.hl7.fhir.dstu2.model.CodeType("code1"))) + .addConcept(new org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent(new org.hl7.fhir.dstu2.model.CodeType("code2"))); + + dstu2PrePopulated.addValueSet(vs, "http://vs", "http://cs"); + + ValidationSupportContext valCtx = new ValidationSupportContext(myChain); + ConceptValidationOptions options = new ConceptValidationOptions(); + + IValidationSupport.CodeValidationResult outcome = mySvc.validateCode(valCtx, options, "http://cs", "code1", null, "http://vs"); + assertTrue(outcome.isOk()); + + } + + private static class PrePopulatedValidationSupportDstu2 extends PrePopulatedValidationSupport { + private final Map myDstu2ValueSets; + + PrePopulatedValidationSupportDstu2(FhirContext theFhirContext) { + super(theFhirContext); + myDstu2ValueSets = new HashMap<>(); + } + + public void addValueSet(org.hl7.fhir.dstu2.model.ValueSet theValueSet, String valueSetUrl, String codeSystemUrl) { + myDstu2ValueSets.put(valueSetUrl, theValueSet); + myDstu2ValueSets.put(codeSystemUrl, theValueSet); + } + + @Override + public IBaseResource fetchValueSet(String theUri) { + return myDstu2ValueSets.get(theUri); + } + + @Override + public IBaseResource fetchCodeSystem(String theSystem) { + return myDstu2ValueSets.get(theSystem); + } + + } }