diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7b06c6ab5..9d6032298 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ ## Validator Changes -* no changes +* Fix issues with multiple terminology servers (should be live soon) ## Other code changes diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index 5383153cc..0b1a5766d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -231,7 +231,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte private Object lock = new Object(); // used as a lock for the data that follows protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be - protected TerminologyClientManager terminologyClientManager = new TerminologyClientManager(new TerminologyClientR5Factory()); + protected TerminologyClientManager terminologyClientManager = new TerminologyClientManager(null); private boolean minimalMemory = false; private Map> allResourcesById = new HashMap>(); @@ -850,6 +850,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte } Set systems = findRelevantSystems(vs); TerminologyClientContext tc = terminologyClientManager.chooseServer(systems, true); + if (tc == null) { + res = new ValueSetExpansionOutcome("No server available", TerminologyServiceErrorClass.INTERNAL_ERROR, true); + } Parameters p = constructParameters(tc, vs, hierarchical); for (ConceptSetComponent incl : vs.getCompose().getInclude()) { codeSystemsUsed.add(incl.getSystem()); @@ -1885,8 +1888,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte return expParameters; } - public void setExpansionProfile(Parameters expParameters) { + public void setExpansionParameters(Parameters expParameters) { this.expParameters = expParameters; + this.terminologyClientManager.setExpansionParameters(expParameters); } @Override diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java index 04c666fb9..20440466f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/IWorkerContext.java @@ -284,7 +284,7 @@ public interface IWorkerContext { * * Note that the Validation Options override these when they are specified on validateCode */ - public void setExpansionProfile(Parameters expParameters); + public void setExpansionParameters(Parameters expParameters); // these are the terminology services used internally by the tools /** diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index 1498e416e..b21913ff5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -535,7 +535,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon version = "5.0.0"; } } - if (loader != null) { + if (loader != null && terminologyClientManager.getFactory() == null) { terminologyClientManager.setFactory(loader.txFactory()); } return t; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java index d9ae0ad06..145f39ad0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Parameters.java @@ -1512,7 +1512,14 @@ public String toString() { } return s; } + + + public boolean hasValuePrimitive() { + return hasValue() && getValue() instanceof PrimitiveType; + } + // end addition + } /** diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientManager.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientManager.java index 56ff5c0d5..6e77f5977 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientManager.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/client/TerminologyClientManager.java @@ -2,7 +2,9 @@ package org.hl7.fhir.r5.terminologies.client; import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URISyntaxException; +import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -11,6 +13,8 @@ import java.util.Map; import java.util.Set; import org.hl7.fhir.exceptions.TerminologyServiceException; +import org.hl7.fhir.r5.model.Parameters; +import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; import org.hl7.fhir.r5.model.TerminologyCapabilities; import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache; import org.hl7.fhir.utilities.ToolingClientLogger; @@ -37,10 +41,12 @@ public class TerminologyClientManager { private Map serverMap = new HashMap<>(); // clients by server address private Map resMap = new HashMap<>(); // client resolution list private List internalErrors = new ArrayList<>(); + protected Parameters expParameters; private TerminologyCache cache; private File cacheFile; + private String usage; private String monitorServiceURL; @@ -65,7 +71,6 @@ public class TerminologyClientManager { this.isTxCaching = isTxCaching; } - public void copy(TerminologyClientManager other) { cacheId = other.cacheId; isTxCaching = other.isTxCaching; @@ -74,6 +79,7 @@ public class TerminologyClientManager { resMap.putAll(other.resMap); monitorServiceURL = other.monitorServiceURL; factory = other.factory; + usage = other.usage; } public boolean usingCache() { @@ -105,6 +111,13 @@ public class TerminologyClientManager { String server = resMap.get(s); if (server == null) { server = decideWhichServer(s); + // testing support + if (server != null && server.contains("://tx.fhir.org")) { + try { + server = server.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost()); + } catch (MalformedURLException e) { + } + } resMap.put(s, server); save(); } @@ -123,7 +136,27 @@ public class TerminologyClientManager { } private String decideWhichServer(String url) { + if (expParameters != null) { + if (!url.contains("|")) { + // the client hasn''t specified an explicit version, but the expansion parameters might + for (ParametersParameterComponent p : expParameters.getParameter()) { + if (Utilities.existsInList(p.getName(), "system-version", "force-system-version") && p.hasValuePrimitive() && p.getValue().primitiveValue().startsWith(url+"|")) { + url = p.getValue().primitiveValue(); + } + } + } else { + // the expansion parameters might override the version + for (ParametersParameterComponent p : expParameters.getParameter()) { + if (Utilities.existsInList(p.getName(), "force-system-version") && p.hasValueCanonicalType() && p.getValue().primitiveValue().startsWith(url+"|")) { + url = p.getValue().primitiveValue(); + } + } + } + } String request = Utilities.pathURL(monitorServiceURL, "resolve?fhirVersion="+factory.getVersion()+"&url="+url); + if (usage != null) { + request = request + "&usage="+usage; + } try { JsonObject json = JsonParser.parseObjectFromUrl(request); for (JsonObject item : json.getJsonObjects("authoritative")) { @@ -209,6 +242,7 @@ public class TerminologyClientManager { public void setFactory(ITerminologyClientFactory factory) { this.factory = factory; + System.out.println("tcc factory version = "+factory.getVersion()); } public void setCache(TerminologyCache cache) { @@ -263,5 +297,21 @@ public class TerminologyClientManager { } - + + public Parameters getExpansionParameters() { + return expParameters; + } + + public void setExpansionParameters(Parameters expParameters) { + this.expParameters = expParameters; + } + + public String getUsage() { + return usage; + } + + public void setUsage(String usage) { + this.usage = usage; + } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java index 43b7c9f03..0c99acc42 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/test/utils/TestingUtilities.java @@ -86,7 +86,7 @@ public class TestingUtilities extends BaseTestingUtilities { fcontext = getWorkerContext(pcm.loadPackage(VersionUtilities.packageForVersion(version), version)); } fcontext.setUcumService(new UcumEssenceService(TestingUtilities.loadTestResourceStream("ucum", "ucum-essence.xml"))); - fcontext.setExpansionProfile(new Parameters()); + fcontext.setExpansionParameters(new Parameters()); if (!fcontext.hasPackage("hl7.terminology.r5", null)) { NpmPackage utg = pcm.loadPackage("hl7.terminology.r5"); System.out.println("Loading THO: "+utg.name()+"#"+utg.version()); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/context/SimpleWorkerContextTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/context/SimpleWorkerContextTests.java index a3c4afa60..509ca89bb 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/context/SimpleWorkerContextTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/context/SimpleWorkerContextTests.java @@ -1,6 +1,8 @@ package org.hl7.fhir.r5.context; import static org.junit.jupiter.api.Assertions.*; +import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5.TerminologyClientR5Factory; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.argThat; @@ -432,7 +434,7 @@ public class SimpleWorkerContextTests { Mockito.doReturn(terminologyCapabilities).when(terminologyCache).getTerminologyCapabilities(); Mockito.doReturn(capabilitiesStatement).when(terminologyCache).getCapabilityStatement(); - String actual = context.connectToTSServer(null, terminologyClient, null); + String actual = context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient, null); assertEquals("dummyVersion", actual); @@ -454,7 +456,7 @@ public class SimpleWorkerContextTests { Mockito.doReturn(terminologyCapabilities).when(terminologyClient).getTerminologyCapabilities(); Mockito.doReturn(capabilitiesStatement).when(terminologyClient).getCapabilitiesStatementQuick(); - String actual = context.connectToTSServer(null, terminologyClient, null); + String actual = context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient, null); assertEquals("dummyVersion", actual); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index 05b81a143..84f43d39f 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -477,7 +477,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP context.setCanNoTS(true); context.setCacheId(UUID.randomUUID().toString()); context.setAllowLoadingDuplicates(true); // because of Forge - context.setExpansionProfile(makeExpProfile()); + context.setExpansionParameters(makeExpProfile()); if (tt != null) { context.setClock(tt); } @@ -841,6 +841,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP public InstanceValidator getValidator(FhirFormat format) throws FHIRException, IOException { InstanceValidator validator = new InstanceValidator(context, null, null); + context.getTxClientManager().setUsage("validation"); validator.setHintAboutNonMustSupport(hintAboutNonMustSupport); validator.setAnyExtensionsAllowed(anyExtensionsAllowed); validator.getExtensionDomains().clear(); diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/R4R5MapTester.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/R4R5MapTester.java index 35d9e1ad8..dfecae980 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/R4R5MapTester.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/special/R4R5MapTester.java @@ -196,7 +196,7 @@ public class R4R5MapTester implements IValidatorResourceFetcher { validator.setDebug(false); validator.setForPublication(true); validator.setNoTerminologyChecks(true); - context.setExpansionProfile(new Parameters()); + context.setExpansionParameters(new Parameters()); log("Load R4 Examples"); NpmPackage r4Examples = pcm.loadPackage("hl7.fhir.r4.examples"); diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java index 9f168dc71..c91fa947a 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/UtilitiesXTests.java @@ -90,7 +90,7 @@ public class UtilitiesXTests { pcm = new FilesystemPackageCacheManager.Builder().build(); IWorkerContext fcontext = TestingUtilities.getWorkerContext(pcm.loadPackage(VersionUtilities.packageForVersion(version), version), loaderForVersion(version)); fcontext.setUcumService(new UcumEssenceService(UtilitiesXTests.loadTestResourceStream("ucum", "ucum-essence.xml"))); - fcontext.setExpansionProfile(new Parameters()); + fcontext.setExpansionParameters(new Parameters()); fcontexts.put(version, fcontext); } catch (Exception e) { throw new Error(e); diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java index 77757fafe..d924f6a16 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/terminology/tests/TerminologyServiceTests.java @@ -140,9 +140,9 @@ public class TerminologyServiceTests { fo.delete(); } if (setup.test.has("profile")) { - engine.getContext().setExpansionProfile((org.hl7.fhir.r5.model.Parameters) loadResource(setup.test.asString("profile"))); + engine.getContext().setExpansionParameters((org.hl7.fhir.r5.model.Parameters) loadResource(setup.test.asString("profile"))); } else { - engine.getContext().setExpansionProfile((org.hl7.fhir.r5.model.Parameters) loadResource("parameters-default.json")); + engine.getContext().setExpansionParameters((org.hl7.fhir.r5.model.Parameters) loadResource("parameters-default.json")); } if (setup.test.asString("operation").equals("expand")) { expand(engine, req, resp, setup.test.asString("Content-Language"), fp, ext); diff --git a/pom.xml b/pom.xml index d1633dfd5..02d08d870 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 32.0.1-jre 6.4.1 - 1.4.23 + 1.4.23-SNAPSHOT 2.16.0 5.9.2 1.8.2