Refactor Context to support multiple terminology services

This commit is contained in:
Grahame Grieve 2024-01-08 21:07:08 +11:00
parent cdfd941205
commit d74b0e2b4a
34 changed files with 763 additions and 180 deletions

View File

@ -16,3 +16,4 @@ major upgrade to validation - use terminology server to perform more logic, and
* R6 release support * R6 release support
* IPS tool development * IPS tool development
* Improved errors publishing IGs * Improved errors publishing IGs
* Refactor Context to support multiple terminology services

View File

@ -38,6 +38,7 @@ import java.util.UUID;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_14_50; import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_14_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_14_50;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.dstu2016may.formats.JsonParser; import org.hl7.fhir.dstu2016may.formats.JsonParser;
import org.hl7.fhir.dstu2016may.formats.XmlParser; import org.hl7.fhir.dstu2016may.formats.XmlParser;
import org.hl7.fhir.dstu2016may.model.Resource; import org.hl7.fhir.dstu2016may.model.Resource;
@ -49,6 +50,7 @@ import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
public class R2016MayToR5Loader extends BaseLoaderR5 { public class R2016MayToR5Loader extends BaseLoaderR5 {
@ -136,4 +138,9 @@ public class R2016MayToR5Loader extends BaseLoaderR5 {
return "4.3"; return "4.3";
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -38,6 +38,7 @@ import java.util.UUID;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_10_50; import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_10_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.dstu2.formats.JsonParser; import org.hl7.fhir.dstu2.formats.JsonParser;
import org.hl7.fhir.dstu2.formats.XmlParser; import org.hl7.fhir.dstu2.formats.XmlParser;
import org.hl7.fhir.dstu2.model.Resource; import org.hl7.fhir.dstu2.model.Resource;
@ -50,6 +51,7 @@ import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
public class R2ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader { public class R2ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader {
@ -140,4 +142,9 @@ public class R2ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader
return "1.0"; return "1.0";
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -38,6 +38,7 @@ import java.util.UUID;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_50; import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_30_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.dstu3.formats.JsonParser; import org.hl7.fhir.dstu3.formats.JsonParser;
import org.hl7.fhir.dstu3.formats.XmlParser; import org.hl7.fhir.dstu3.formats.XmlParser;
import org.hl7.fhir.dstu3.model.Resource; import org.hl7.fhir.dstu3.model.Resource;
@ -50,6 +51,7 @@ import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
public class R3ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader { public class R3ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader {
@ -135,4 +137,9 @@ public class R3ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader
return "3.0"; return "3.0";
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -38,6 +38,7 @@ import java.util.UUID;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50; import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.formats.JsonParser; import org.hl7.fhir.r4.formats.JsonParser;
import org.hl7.fhir.r4.formats.XmlParser; import org.hl7.fhir.r4.formats.XmlParser;
@ -51,6 +52,7 @@ import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.VersionUtilities;
public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoader { public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoader {
@ -143,4 +145,9 @@ public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoade
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -38,6 +38,7 @@ import java.util.UUID;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50; import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50; import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.formats.JsonParser; import org.hl7.fhir.r4.formats.JsonParser;
import org.hl7.fhir.r4.formats.XmlParser; import org.hl7.fhir.r4.formats.XmlParser;
@ -51,6 +52,7 @@ import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.VersionUtilities;
public class R4ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader { public class R4ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader {
@ -144,4 +146,9 @@ public class R4ToR5Loader extends BaseLoaderR5 implements IContextResourceLoader
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -6,6 +6,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -47,6 +49,7 @@ import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
public class R5ToR5Loader extends BaseLoaderR5 { public class R5ToR5Loader extends BaseLoaderR5 {
@ -128,4 +131,9 @@ public class R5ToR5Loader extends BaseLoaderR5 {
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -6,6 +6,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -47,6 +49,7 @@ import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
public class R6ToR5Loader extends BaseLoaderR5 { public class R6ToR5Loader extends BaseLoaderR5 {
@ -120,5 +123,10 @@ public class R6ToR5Loader extends BaseLoaderR5 {
return "5.0"; return "5.0";
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientFactory(versionString());
}
} }

View File

@ -3,36 +3,27 @@ package org.hl7.fhir.convertors.txClient;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient; import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5;
import org.hl7.fhir.utilities.FhirPublication; import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.VersionUtilities;
public class TerminologyClientFactory { public class TerminologyClientFactory implements ITerminologyClientFactory {
public static ITerminologyClient makeClient(String id, String url, String userAgent, FhirPublication v) throws URISyntaxException { private String v;
if (v == null)
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent); public TerminologyClientFactory(FhirPublication v) {
switch (v) { super();
case DSTU2016May: this.v = v == null ? null : v.toCode();
return new TerminologyClientR3(id, checkEndsWith("/r3", url), userAgent); // r3 is the least worst match }
case DSTU1:
throw new Error("The version " + v + " is not currently supported"); public TerminologyClientFactory(String version) {
case DSTU2: super();
return new TerminologyClientR2(id, checkEndsWith("/r2", url), userAgent); this.v = version;
case R4:
return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent);
case R4B:
return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent);
case R5:
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent); // r4 for now, since the terminology is currently the same
case STU3:
return new TerminologyClientR3(id, checkEndsWith("/r3", url), userAgent);
default:
throw new Error("The version " + v + " is not currently supported");
}
} }
public static ITerminologyClient makeClient(String id, String url, String userAgent, String v) throws URISyntaxException { public ITerminologyClient makeClient(String id, String url, String userAgent) throws URISyntaxException {
if (v == null) if (v == null)
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent); return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent);
v = VersionUtilities.getMajMin(v); v = VersionUtilities.getMajMin(v);
@ -57,7 +48,7 @@ public class TerminologyClientFactory {
throw new Error("The version " + v + " is not currently supported"); throw new Error("The version " + v + " is not currently supported");
} }
private static String checkEndsWith(String term, String url) { private String checkEndsWith(String term, String url) {
if (url.endsWith(term)) if (url.endsWith(term))
return url; return url;
if (Utilities.isTxFhirOrgServer(url)) { if (Utilities.isTxFhirOrgServer(url)) {
@ -66,4 +57,9 @@ public class TerminologyClientFactory {
return url; return url;
} }
@Override
public String getVersion() {
return v;
}
} }

View File

@ -221,4 +221,9 @@ public class TerminologyClientR2 implements ITerminologyClient {
client.setContentLanguage(lang); client.setContentLanguage(lang);
return this; return this;
} }
@Override
public int getUseCount() {
return client.getUseCount();
}
} }

View File

@ -223,4 +223,10 @@ public class TerminologyClientR3 implements ITerminologyClient {
client.setContentLanguage(lang); client.setContentLanguage(lang);
return this; return this;
} }
@Override
public int getUseCount() {
return client.getUseCount();
}
} }

View File

@ -235,4 +235,11 @@ public class TerminologyClientR4 implements ITerminologyClient {
client.setContentLanguage(lang); client.setContentLanguage(lang);
return this; return this;
} }
@Override
public int getUseCount() {
return client.getUseCount();
}
} }

View File

@ -53,14 +53,14 @@ public class TerminologyClientFactoryTest {
@ParameterizedTest @ParameterizedTest
@MethodSource("data") @MethodSource("data")
public void testMakeClient(String url, FhirPublication fhirPublication, String expectedAddress) throws URISyntaxException { public void testMakeClient(String url, FhirPublication fhirPublication, String expectedAddress) throws URISyntaxException {
ITerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", url, "dummyUserAgent", fhirPublication); ITerminologyClient terminologyClient = new TerminologyClientFactory(fhirPublication).makeClient("id", url, "dummyUserAgent");
assertEquals(expectedAddress, terminologyClient.getAddress()); assertEquals(expectedAddress, terminologyClient.getAddress());
} }
@Test @Test
public void testMakeClientDstu1Fails() throws URISyntaxException { public void testMakeClientDstu1Fails() throws URISyntaxException {
assertThrows(Error.class, () -> { assertThrows(Error.class, () -> {
ITerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", "urldoesnotmatter", "dummyUserAgent", FhirPublication.DSTU1); ITerminologyClient terminologyClient = new TerminologyClientFactory(FhirPublication.DSTU1).makeClient("id", "urldoesnotmatter", "dummyUserAgent");
} }
); );
} }
@ -68,7 +68,7 @@ public class TerminologyClientFactoryTest {
@Test @Test
public void testMakeClientNullFails() throws URISyntaxException { public void testMakeClientNullFails() throws URISyntaxException {
assertThrows(Error.class, () -> { assertThrows(Error.class, () -> {
ITerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", "urldoesnotmatter", "dummyUserAgent", FhirPublication.NULL); ITerminologyClient terminologyClient = new TerminologyClientFactory(FhirPublication.NULL).makeClient("id", "urldoesnotmatter", "dummyUserAgent");
} }
); );
} }

View File

@ -96,6 +96,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
private int maxResultSetSize = -1;// _count private int maxResultSetSize = -1;// _count
private Conformance conf; private Conformance conf;
private ClientUtils utils = new ClientUtils(); private ClientUtils utils = new ClientUtils();
private int useCount;
// Pass enpoint for client - URI // Pass enpoint for client - URI
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException { public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
@ -213,6 +214,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T read(Class<T> resourceClass, String id) {// TODO Change this to AddressableResource public <T extends Resource> T read(Class<T> resourceClass, String id) {// TODO Change this to AddressableResource
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -231,6 +233,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) { public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = utils.issueGetResourceRequest( result = utils.issueGetResourceRequest(
@ -254,6 +257,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
// fhir/ValueSet?url=http://hl7.org/fhir/ValueSet/clinical-findings&version=0.8 // fhir/ValueSet?url=http://hl7.org/fhir/ValueSet/clinical-findings&version=0.8
public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) { public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = utils.issueGetResourceRequest( result = utils.issueGetResourceRequest(
@ -279,6 +283,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Resource update(Resource resource) { public Resource update(Resource resource) {
recordUse();
ResourceRequest<Resource> result = null; ResourceRequest<Resource> result = null;
try { try {
List<Header> headers = null; List<Header> headers = null;
@ -315,6 +320,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) { public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
List<Header> headers = null; List<Header> headers = null;
@ -515,6 +521,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
// } // }
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) { public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) {
recordUse();
boolean complex = false; boolean complex = false;
for (ParametersParameterComponent p : params.getParameter()) for (ParametersParameterComponent p : params.getParameter())
complex = complex || !(p.getValue() instanceof PrimitiveType); complex = complex || !(p.getValue() instanceof PrimitiveType);
@ -548,6 +555,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle transaction(Bundle batch) { public Bundle transaction(Bundle batch) {
recordUse();
Bundle transactionResult = null; Bundle transactionResult = null;
try { try {
transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(),
@ -561,6 +569,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) { public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
@ -705,6 +714,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle fetchFeed(String url) { public Bundle fetchFeed(String url) {
recordUse();
Bundle feed = null; Bundle feed = null;
try { try {
feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat()); feed = utils.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
@ -715,6 +725,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source) { public ValueSet expandValueset(ValueSet source) {
recordUse();
List<Header> headers = null; List<Header> headers = null;
ResourceRequest<Resource> result = utils.issuePostRequest( ResourceRequest<Resource> result = utils.issuePostRequest(
resourceAddress.resolveOperationUri(ValueSet.class, "expand"), resourceAddress.resolveOperationUri(ValueSet.class, "expand"),
@ -734,6 +745,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Parameters lookupCode(Map<String, String> params) { public Parameters lookupCode(Map<String, String> params) {
recordUse();
ResourceRequest<Resource> result = utils.issueGetResourceRequest( ResourceRequest<Resource> result = utils.issueGetResourceRequest(
resourceAddress.resolveOperationUri(ValueSet.class, "lookup", params), getPreferredResourceFormat(), resourceAddress.resolveOperationUri(ValueSet.class, "lookup", params), getPreferredResourceFormat(),
timeoutNormal); timeoutNormal);
@ -751,6 +763,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) { public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) {
recordUse();
List<Header> headers = null; List<Header> headers = null;
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
@ -794,6 +807,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap initializeClosure(String name) { public ConceptMap initializeClosure(String name) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
List<Header> headers = null; List<Header> headers = null;
@ -815,6 +829,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap updateClosure(String name, Coding coding) { public ConceptMap updateClosure(String name, Coding coding) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
params.addParameter().setName("concept").setValue(coding); params.addParameter().setName("concept").setValue(coding);
@ -902,4 +917,11 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
utils.setAcceptLanguage(lang); utils.setAcceptLanguage(lang);
} }
public int getUseCount() {
return useCount;
}
private void recordUse() {
useCount++;
}
} }

View File

@ -79,6 +79,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
private EnumSet<FhirPublication> allowedVersions; private EnumSet<FhirPublication> allowedVersions;
private String acceptLang; private String acceptLang;
private String contentLang; private String contentLang;
private int useCount;
//Pass endpoint for client - URI //Pass endpoint for client - URI
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException { public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
@ -187,6 +188,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T read(Class<T> resourceClass, String id) {//TODO Change this to AddressableResource public <T extends Resource> T read(Class<T> resourceClass, String id) {//TODO Change this to AddressableResource
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -204,6 +206,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) { public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version),
@ -221,6 +224,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) { public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL),
@ -243,6 +247,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Resource update(Resource resource) { public Resource update(Resource resource) {
recordUse();
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()), result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),
@ -270,6 +275,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) { public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -297,6 +303,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) { public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) {
recordUse();
boolean complex = false; boolean complex = false;
for (ParametersParameterComponent p : params.getParameter()) for (ParametersParameterComponent p : params.getParameter())
complex = complex || !(p.getValue() instanceof PrimitiveType); complex = complex || !(p.getValue() instanceof PrimitiveType);
@ -339,6 +346,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
public Bundle transaction(Bundle batch) { public Bundle transaction(Bundle batch) {
recordUse();
Bundle transactionResult = null; Bundle transactionResult = null;
try { try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "transaction", timeoutOperation + (timeoutEntry * batch.getEntry().size())); transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "transaction", timeoutOperation + (timeoutEntry * batch.getEntry().size()));
@ -350,6 +358,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) { public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
@ -395,6 +404,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle fetchFeed(String url) { public Bundle fetchFeed(String url) {
recordUse();
Bundle feed = null; Bundle feed = null;
try { try {
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat()); feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
@ -405,6 +415,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams) { public ValueSet expandValueset(ValueSet source, Parameters expParams) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
@ -426,6 +437,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
public Parameters lookupCode(Map<String, String> params) { public Parameters lookupCode(Map<String, String> params) {
recordUse();
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params),
@ -443,6 +455,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, ExpansionProfile profile, Map<String, String> params) { public ValueSet expandValueset(ValueSet source, ExpansionProfile profile, Map<String, String> params) {
recordUse();
Parameters p = new Parameters(); Parameters p = new Parameters();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
if (profile != null) if (profile != null)
@ -466,6 +479,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) { public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
for (String n : params.keySet()) { for (String n : params.keySet()) {
@ -494,6 +508,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap initializeClosure(String name) { public ConceptMap initializeClosure(String name) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
ResourceRequest<Resource> result = null; ResourceRequest<Resource> result = null;
@ -514,6 +529,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap updateClosure(String name, Coding coding) { public ConceptMap updateClosure(String name, Coding coding) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
params.addParameter().setName("concept").setValue(coding); params.addParameter().setName("concept").setValue(coding);
@ -629,5 +645,13 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
public void setContentLanguage(String lang) { public void setContentLanguage(String lang) {
this.contentLang = lang; this.contentLang = lang;
} }
public int getUseCount() {
return useCount;
}
private void recordUse() {
useCount++;
}
} }

View File

@ -80,6 +80,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
private String userAgent; private String userAgent;
private String acceptLang; private String acceptLang;
private String contentLang; private String contentLang;
private int useCount;
// Pass endpoint for client - URI // Pass endpoint for client - URI
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException { public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
@ -162,6 +163,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource
recordUse();
ResourceRequest<Resource> result = null; ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -178,6 +180,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T read(Class<T> resourceClass, String id) {// TODO Change this to AddressableResource public <T extends Resource> T read(Class<T> resourceClass, String id) {// TODO Change this to AddressableResource
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -194,6 +197,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) { public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest( result = client.issueGetResourceRequest(
@ -211,6 +215,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) { public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest( result = client.issueGetResourceRequest(
@ -233,6 +238,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Resource update(Resource resource) { public Resource update(Resource resource) {
recordUse();
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issuePutRequest( result = client.issuePutRequest(
@ -263,6 +269,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) { public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -292,6 +299,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) throws IOException { public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) throws IOException {
recordUse();
boolean complex = false; boolean complex = false;
for (ParametersParameterComponent p : params.getParameter()) for (ParametersParameterComponent p : params.getParameter())
complex = complex || !(p.getValue() instanceof PrimitiveType); complex = complex || !(p.getValue() instanceof PrimitiveType);
@ -324,6 +332,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle transaction(Bundle batch) { public Bundle transaction(Bundle batch) {
recordUse();
Bundle transactionResult = null; Bundle transactionResult = null;
try { try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(),
@ -337,6 +346,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) { public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
@ -383,6 +393,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle fetchFeed(String url) { public Bundle fetchFeed(String url) {
recordUse();
Bundle feed = null; Bundle feed = null;
try { try {
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat(), timeoutLong); feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat(), timeoutLong);
@ -393,6 +404,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(String vsUrl, Parameters expParams) { public ValueSet expandValueset(String vsUrl, Parameters expParams) {
recordUse();
Map<String, String> parameters = new HashMap<>(); Map<String, String> parameters = new HashMap<>();
parameters.put("url", vsUrl); parameters.put("url", vsUrl);
if (expParams != null) { if (expParams != null) {
@ -422,6 +434,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams) { public ValueSet expandValueset(ValueSet source, Parameters expParams) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
@ -440,6 +453,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Parameters lookupCode(Map<String, String> params) { public Parameters lookupCode(Map<String, String> params) {
recordUse();
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params),
@ -455,6 +469,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) { public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
if (params != null) { if (params != null) {
@ -489,6 +504,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap initializeClosure(String name) { public ConceptMap initializeClosure(String name) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
ResourceRequest<Resource> result = null; ResourceRequest<Resource> result = null;
@ -508,6 +524,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap updateClosure(String name, Coding coding) { public ConceptMap updateClosure(String name, Coding coding) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
params.addParameter().setName("concept").setValue(coding); params.addParameter().setName("concept").setValue(coding);
@ -619,10 +636,12 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle search(String type, String criteria) { public Bundle search(String type, String criteria) {
recordUse();
return fetchFeed(Utilities.pathURL(base, type+criteria)); return fetchFeed(Utilities.pathURL(base, type+criteria));
} }
public <T extends Resource> T fetchResource(Class<T> resourceClass, String id) { public <T extends Resource> T fetchResource(Class<T> resourceClass, String id) {
recordUse();
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetResource(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetResource(resourceClass, id),
@ -636,6 +655,13 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
return (T) result.getPayload(); return (T) result.getPayload();
} }
public int getUseCount() {
return useCount;
}
private void recordUse() {
useCount++;
}
} }

View File

@ -132,6 +132,8 @@ import org.hl7.fhir.r5.terminologies.validation.VSCheckerException;
import org.hl7.fhir.r5.terminologies.validation.ValueSetValidator; import org.hl7.fhir.r5.terminologies.validation.ValueSetValidator;
import org.hl7.fhir.r5.terminologies.ValueSetUtilities; import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient; import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5.TerminologyClientR5Factory;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext; import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext;
import org.hl7.fhir.r5.utils.PackageHackerR5; import org.hl7.fhir.r5.utils.PackageHackerR5;
import org.hl7.fhir.r5.utils.ResourceUtilities; import org.hl7.fhir.r5.utils.ResourceUtilities;
@ -240,7 +242,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
private Object lock = new Object(); // used as a lock for the data that follows 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 String version; // although the internal resources are all R5, the version of FHIR they describe may not be
protected TerminologyClientContext tcc = new TerminologyClientContext(); protected TerminologyClientManager tcc = new TerminologyClientManager(new TerminologyClientR5Factory());
private boolean minimalMemory = false; private boolean minimalMemory = false;
private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>(); private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>();
@ -786,15 +788,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (tcc.getTxcaps() == null) { if (tcc.getTxcaps() == null) {
try { try {
logger.logMessage("Terminology server: Check for supported code systems for "+system); logger.logMessage("Terminology server: Check for supported code systems for "+system);
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : tcc.getClient().getTerminologyCapabilities(); final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : tcc.getMasterClient().getTerminologyCapabilities();
txCache.cacheTerminologyCapabilities(capabilityStatement); txCache.cacheTerminologyCapabilities(capabilityStatement);
setTxCaps(capabilityStatement); setTxCaps(capabilityStatement);
} catch (Exception e) { } catch (Exception e) {
if (canRunWithoutTerminology) { if (canRunWithoutTerminology) {
noTerminologyServer = true; noTerminologyServer = true;
logger.logMessage("==============!! Running without terminology server !! =============="); logger.logMessage("==============!! Running without terminology server !! ==============");
if (tcc.getClient() != null) { if (tcc.getMasterClient() != null) {
logger.logMessage("txServer = "+tcc.getClient().getId()); logger.logMessage("txServer = "+tcc.getMasterClient().getId());
logger.logMessage("Error = "+e.getMessage()+""); logger.logMessage("Error = "+e.getMessage()+"");
} }
logger.logMessage("====================================================================="); logger.logMessage("=====================================================================");
@ -857,7 +859,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (res != null) { if (res != null) {
return res; return res;
} }
Parameters p = constructParameters(vs, hierarchical); Set<String> systems = findRelevantSystems(vs);
TerminologyClientContext tc = tcc.chooseServer(systems, true);
Parameters p = constructParameters(tc, vs, hierarchical);
for (ConceptSetComponent incl : vs.getCompose().getInclude()) { for (ConceptSetComponent incl : vs.getCompose().getInclude()) {
codeSystemsUsed.add(incl.getSystem()); codeSystemsUsed.add(incl.getSystem());
} }
@ -871,13 +875,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
Map<String, String> params = new HashMap<String, String>(); Map<String, String> params = new HashMap<String, String>();
params.put("_limit", Integer.toString(expandCodesLimit )); params.put("_limit", Integer.toString(expandCodesLimit ));
params.put("_incomplete", "true"); params.put("_incomplete", "true");
txLog("$expand on "+txCache.summary(vs)); txLog("$expand on "+txCache.summary(vs)+" on "+tc.getAddress());
if (addDependentResources(p, vs)) { if (addDependentResources(tc, p, vs)) {
p.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId())); p.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId()));
} }
try { try {
ValueSet result = tcc.getClient().expandValueset(vs, p, params); ValueSet result = tc.getClient().expandValueset(vs, p, params);
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId()); res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
} catch (Exception e) { } catch (Exception e) {
res = new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.UNKNOWN, true); res = new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.UNKNOWN, true);
@ -972,14 +976,18 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
p.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId())); p.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId()));
addDependentResources(p, vs); Set<String> systems = findRelevantSystems(vs);
TerminologyClientContext tc = tcc.chooseServer(systems, true);
addDependentResources(tc, p, vs);
Map<String, String> params = new HashMap<String, String>(); Map<String, String> params = new HashMap<String, String>();
params.put("_limit", Integer.toString(expandCodesLimit )); params.put("_limit", Integer.toString(expandCodesLimit ));
params.put("_incomplete", "true"); params.put("_incomplete", "true");
txLog("$expand on "+txCache.summary(vs));
txLog("$expand on "+txCache.summary(vs)+" on "+tc.getAddress());
try { try {
ValueSet result = tcc.getClient().expandValueset(vs, p, params); ValueSet result = tc.getClient().expandValueset(vs, p, params);
if (result != null) { if (result != null) {
if (!result.hasUrl()) { if (!result.hasUrl()) {
result.setUrl(vs.getUrl()); result.setUrl(vs.getUrl());
@ -1052,7 +1060,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (!t.hasResult()) { if (!t.hasResult()) {
try { try {
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs == null ? t.getVsObj() : vs); ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs == null ? t.getVsObj() : vs);
vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null); vsc.setThrowToServer(options.isUseServer() && tcc.hasClient());
ValidationResult res = vsc.validateCode("Coding", t.getCoding()); ValidationResult res = vsc.validateCode("Coding", t.getCoding());
if (txCache != null) { if (txCache != null) {
txCache.cacheValidation(t.getCacheToken(), res, TerminologyCache.TRANSIENT); txCache.cacheValidation(t.getCacheToken(), res, TerminologyCache.TRANSIENT);
@ -1082,7 +1090,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
// for those that that failed, we try to validate on the server // for those that that failed, we try to validate on the server
Bundle batch = new Bundle(); Bundle batch = new Bundle();
batch.setType(BundleType.BATCH); batch.setType(BundleType.BATCH);
Set<String> systems = new HashSet<>(); Set<String> systems = findRelevantSystems(vs);
for (CodingValidationRequest codingValidationRequest : codes) { for (CodingValidationRequest codingValidationRequest : codes) {
if (!codingValidationRequest.hasResult()) { if (!codingValidationRequest.hasResult()) {
Parameters pIn = constructParameters(options, codingValidationRequest, vs == null ? codingValidationRequest.getVsObj() : vs); Parameters pIn = constructParameters(options, codingValidationRequest, vs == null ? codingValidationRequest.getVsObj() : vs);
@ -1097,16 +1105,19 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
be.setUserData("source", codingValidationRequest); be.setUserData("source", codingValidationRequest);
systems.add(codingValidationRequest.getCoding().getSystem()); systems.add(codingValidationRequest.getCoding().getSystem());
findRelevantSystems(systems, codingValidationRequest.getCoding());
} }
} }
if (batch.getEntry().size() > 0) { if (batch.getEntry().size() > 0) {
Bundle resp = processBatch(batch, systems); TerminologyClientContext tc = tcc.chooseServer(systems, false);
Bundle resp = processBatch(tc, batch, systems);
for (int i = 0; i < batch.getEntry().size(); i++) { for (int i = 0; i < batch.getEntry().size(); i++) {
CodingValidationRequest t = (CodingValidationRequest) batch.getEntry().get(i).getUserData("source"); CodingValidationRequest t = (CodingValidationRequest) batch.getEntry().get(i).getUserData("source");
BundleEntryComponent r = resp.getEntry().get(i); BundleEntryComponent r = resp.getEntry().get(i);
if (r.getResource() instanceof Parameters) { if (r.getResource() instanceof Parameters) {
t.setResult(processValidationResult((Parameters) r.getResource(), vs != null ? vs.getUrl() : t.getVsObj() != null ? t.getVsObj().getUrl() : null, tcc.getClient().getAddress())); t.setResult(processValidationResult((Parameters) r.getResource(), vs != null ? vs.getUrl() : t.getVsObj() != null ? t.getVsObj().getUrl() : null, tc.getAddress()));
if (txCache != null) { if (txCache != null) {
txCache.cacheValidation(t.getCacheToken(), t.getResult(), TerminologyCache.PERMANENT); txCache.cacheValidation(t.getCacheToken(), t.getResult(), TerminologyCache.PERMANENT);
} }
@ -1117,15 +1128,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
private Bundle processBatch(Bundle batch, Set<String> systems) { private Bundle processBatch(TerminologyClientContext tc, Bundle batch, Set<String> systems) {
txLog("$batch validate for "+batch.getEntry().size()+" codes on systems "+systems.toString()); txLog("$batch validate for "+batch.getEntry().size()+" codes on systems "+systems.toString());
if (tcc.getClient() == null) { if (tcc == null) {
throw new FHIRException(formatMessage(I18nConstants.ATTEMPT_TO_USE_TERMINOLOGY_SERVER_WHEN_NO_TERMINOLOGY_SERVER_IS_AVAILABLE)); throw new FHIRException(formatMessage(I18nConstants.ATTEMPT_TO_USE_TERMINOLOGY_SERVER_WHEN_NO_TERMINOLOGY_SERVER_IS_AVAILABLE));
} }
if (txLog != null) { if (txLog != null) {
txLog.clearLastId(); txLog.clearLastId();
} }
Bundle resp = tcc.getClient().validateBatch(batch); Bundle resp = tc.getClient().validateBatch(batch);
if (resp == null) { if (resp == null) {
throw new FHIRException(formatMessage(I18nConstants.TX_SERVER_NO_BATCH_RESPONSE)); throw new FHIRException(formatMessage(I18nConstants.TX_SERVER_NO_BATCH_RESPONSE));
} }
@ -1149,14 +1160,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
t.setResult(txCache.getValidation(t.getCacheToken())); t.setResult(txCache.getValidation(t.getCacheToken()));
} }
} }
ValueSet vs = fetchResource(ValueSet.class, vsUrl);
if (options.isUseClient()) { if (options.isUseClient()) {
ValueSet vs = fetchResource(ValueSet.class, vsUrl);
if (vs != null) { if (vs != null) {
for (CodingValidationRequest t : codes) { for (CodingValidationRequest t : codes) {
if (!t.hasResult()) { if (!t.hasResult()) {
try { try {
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs); ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs);
vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null); vsc.setThrowToServer(options.isUseServer() && tcc.hasClient());
ValidationResult res = vsc.validateCode("Coding", t.getCoding()); ValidationResult res = vsc.validateCode("Coding", t.getCoding());
if (txCache != null) { if (txCache != null) {
txCache.cacheValidation(t.getCacheToken(), res, TerminologyCache.TRANSIENT); txCache.cacheValidation(t.getCacheToken(), res, TerminologyCache.TRANSIENT);
@ -1187,7 +1198,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
// for those that that failed, we try to validate on the server // for those that that failed, we try to validate on the server
Bundle batch = new Bundle(); Bundle batch = new Bundle();
batch.setType(BundleType.BATCH); batch.setType(BundleType.BATCH);
Set<String> systems = new HashSet<>(); Set<String> systems = vs != null ? findRelevantSystems(vs) : new HashSet<>();
for (CodingValidationRequest codingValidationRequest : codes) { for (CodingValidationRequest codingValidationRequest : codes) {
if (!codingValidationRequest.hasResult()) { if (!codingValidationRequest.hasResult()) {
Parameters pIn = constructParameters(options, codingValidationRequest, vsUrl); Parameters pIn = constructParameters(options, codingValidationRequest, vsUrl);
@ -1204,14 +1215,16 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
systems.add(codingValidationRequest.getCoding().getSystem()); systems.add(codingValidationRequest.getCoding().getSystem());
} }
} }
TerminologyClientContext tc = tcc.chooseServer(systems, false);
if (batch.getEntry().size() > 0) { if (batch.getEntry().size() > 0) {
Bundle resp = processBatch(batch, systems); Bundle resp = processBatch(tc, batch, systems);
for (int i = 0; i < batch.getEntry().size(); i++) { for (int i = 0; i < batch.getEntry().size(); i++) {
CodingValidationRequest t = (CodingValidationRequest) batch.getEntry().get(i).getUserData("source"); CodingValidationRequest t = (CodingValidationRequest) batch.getEntry().get(i).getUserData("source");
BundleEntryComponent r = resp.getEntry().get(i); BundleEntryComponent r = resp.getEntry().get(i);
if (r.getResource() instanceof Parameters) { if (r.getResource() instanceof Parameters) {
t.setResult(processValidationResult((Parameters) r.getResource(), vsUrl, tcc.getClient().getAddress())); t.setResult(processValidationResult((Parameters) r.getResource(), vsUrl, tc.getAddress()));
if (txCache != null) { if (txCache != null) {
txCache.cacheValidation(t.getCacheToken(), t.getResult(), TerminologyCache.PERMANENT); txCache.cacheValidation(t.getCacheToken(), t.getResult(), TerminologyCache.PERMANENT);
} }
@ -1278,7 +1291,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
try { try {
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs, ctxt); ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs, ctxt);
vsc.setUnknownSystems(unknownSystems); vsc.setUnknownSystems(unknownSystems);
vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null); vsc.setThrowToServer(options.isUseServer() && tcc.hasClient());
if (!ValueSetUtilities.isServerSide(code.getSystem())) { if (!ValueSetUtilities.isServerSide(code.getSystem())) {
res = vsc.validateCode(path, code); res = vsc.validateCode(path, code);
if (txCache != null && cachingAllowed) { if (txCache != null && cachingAllowed) {
@ -1307,14 +1320,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
if (localError != null && tcc.getClient() == null) { if (localError != null && !tcc.hasClient()) {
if (unknownSystems.size() > 0) { if (unknownSystems.size() > 0) {
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues).setUnknownSystems(unknownSystems); return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues).setUnknownSystems(unknownSystems);
} else { } else {
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.UNKNOWN, issues); return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.UNKNOWN, issues);
} }
} }
if (localWarning != null && tcc.getClient() == null) { if (localWarning != null && !tcc.hasClient()) {
return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER, localWarning), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, issues); return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER, localWarning), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, issues);
} }
if (!options.isUseServer()) { if (!options.isUseServer()) {
@ -1333,15 +1346,19 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (noTerminologyServer) { if (noTerminologyServer) {
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, issues); return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, issues);
} }
Set<String> systems = findRelevantSystems(code, vs);
TerminologyClientContext tc = tcc.chooseServer(systems, false);
String csumm =cachingAllowed && txCache != null ? txCache.summary(code) : null; String csumm =cachingAllowed && txCache != null ? txCache.summary(code) : null;
if (cachingAllowed && txCache != null) { if (cachingAllowed && txCache != null) {
txLog("$validate "+csumm+(vs == null ? "" : " for "+ txCache.summary(vs))); txLog("$validate "+csumm+(vs == null ? "" : " for "+ txCache.summary(vs))+" on "+tc.getAddress());
} else { } else {
txLog("$validate "+csumm+" before cache exists"); txLog("$validate "+csumm+" before cache exists on "+tc.getAddress());
} }
try { try {
Parameters pIn = constructParameters(options, code); Parameters pIn = constructParameters(options, code);
res = validateOnServer(vs, pIn, options); res = validateOnServer(tc, vs, pIn, options);
} catch (Exception e) { } catch (Exception e) {
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR); res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId()).setErrorClass(TerminologyServiceErrorClass.SERVER_ERROR);
} }
@ -1375,12 +1392,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, expParameters, tcc.getTxcaps()); return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, expParameters, tcc.getTxcaps());
} }
protected Parameters constructParameters(ValueSet vs, boolean hierarchical) { protected Parameters constructParameters(TerminologyClientContext tcd, ValueSet vs, boolean hierarchical) {
Parameters p = expParameters.copy(); Parameters p = expParameters.copy();
p.setParameter("includeDefinition", false); p.setParameter("includeDefinition", false);
p.setParameter("excludeNested", !hierarchical); p.setParameter("excludeNested", !hierarchical);
addDependentResources(p, vs); addDependentResources(tcd, p, vs);
p.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId())); p.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId()));
return p; return p;
} }
@ -1477,7 +1494,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
try { try {
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs); ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs);
vsc.setUnknownSystems(unknownSystems); vsc.setUnknownSystems(unknownSystems);
vsc.setThrowToServer(options.isUseServer() && tcc.getClient() != null); vsc.setThrowToServer(options.isUseServer() && tcc.hasClient());
res = vsc.validateCode("CodeableConcept", code); res = vsc.validateCode("CodeableConcept", code);
if (cachingAllowed) { if (cachingAllowed) {
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT); txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
@ -1503,14 +1520,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
if (localError != null && tcc.getClient() == null) { if (localError != null && !tcc.hasClient()) {
if (unknownSystems.size() > 0) { if (unknownSystems.size() > 0) {
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues).setUnknownSystems(unknownSystems); return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues).setUnknownSystems(unknownSystems);
} else { } else {
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.UNKNOWN, issues); return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.UNKNOWN, issues);
} }
} }
if (localWarning != null && tcc.getClient() == null) { if (localWarning != null && !tcc.hasClient()) {
return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER, localWarning), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, issues); return new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER, localWarning), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, issues);
} }
@ -1522,10 +1539,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (noTerminologyServer) { if (noTerminologyServer) {
return new ValidationResult(IssueSeverity.ERROR, "Error validating code: running without terminology services", TerminologyServiceErrorClass.NOSERVICE, null); return new ValidationResult(IssueSeverity.ERROR, "Error validating code: running without terminology services", TerminologyServiceErrorClass.NOSERVICE, null);
} }
txLog("$validate "+txCache.summary(code)+" for "+ txCache.summary(vs)); Set<String> systems = findRelevantSystems(code, vs);
TerminologyClientContext tc = tcc.chooseServer(systems, false);
txLog("$validate "+txCache.summary(code)+" for "+ txCache.summary(vs)+" on "+tc.getAddress());
try { try {
Parameters pIn = constructParameters(options, code); Parameters pIn = constructParameters(options, code);
res = validateOnServer(vs, pIn, options); res = validateOnServer(tc, vs, pIn, options);
} catch (Exception e) { } catch (Exception e) {
res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId()); res = new ValidationResult(IssueSeverity.ERROR, e.getMessage() == null ? e.getClass().getName() : e.getMessage(), null).setTxLink(txLog == null ? null : txLog.getLastId());
} }
@ -1535,7 +1555,74 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
return res; return res;
} }
protected ValidationResult validateOnServer(ValueSet vs, Parameters pin, ValidationOptions options) throws FHIRException { private Set<String> findRelevantSystems(ValueSet vs) {
Set<String> set = new HashSet<>();
if (vs != null) {
findRelevantSystems(set, vs);
}
return set;
}
private Set<String> findRelevantSystems(CodeableConcept code, ValueSet vs) {
Set<String> set = new HashSet<>();
if (vs != null) {
findRelevantSystems(set, vs);
}
for (Coding c : code.getCoding()) {
findRelevantSystems(set, c);
}
return set;
}
private Set<String> findRelevantSystems(Coding code, ValueSet vs) {
Set<String> set = new HashSet<>();
if (vs != null) {
findRelevantSystems(set, vs);
}
if (code != null) {
findRelevantSystems(set, code);
}
return set;
}
private void findRelevantSystems(Set<String> set, ValueSet vs) {
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
findRelevantSystems(set, inc);
}
for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
findRelevantSystems(set, inc);
}
}
private void findRelevantSystems(Set<String> set, ConceptSetComponent inc) {
if (inc.hasSystem()) {
if (inc.hasVersion()) {
set.add(inc.getSystem()+"|"+inc.getVersion());
} else {
set.add(inc.getSystem());
}
}
for (CanonicalType u : inc.getValueSet()) {
ValueSet vs = fetchResource(ValueSet.class, u.getValue());
if (vs != null) {
findRelevantSystems(set, vs);
} else {
set.add(TerminologyClientManager.UNRESOLVED_VALUESET);
}
}
}
private void findRelevantSystems(Set<String> set, Coding c) {
if (c.hasSystem()) {
if (c.hasVersion()) {
set.add(c.getSystem()+"|"+c.getVersion());
} else {
set.add(c.getSystem());
}
}
}
protected ValidationResult validateOnServer(TerminologyClientContext tc, ValueSet vs, Parameters pin, ValidationOptions options) throws FHIRException {
if (vs != null) { if (vs != null) {
for (ConceptSetComponent inc : vs.getCompose().getInclude()) { for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
@ -1546,38 +1633,38 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
addServerValidationParameters(vs, pin, options); addServerValidationParameters(tc, vs, pin, options);
if (txLog != null) { if (txLog != null) {
txLog.clearLastId(); txLog.clearLastId();
} }
if (tcc.getClient() == null) { if (tc == null) {
throw new FHIRException(formatMessage(I18nConstants.ATTEMPT_TO_USE_TERMINOLOGY_SERVER_WHEN_NO_TERMINOLOGY_SERVER_IS_AVAILABLE)); throw new FHIRException(formatMessage(I18nConstants.ATTEMPT_TO_USE_TERMINOLOGY_SERVER_WHEN_NO_TERMINOLOGY_SERVER_IS_AVAILABLE));
} }
Parameters pOut; Parameters pOut;
if (vs == null) { if (vs == null) {
pOut = tcc.getClient().validateCS(pin); pOut = tc.getClient().validateCS(pin);
} else { } else {
pOut = tcc.getClient().validateVS(pin); pOut = tc.getClient().validateVS(pin);
} }
return processValidationResult(pOut, vs == null ? null : vs.getUrl(), tcc.getClient().getAddress()); return processValidationResult(pOut, vs == null ? null : vs.getUrl(), tc.getClient().getAddress());
} }
protected void addServerValidationParameters(ValueSet vs, Parameters pin, ValidationOptions options) { protected void addServerValidationParameters(TerminologyClientContext tcd, ValueSet vs, Parameters pin, ValidationOptions options) {
boolean cache = false; boolean cache = false;
if (vs != null) { if (vs != null) {
if (tcc.isTxCaching() && tcc.getCacheId() != null && vs.getUrl() != null && tcc.getCached().contains(vs.getUrl()+"|"+ vs.getVersion())) { if (tcc.isTxCaching() && tcc.getCacheId() != null && vs.getUrl() != null && tcd.getCached().contains(vs.getUrl()+"|"+ vs.getVersion())) {
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()+(vs.hasVersion() ? "|"+ vs.getVersion() : ""))); pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()+(vs.hasVersion() ? "|"+ vs.getVersion() : "")));
} else if (options.getVsAsUrl()){ } else if (options.getVsAsUrl()){
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl())); pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()));
} else { } else {
pin.addParameter().setName("valueSet").setResource(vs); pin.addParameter().setName("valueSet").setResource(vs);
if (vs.getUrl() != null) { if (vs.getUrl() != null) {
tcc.getCached().add(vs.getUrl()+"|"+ vs.getVersion()); tcd.getCached().add(vs.getUrl()+"|"+ vs.getVersion());
} }
} }
cache = true; cache = true;
addDependentResources(pin, vs); addDependentResources(tcd, pin, vs);
} }
pin.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId())); pin.addParameter().setName("cache-id").setValue(new IdType(tcc.getCacheId()));
for (ParametersParameterComponent pp : pin.getParameter()) { for (ParametersParameterComponent pp : pin.getParameter()) {
@ -1595,40 +1682,40 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
private boolean addDependentResources(Parameters pin, ValueSet vs) { private boolean addDependentResources(TerminologyClientContext tc, Parameters pin, ValueSet vs) {
boolean cache = false; boolean cache = false;
for (ConceptSetComponent inc : vs.getCompose().getInclude()) { for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
cache = addDependentResources(pin, inc, vs) || cache; cache = addDependentResources(tc, pin, inc, vs) || cache;
} }
for (ConceptSetComponent inc : vs.getCompose().getExclude()) { for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
cache = addDependentResources(pin, inc, vs) || cache; cache = addDependentResources(tc, pin, inc, vs) || cache;
} }
return cache; return cache;
} }
private boolean addDependentResources(Parameters pin, ConceptSetComponent inc, Resource src) { private boolean addDependentResources(TerminologyClientContext tc, Parameters pin, ConceptSetComponent inc, Resource src) {
boolean cache = false; boolean cache = false;
for (CanonicalType c : inc.getValueSet()) { for (CanonicalType c : inc.getValueSet()) {
ValueSet vs = fetchResource(ValueSet.class, c.getValue(), src); ValueSet vs = fetchResource(ValueSet.class, c.getValue(), src);
if (vs != null && !hasCanonicalResource(pin, "tx-resource", vs.getVUrl())) { if (vs != null && !hasCanonicalResource(pin, "tx-resource", vs.getVUrl())) {
cache = checkAddToParams(pin, vs) || cache; cache = checkAddToParams(tc, pin, vs) || cache;
addDependentResources(pin, vs); addDependentResources(tc, pin, vs);
} }
} }
CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem(), src); CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem(), src);
if (cs != null && !hasCanonicalResource(pin, "tx-resource", cs.getVUrl()) && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) { if (cs != null && !hasCanonicalResource(pin, "tx-resource", cs.getVUrl()) && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
cache = checkAddToParams(pin, cs) || cache; cache = checkAddToParams(tc, pin, cs) || cache;
// todo: supplements // todo: supplements
} }
return cache; return cache;
} }
private boolean checkAddToParams(Parameters pin, CanonicalResource cr) { private boolean checkAddToParams(TerminologyClientContext tc, Parameters pin, CanonicalResource cr) {
boolean cache = false; boolean cache = false;
boolean addToParams = false; boolean addToParams = false;
if (tcc.usingCache()) { if (tcc.usingCache()) {
if (!tcc.alreadyCached(cr)) { if (!tc.alreadyCached(cr)) {
tcc.addToCache(cr); tc.addToCache(cr);
if (logger.isDebugLogging()) { if (logger.isDebugLogging()) {
logger.logMessage("add to cache: "+cr.getVUrl()); logger.logMessage("add to cache: "+cr.getVUrl());
} }
@ -1782,6 +1869,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
Utilities.createDirectory(cachePath); Utilities.createDirectory(cachePath);
} }
txCache = new TerminologyCache(lock, cachePath); txCache = new TerminologyCache(lock, cachePath);
tcc.setCache(txCache);
} }
public void clearTSCache(String url) throws Exception { public void clearTSCache(String url) throws Exception {
@ -1814,7 +1902,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
@Override @Override
public boolean isNoTerminologyServer() { public boolean isNoTerminologyServer() {
return noTerminologyServer || tcc.getClient() == null; return noTerminologyServer || !tcc.hasClient();
} }
public void setNoTerminologyServer(boolean noTerminologyServer) { public void setNoTerminologyServer(boolean noTerminologyServer) {
@ -2860,6 +2948,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
} }
codeSystems.setVersion(version); codeSystems.setVersion(version);
valueSets.setVersion(version); valueSets.setVersion(version);
maps.setVersion(version); maps.setVersion(version);
@ -2890,18 +2979,16 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
public int getClientRetryCount() { public int getClientRetryCount() {
return tcc.getClient() == null ? 0 : tcc.getClient().getRetryCount(); return tcc.getRetryCount();
} }
public IWorkerContext setClientRetryCount(int value) { public IWorkerContext setClientRetryCount(int value) {
if (tcc.getClient() != null) { tcc.setRetryCount(value);
tcc.getClient().setRetryCount(value);
}
return this; return this;
} }
public ITerminologyClient getTxClient() { public TerminologyClientManager getTxClientManager() {
return tcc.getClient(); return tcc;
} }
public String getCacheId() { public String getCacheId() {
@ -2959,8 +3046,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected void setUserAgent(String userAgent) { protected void setUserAgent(String userAgent) {
this.userAgent = userAgent; this.userAgent = userAgent;
if (tcc.getClient() != null) tcc.setUserAgent(userAgent);
tcc.getClient().setUserAgent(userAgent);
} }

View File

@ -8,6 +8,7 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.utilities.npm.NpmPackage; import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation; import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
@ -89,6 +90,11 @@ public interface IContextResourceLoader {
*/ */
IContextResourceLoader setLoadProfiles(boolean value); IContextResourceLoader setLoadProfiles(boolean value);
/**
* @return the terminology client factory
*/
ITerminologyClientFactory txFactory();
/** /**
* Called during the loading process - the loader can decide which resources to load. * Called during the loading process - the loader can decide which resources to load.
* At this point, only the .index.json is being read * At this point, only the .index.json is being read

View File

@ -68,6 +68,9 @@ import org.hl7.fhir.r5.profilemodel.PEBuilder;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities; import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient; import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.R5Hacker; import org.hl7.fhir.r5.utils.R5Hacker;
import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager;
@ -248,6 +251,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
public SimpleWorkerContext fromPackage(NpmPackage pi) throws IOException, FHIRException { public SimpleWorkerContext fromPackage(NpmPackage pi) throws IOException, FHIRException {
SimpleWorkerContext context = getSimpleWorkerContextInstance(); SimpleWorkerContext context = getSimpleWorkerContextInstance();
context.setAllowLoadingDuplicates(allowLoadingDuplicates); context.setAllowLoadingDuplicates(allowLoadingDuplicates);
context.tcc = new TerminologyClientManager(TerminologyClientR5.factory());
context.loadFromPackage(pi, null); context.loadFromPackage(pi, null);
return build(context); return build(context);
} }
@ -256,6 +260,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
SimpleWorkerContext context = getSimpleWorkerContextInstance(); SimpleWorkerContext context = getSimpleWorkerContextInstance();
context.setAllowLoadingDuplicates(allowLoadingDuplicates); context.setAllowLoadingDuplicates(allowLoadingDuplicates);
context.version = pi.getNpm().asString("version"); context.version = pi.getNpm().asString("version");
context.tcc.setFactory(loader.txFactory());
context.loadFromPackage(pi, loader); context.loadFromPackage(pi, loader);
context.finishLoading(genSnapshots); context.finishLoading(genSnapshots);
return build(context); return build(context);
@ -327,22 +332,23 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
loadBytes(name, stream); loadBytes(name, stream);
} }
public String connectToTSServer(ITerminologyClient client, String log) { public String connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client, String log) {
try { try {
txLog("Connect to "+client.getAddress()); txLog("Connect to "+client.getAddress());
tcc.setClient(client); tcc.setFactory(factory);
tcc.setMasterClient(client);
if (log != null && (log.endsWith(".htm") || log.endsWith(".html"))) { if (log != null && (log.endsWith(".htm") || log.endsWith(".html"))) {
txLog = new HTMLClientLogger(log); txLog = new HTMLClientLogger(log);
} else { } else {
txLog = new TextClientLogger(log); txLog = new TextClientLogger(log);
} }
tcc.getClient().setLogger(txLog); tcc.setLogger(txLog);
tcc.getClient().setUserAgent(userAgent); tcc.setUserAgent(userAgent);
final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : tcc.getClient().getCapabilitiesStatementQuick(); final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : tcc.getMasterClient().getCapabilitiesStatementQuick();
txCache.cacheCapabilityStatement(capabilitiesStatementQuick); txCache.cacheCapabilityStatement(capabilitiesStatementQuick);
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : tcc.getClient().getTerminologyCapabilities(); final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : tcc.getMasterClient().getTerminologyCapabilities();
txCache.cacheTerminologyCapabilities(capabilityStatement); txCache.cacheTerminologyCapabilities(capabilityStatement);
setTxCaps(capabilityStatement); setTxCaps(capabilityStatement);
@ -532,6 +538,9 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
version = "5.0.0"; version = "5.0.0";
} }
} }
if (loader != null) {
tcc.setFactory(loader.txFactory());
}
return t; return t;
} }

View File

@ -68,4 +68,5 @@ public interface ITerminologyClient {
ITerminologyClient setAcceptLanguage(String lang); ITerminologyClient setAcceptLanguage(String lang);
ITerminologyClient setContentLanguage(String lang); ITerminologyClient setContentLanguage(String lang);
String getUserAgent(); String getUserAgent();
int getUseCount();
} }

View File

@ -1,65 +1,70 @@
package org.hl7.fhir.r5.terminologies.client; package org.hl7.fhir.r5.terminologies.client;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.TerminologyCapabilities; import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseCount;
public class TerminologyClientContext { public class TerminologyClientContext {
private String cacheId; public class TerminologyClientContextUseCount {
private boolean isTxCaching; private int expands;
private int serverQueryCount = 0; private int validates;
private final Set<String> cached = new HashSet<>(); public int getExpands() {
protected String server; return expands;
}
public void setExpands(int expands) {
this.expands = expands;
}
public int getValidates() {
return validates;
}
public void setValidates(int validates) {
this.validates = validates;
}
}
private ITerminologyClient client; private ITerminologyClient client;
Map<String, TerminologyClientContextUseCount> useCounts = new HashMap<>();
private TerminologyCapabilities txcaps; private TerminologyCapabilities txcaps;
private final Set<String> cached = new HashSet<>();
private boolean master;
public String getCacheId() { protected TerminologyClientContext(ITerminologyClient client, boolean master) {
return cacheId; super();
} this.client = client;
this.master = master;
public void setCacheId(String cacheId) {
this.cacheId = cacheId;
}
public boolean isTxCaching() {
return isTxCaching;
}
public void setTxCaching(boolean isTxCaching) {
this.isTxCaching = isTxCaching;
}
public int getServerQueryCount() {
return serverQueryCount;
}
public void setServerQueryCount(int serverQueryCount) {
this.serverQueryCount = serverQueryCount;
}
public Set<String> getCached() {
return cached;
} }
public String getServer() { public Map<String, TerminologyClientContextUseCount> getUseCounts() {
return server; return useCounts;
} }
public void setServer(String server) { public boolean isMaster() {
this.server = server; return master;
} }
public ITerminologyClient getClient() { public ITerminologyClient getClient() {
return client; return client;
} }
public void setClient(ITerminologyClient client) { public void seeUse(String s, boolean expand) {
this.client = client; TerminologyClientContextUseCount uc = useCounts.get(s);
if (uc == null) {
uc = new TerminologyClientContextUseCount();
useCounts.put(s,uc);
}
if (expand) {
uc.expands++;
} else {
uc.validates++;
}
} }
public TerminologyCapabilities getTxcaps() { public TerminologyCapabilities getTxcaps() {
return txcaps; return txcaps;
} }
@ -68,18 +73,8 @@ public class TerminologyClientContext {
this.txcaps = txcaps; this.txcaps = txcaps;
} }
public void copy(TerminologyClientContext other) { public Set<String> getCached() {
cacheId = other.cacheId; return cached;
isTxCaching = other.isTxCaching;
cached.addAll(other.cached);
// tsServer = other.tsServer;
client = other.client;
txcaps = other.txcaps;
}
public boolean usingCache() {
return isTxCaching && cacheId != null;
} }
public boolean alreadyCached(CanonicalResource cr) { public boolean alreadyCached(CanonicalResource cr) {
@ -90,6 +85,12 @@ public class TerminologyClientContext {
cached.add(cr.getVUrl()); cached.add(cr.getVUrl());
} }
public String getAddress() {
return client.getAddress();
}
public int getUseCount() {
return getClient().getUseCount();
}
} }

View File

@ -0,0 +1,266 @@
package org.hl7.fhir.r5.terminologies.client;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.parser.JsonParser;
public class TerminologyClientManager {
public ITerminologyClientFactory getFactory() {
return factory;
}
public interface ITerminologyClientFactory {
ITerminologyClient makeClient(String id, String url, String userAgent) throws URISyntaxException;
String getVersion();
}
public static final String UNRESOLVED_VALUESET = "--unknown--";
private ITerminologyClientFactory factory;
private String cacheId;
private boolean isTxCaching;
private List<TerminologyClientContext> serverList = new ArrayList<>(); // clients by server address
private Map<String, TerminologyClientContext> serverMap = new HashMap<>(); // clients by server address
private Map<String, String> resMap = new HashMap<>(); // client resolution list
private List<String> internalErrors = new ArrayList<>();
private TerminologyCache cache;
private File cacheFile;
private String monitorServiceURL;
public TerminologyClientManager(ITerminologyClientFactory factory) {
super();
this.factory = factory;
}
public String getCacheId() {
return cacheId;
}
public void setCacheId(String cacheId) {
this.cacheId = cacheId;
}
public boolean isTxCaching() {
return isTxCaching;
}
public void setTxCaching(boolean isTxCaching) {
this.isTxCaching = isTxCaching;
}
public void copy(TerminologyClientManager other) {
cacheId = other.cacheId;
isTxCaching = other.isTxCaching;
serverList.addAll(other.serverList);
serverMap.putAll(other.serverMap);
resMap.putAll(other.resMap);
}
public boolean usingCache() {
return isTxCaching && cacheId != null;
}
public TerminologyClientContext chooseServer(Set<String> systems, boolean expand) throws TerminologyServiceException {
if (serverList.isEmpty()) {
return null;
}
if (systems.contains(UNRESOLVED_VALUESET)) {
return serverList.get(0);
}
Set<TerminologyClientContext> clients = new HashSet<>();
for (String s : systems) {
clients.add(findServerForSystem(s, expand));
}
if (clients.size() == 1) {
return clients.iterator().next();
} else {
System.out.println("systems: "+systems.toString());
return serverList.get(0);
}
}
private TerminologyClientContext findServerForSystem(String s, boolean expand) throws TerminologyServiceException {
String server = resMap.get(s);
if (server == null) {
server = decideWhichServer(s);
resMap.put(s, server);
save();
}
TerminologyClientContext client = serverMap.get(server);
if (client == null) {
try {
client = new TerminologyClientContext(factory.makeClient("id"+(serverList.size()+1), server, getMasterClient().getUserAgent()), false);
} catch (URISyntaxException e) {
throw new TerminologyServiceException(e);
}
serverList.add(client);
serverMap.put(server, client);
}
client.seeUse(s, expand);
return client;
}
private String decideWhichServer(String url) {
String request = Utilities.pathURL(monitorServiceURL, "resolve?fhirVersion="+factory.getVersion()+"&url="+url);
try {
JsonObject json = JsonParser.parseObjectFromUrl(request);
for (JsonObject item : json.getJsonObjects("authoritative")) {
return item.asString("url");
}
for (JsonObject item : json.getJsonObjects("candidate")) {
return item.asString("url");
}
} catch (Exception e) {
String msg = "Error resolving system "+url+": "+e.getMessage()+" ("+request+")";
if (!internalErrors.contains(msg)) {
internalErrors.add(msg);
}
e.printStackTrace();
}
return getMasterClient().getAddress();
}
public List<TerminologyClientContext> serverList() {
return serverList;
}
public boolean hasClient() {
return !serverList.isEmpty();
}
public int getRetryCount() {
return hasClient() ? getMasterClient().getRetryCount() : 0;
}
public void setRetryCount(int value) {
if (hasClient()) {
getMasterClient().setRetryCount(value);
}
}
public void setUserAgent(String value) {
if (hasClient()) {
getMasterClient().setUserAgent(value);
}
}
public void setLogger(ToolingClientLogger txLog) {
if (hasClient()) {
getMasterClient().setLogger(txLog);
}
}
public void setMasterClient(ITerminologyClient client) {
TerminologyClientContext details = new TerminologyClientContext(client, true);
serverList.clear();
serverList.add(details);
serverMap.put(client.getAddress(), details);
monitorServiceURL = Utilities.pathURL(Utilities.getDirectoryForURL(client.getAddress()), "tx-reg");
}
public TerminologyClientContext getMaster() {
return serverList.isEmpty() ? null : serverList.get(0);
}
public ITerminologyClient getMasterClient() {
return serverList.isEmpty() ? null : serverList.get(0).getClient();
}
public Map<String, TerminologyClientContext> serverMap() {
Map<String, TerminologyClientContext> map = new HashMap<>();
for (TerminologyClientContext t : serverList) {
map.put(t.getClient().getAddress(), t);
}
return map;
}
public TerminologyCapabilities getTxcaps() {
return hasClient() ? serverList.get(0).getTxcaps() : null;
}
public void setTxcaps(TerminologyCapabilities txCaps) {
serverList.get(0).setTxcaps(txCaps);
}
public void setFactory(ITerminologyClientFactory factory) {
this.factory = factory;
}
public void setCache(TerminologyCache cache) {
this.cache = cache;
this.cacheFile = null;
if (cache != null) {
try {
cacheFile = new File(Utilities.path(cache.getFolder(), "system-map.json"));
if (cacheFile.exists()) {
JsonObject json = JsonParser.parseObject(cacheFile);
for (JsonObject pair : json.getJsonObjects("systems")) {
resMap.put(pair.asString("system"), pair.asString("server"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void save() {
if (cacheFile != null) {
JsonObject json = new JsonObject();
for (String s : Utilities.sorted(resMap.keySet())) {
JsonObject si = new JsonObject();
json.forceArray("systems").add(si);
si.add("system", s);
si.add("server", resMap.get(s));
}
try {
JsonParser.compose(json, cacheFile, true);
} catch (IOException e) {
}
}
}
public List<String> getInternalErrors() {
return internalErrors;
}
public List<TerminologyClientContext> getServerList() {
return serverList;
}
public Map<String, TerminologyClientContext> getServerMap() {
return serverMap;
}
public String getMonitorServiceURL() {
return monitorServiceURL;
}
}

View File

@ -1,4 +1,4 @@
package org.hl7.fhir.convertors.txClient; package org.hl7.fhir.r5.terminologies.client;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.EnumSet; import java.util.EnumSet;
@ -44,6 +44,8 @@ import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.TerminologyCapabilities; import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient; import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5.TerminologyClientR5Factory;
import org.hl7.fhir.r5.utils.client.FHIRToolingClient; import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
import org.hl7.fhir.r5.utils.client.network.ClientHeaders; import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.utilities.FhirPublication; import org.hl7.fhir.utilities.FhirPublication;
@ -52,6 +54,28 @@ import org.hl7.fhir.utilities.Utilities;
public class TerminologyClientR5 implements ITerminologyClient { public class TerminologyClientR5 implements ITerminologyClient {
public static class TerminologyClientR5Factory implements ITerminologyClientFactory {
@Override
public ITerminologyClient makeClient(String id, String url, String userAgent) throws URISyntaxException {
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent);
}
private String checkEndsWith(String term, String url) {
if (url.endsWith(term))
return url;
if (Utilities.isTxFhirOrgServer(url)) {
return Utilities.pathURL(url, term);
}
return url;
}
@Override
public String getVersion() {
return "5.0.0";
}
}
private final FHIRToolingClient client; private final FHIRToolingClient client;
private ClientHeaders clientHeaders; private ClientHeaders clientHeaders;
private String id; private String id;
@ -211,4 +235,14 @@ public class TerminologyClientR5 implements ITerminologyClient {
client.setContentLanguage(lang); client.setContentLanguage(lang);
return this; return this;
} }
@Override
public int getUseCount() {
return client.getUseCount();
}
public static ITerminologyClientFactory factory() {
return new TerminologyClientR5Factory();
}
} }

View File

@ -1,6 +1,6 @@
package org.hl7.fhir.r5.test.utils; package org.hl7.fhir.r5.test.utils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -12,6 +12,8 @@ import org.hl7.fhir.r5.formats.XmlParser;
import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ITerminologyClientFactory;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientR5.TerminologyClientR5Factory;
import org.hl7.fhir.utilities.npm.NpmPackage; import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation; import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
@ -73,4 +75,9 @@ public class TestPackageLoader implements IContextResourceLoader {
return true; return true;
} }
@Override
public ITerminologyClientFactory txFactory() {
return new TerminologyClientR5Factory();
}
} }

View File

@ -106,6 +106,9 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
private String acceptLang; private String acceptLang;
private String contentLang; private String contentLang;
private int useCount;
//Pass endpoint for client - URI //Pass endpoint for client - URI
public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException { public FHIRToolingClient(String baseServiceUrl, String userAgent) throws URISyntaxException {
preferredResourceFormat = ResourceFormat.RESOURCE_JSON; preferredResourceFormat = ResourceFormat.RESOURCE_JSON;
@ -206,6 +209,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource
recordUse();
ResourceRequest<Resource> result = null; ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -223,6 +227,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
public <T extends Resource> T read(Class<T> resourceClass, String id) {//TODO Change this to AddressableResource public <T extends Resource> T read(Class<T> resourceClass, String id) {//TODO Change this to AddressableResource
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -240,6 +245,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) { public <T extends Resource> T vread(Class<T> resourceClass, String id, String version) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version),
@ -257,6 +263,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) { public <T extends Resource> T getCanonical(Class<T> resourceClass, String canonicalURL) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL),
@ -279,6 +286,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Resource update(Resource resource) { public Resource update(Resource resource) {
recordUse();
org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()), result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),
@ -306,6 +314,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) { public <T extends Resource> T update(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
@ -333,6 +342,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) { public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) {
recordUse();
boolean complex = false; boolean complex = false;
for (ParametersParameterComponent p : params.getParameter()) for (ParametersParameterComponent p : params.getParameter())
complex = complex || !(p.getValue() instanceof PrimitiveType); complex = complex || !(p.getValue() instanceof PrimitiveType);
@ -368,6 +378,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle transaction(Bundle batch) { public Bundle transaction(Bundle batch) {
recordUse();
Bundle transactionResult = null; Bundle transactionResult = null;
try { try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(),
@ -381,6 +392,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) { public <T extends Resource> OperationOutcome validate(Class<T> resourceClass, T resource, String id) {
recordUse();
ResourceRequest<T> result = null; ResourceRequest<T> result = null;
try { try {
result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
@ -426,6 +438,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle fetchFeed(String url) { public Bundle fetchFeed(String url) {
recordUse();
Bundle feed = null; Bundle feed = null;
try { try {
feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat()); feed = client.issueGetFeedRequest(new URI(url), getPreferredResourceFormat());
@ -436,6 +449,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams) { public ValueSet expandValueset(ValueSet source, Parameters expParams) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null;
@ -457,6 +471,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
public Parameters lookupCode(Map<String, String> params) { public Parameters lookupCode(Map<String, String> params) {
recordUse();
org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), result = client.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params),
@ -474,6 +489,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) { public ValueSet expandValueset(ValueSet source, Parameters expParams, Map<String, String> params) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy(); Parameters p = expParams == null ? new Parameters() : expParams.copy();
if (source != null) { if (source != null) {
p.addParameter().setName("valueSet").setResource(source); p.addParameter().setName("valueSet").setResource(source);
@ -507,6 +523,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap initializeClosure(String name) { public ConceptMap initializeClosure(String name) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
ResourceRequest<Resource> result = null; ResourceRequest<Resource> result = null;
@ -527,6 +544,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public ConceptMap updateClosure(String name, Coding coding) { public ConceptMap updateClosure(String name, Coding coding) {
recordUse();
Parameters params = new Parameters(); Parameters params = new Parameters();
params.addParameter().setName("name").setValue(new StringType(name)); params.addParameter().setName("name").setValue(new StringType(name));
params.addParameter().setName("concept").setValue(coding); params.addParameter().setName("concept").setValue(coding);
@ -654,10 +672,12 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
public Bundle search(String type, String criteria) { public Bundle search(String type, String criteria) {
recordUse();
return fetchFeed(Utilities.pathURL(base, type+criteria)); return fetchFeed(Utilities.pathURL(base, type+criteria));
} }
public <T extends Resource> T fetchResource(Class<T> resourceClass, String id) { public <T extends Resource> T fetchResource(Class<T> resourceClass, String id) {
recordUse();
org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null; org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null;
try { try {
result = client.issueGetResourceRequest(resourceAddress.resolveGetResource(resourceClass, id), result = client.issueGetResourceRequest(resourceAddress.resolveGetResource(resourceClass, id),
@ -671,6 +691,14 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
} }
return (T) result.getPayload(); return (T) result.getPayload();
} }
private void recordUse() {
useCount++;
}
public int getUseCount() {
return useCount;
}
} }

View File

@ -94,7 +94,7 @@ public class BaseWorkerContextTests {
public void testAddServerValidationParametersDisplayWarning() throws IOException { public void testAddServerValidationParametersDisplayWarning() throws IOException {
BaseWorkerContext baseWorkerContext = getBaseWorkerContext(); BaseWorkerContext baseWorkerContext = getBaseWorkerContext();
Parameters pin = new Parameters(); Parameters pin = new Parameters();
baseWorkerContext.addServerValidationParameters(new ValueSet(), pin, new ValidationOptions(FhirPublication.fromCode(baseWorkerContext.getVersion())).setDisplayWarningMode(true)); baseWorkerContext.addServerValidationParameters(baseWorkerContext.getTxClientManager().getMaster(), new ValueSet(), pin, new ValidationOptions(FhirPublication.fromCode(baseWorkerContext.getVersion())).setDisplayWarningMode(true));
assertEquals("lenient-display-validation", pin.getParameter("mode").getValue().primitiveValue()); assertEquals("lenient-display-validation", pin.getParameter("mode").getValue().primitiveValue());
} }
@ -102,7 +102,7 @@ public class BaseWorkerContextTests {
public void testAddServerValidationParametersVsAsUrl() throws IOException { public void testAddServerValidationParametersVsAsUrl() throws IOException {
BaseWorkerContext baseWorkerContext = getBaseWorkerContext(); BaseWorkerContext baseWorkerContext = getBaseWorkerContext();
Parameters pin = new Parameters(); Parameters pin = new Parameters();
baseWorkerContext.addServerValidationParameters(new ValueSet().setUrl("http://dummy.org/vs"), pin, new ValidationOptions(FhirPublication.fromCode(baseWorkerContext.getVersion())).setVsAsUrl(true)); baseWorkerContext.addServerValidationParameters(baseWorkerContext.getTxClientManager().getMaster(), new ValueSet().setUrl("http://dummy.org/vs"), pin, new ValidationOptions(FhirPublication.fromCode(baseWorkerContext.getVersion())).setVsAsUrl(true));
assertEquals("uri", pin.getParameter("url").getValue().fhirType()); assertEquals("uri", pin.getParameter("url").getValue().fhirType());
assertEquals("http://dummy.org/vs", pin.getParameter("url").getValue().primitiveValue()); assertEquals("http://dummy.org/vs", pin.getParameter("url").getValue().primitiveValue());
} }
@ -112,7 +112,7 @@ public class BaseWorkerContextTests {
BaseWorkerContext baseWorkerContext = getBaseWorkerContext(); BaseWorkerContext baseWorkerContext = getBaseWorkerContext();
Parameters pin = new Parameters(); Parameters pin = new Parameters();
baseWorkerContext.addServerValidationParameters(new ValueSet(), pin, new ValidationOptions(FhirPublication.fromCode(baseWorkerContext.getVersion()))); baseWorkerContext.addServerValidationParameters(baseWorkerContext.getTxClientManager().getMaster(), new ValueSet(), pin, new ValidationOptions(FhirPublication.fromCode(baseWorkerContext.getVersion())));
assertNull(pin.getParameter("mode")); assertNull(pin.getParameter("mode"));
} }
} }

View File

@ -93,7 +93,7 @@ public class SimpleWorkerContextTests {
public void beforeEach() { public void beforeEach() {
context.txCache = terminologyCache; context.txCache = terminologyCache;
context.expParameters = expParameters; context.expParameters = expParameters;
context.tcc.setClient(terminologyClient); context.tcc.setMasterClient(terminologyClient);
context.txLog = txLog; context.txLog = txLog;
} }
@ -189,7 +189,7 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, coding, valueSet, expParameters); Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, coding, valueSet, expParameters);
Mockito.doReturn(pIn).when(context).constructParameters(validationOptions, coding); Mockito.doReturn(pIn).when(context).constructParameters(validationOptions, coding);
Mockito.doReturn(expectedValidationResult).when(context).validateOnServer(valueSet, pIn, validationOptions); Mockito.doReturn(expectedValidationResult).when(context).validateOnServer(context.getTxClientManager().getMaster(), valueSet, pIn, validationOptions);
ValidationContextCarrier ctxt = mock(ValidationContextCarrier.class); ValidationContextCarrier ctxt = mock(ValidationContextCarrier.class);
@ -233,7 +233,7 @@ public class SimpleWorkerContextTests {
Mockito.verify(valueSetCheckerSimple).validateCode("CodeableConcept", codeableConcept); Mockito.verify(valueSetCheckerSimple).validateCode("CodeableConcept", codeableConcept);
Mockito.verify(terminologyCache).cacheValidation(cacheToken, expectedValidationResult, false); Mockito.verify(terminologyCache).cacheValidation(cacheToken, expectedValidationResult, false);
Mockito.verify(context, times(0)).validateOnServer(any(), any(), any()); Mockito.verify(context, times(0)).validateOnServer(context.getTxClientManager().getMaster(), any(), any(), any());
} }
@ -246,7 +246,7 @@ public class SimpleWorkerContextTests {
ValidationOptions validationOptions = CacheTestUtils.validationOptions.withNoClient(); ValidationOptions validationOptions = CacheTestUtils.validationOptions.withNoClient();
Mockito.doReturn(pIn).when(context).constructParameters(validationOptions, codeableConcept); Mockito.doReturn(pIn).when(context).constructParameters(validationOptions, codeableConcept);
Mockito.doReturn(expectedValidationResult).when(context).validateOnServer(valueSet, pIn, validationOptions); Mockito.doReturn(expectedValidationResult).when(context).validateOnServer(context.getTxClientManager().getMaster(), valueSet, pIn, validationOptions);
Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, codeableConcept, valueSet, expParameters); Mockito.doReturn(cacheToken).when(terminologyCache).generateValidationToken(validationOptions, codeableConcept, valueSet, expParameters);
@ -256,7 +256,7 @@ public class SimpleWorkerContextTests {
Mockito.verify(valueSetCheckerSimple, times(0)).validateCode("CodeableConcept", codeableConcept); Mockito.verify(valueSetCheckerSimple, times(0)).validateCode("CodeableConcept", codeableConcept);
Mockito.verify(terminologyCache).cacheValidation(cacheToken, expectedValidationResult, true); Mockito.verify(terminologyCache).cacheValidation(cacheToken, expectedValidationResult, true);
Mockito.verify(context).validateOnServer(valueSet, pIn, validationOptions); Mockito.verify(context).validateOnServer(context.getTxClientManager().getMaster(),valueSet, pIn, validationOptions);
} }
@Test @Test
@ -295,7 +295,8 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(cacheToken).when(terminologyCache).generateExpandToken(argThat(new ValueSetMatcher(vs)),eq(true)); Mockito.doReturn(cacheToken).when(terminologyCache).generateExpandToken(argThat(new ValueSetMatcher(vs)),eq(true));
Mockito.doReturn(expParameters).when(context).constructParameters(argThat(new ValueSetMatcher(vs)), eq(true)); // #FIXME
// Mockito.doReturn(expParameters).when(context).constructParameters(argThat(new ValueSetMatcher(vs)), eq(true));
ValueSet expectedValueSet = new ValueSet(); ValueSet expectedValueSet = new ValueSet();
@ -408,7 +409,7 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(terminologyCapabilities).when(terminologyCache).getTerminologyCapabilities(); Mockito.doReturn(terminologyCapabilities).when(terminologyCache).getTerminologyCapabilities();
Mockito.doReturn(capabilitiesStatement).when(terminologyCache).getCapabilityStatement(); Mockito.doReturn(capabilitiesStatement).when(terminologyCache).getCapabilityStatement();
String actual = context.connectToTSServer(terminologyClient, null); String actual = context.connectToTSServer(null, terminologyClient, null);
assertEquals("dummyVersion", actual); assertEquals("dummyVersion", actual);
@ -430,7 +431,7 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(terminologyCapabilities).when(terminologyClient).getTerminologyCapabilities(); Mockito.doReturn(terminologyCapabilities).when(terminologyClient).getTerminologyCapabilities();
Mockito.doReturn(capabilitiesStatement).when(terminologyClient).getCapabilitiesStatementQuick(); Mockito.doReturn(capabilitiesStatement).when(terminologyClient).getCapabilitiesStatementQuick();
String actual = context.connectToTSServer(terminologyClient, null); String actual = context.connectToTSServer(null, terminologyClient, null);
assertEquals("dummyVersion", actual); assertEquals("dummyVersion", actual);

View File

@ -750,6 +750,10 @@ public class Utilities {
return f.getParent(); return f.getParent();
} }
public static String getDirectoryForURL(String url) {
return url.contains("/") && url.lastIndexOf("/") > 10 ? url.substring(0, url.lastIndexOf("/")) : url;
}
public static String appendPeriod(String s) { public static String appendPeriod(String s) {
if (Utilities.noString(s)) if (Utilities.noString(s))
return s; return s;

View File

@ -672,7 +672,8 @@ public class JsonParser {
private static byte[] fetch(String source) throws IOException { private static byte[] fetch(String source) throws IOException {
SimpleHTTPClient fetcher = new SimpleHTTPClient(); SimpleHTTPClient fetcher = new SimpleHTTPClient();
fetcher.addHeader("Accept", "application/json, application/fhir+json"); fetcher.addHeader("Accept", "application/json, application/fhir+json");
HTTPResult res = fetcher.get(source+"?nocache=" + System.currentTimeMillis()); String murl = source.contains("?") ? source+"&nocache=" + System.currentTimeMillis() : source+"?nocache=" + System.currentTimeMillis();
HTTPResult res = fetcher.get(murl);
res.checkThrowException(); res.checkThrowException();
return res.getContent(); return res.getContent();
} }

View File

@ -523,7 +523,8 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
return "n/a: No Terminology Server"; return "n/a: No Terminology Server";
} else { } else {
try { try {
return context.connectToTSServer(TerminologyClientFactory.makeClient("Tx-Server", url, context.getUserAgent(), version), log); TerminologyClientFactory factory = new TerminologyClientFactory(version);
return context.connectToTSServer(factory, factory.makeClient("Tx-Server", url, context.getUserAgent()), log);
} catch (Exception e) { } catch (Exception e) {
if (context.isCanRunWithoutTerminology()) { if (context.isCanRunWithoutTerminology()) {
return "n/a: Running without Terminology Server (error: " + e.getMessage() + ")"; return "n/a: Running without Terminology Server (error: " + e.getMessage() + ")";

View File

@ -289,7 +289,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV
@Nonnull @Nonnull
protected ITerminologyClient getTerminologyClient(String root) throws URISyntaxException { protected ITerminologyClient getTerminologyClient(String root) throws URISyntaxException {
return TerminologyClientFactory.makeClient("source", root, Common.getValidatorUserAgent(), context.getVersion()); return new TerminologyClientFactory(context.getVersion()).makeClient("source", root, Common.getValidatorUserAgent());
} }
private String getRoot(String[] p, String url) { private String getRoot(String[] p, String url) {

View File

@ -139,7 +139,7 @@ public class TxTester {
private ITerminologyClient connectToServer() throws URISyntaxException { private ITerminologyClient connectToServer() throws URISyntaxException {
System.out.println("Connect to "+server); System.out.println("Connect to "+server);
return TerminologyClientFactory.makeClient("Test-Server", server, "Tools/Java", FhirPublication.R4); return new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java");
} }

View File

@ -32,7 +32,7 @@ public class ValidationEngineTests {
System.out.println("TestCurrentXml: Validate patient-example.xml in Current version"); System.out.println("TestCurrentXml: Validate patient-example.xml in Current version");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, FhirPublication.R4, "4.0.1"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, FhirPublication.R4, "4.0.1");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient-example.xml"), null); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient-example.xml"), null);
int e = errors(op); int e = errors(op);
int w = warnings(op); int w = warnings(op);
@ -55,7 +55,7 @@ public class ValidationEngineTests {
System.out.println("TestCurrentJson: Validate patient-example.json in Current version"); System.out.println("TestCurrentJson: Validate patient-example.json in Current version");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, FhirPublication.R4, "4.0.1"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, FhirPublication.R4, "4.0.1");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "patient-example.json"), null); OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "patient-example.json"), null);
int e = errors(op); int e = errors(op);
int w = warnings(op); int w = warnings(op);
@ -74,7 +74,7 @@ public class ValidationEngineTests {
System.out.println("TestCurrentXml: Validate patient-example.xml in Current version"); System.out.println("TestCurrentXml: Validate patient-example.xml in Current version");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4b.core#4.3.0", DEF_TX, FhirPublication.R4, "4.3.0"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4b.core#4.3.0", DEF_TX, FhirPublication.R4, "4.3.0");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient-example.xml"), null); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient-example.xml"), null);
int e = errors(op); int e = errors(op);
int w = warnings(op); int w = warnings(op);
@ -97,7 +97,7 @@ public class ValidationEngineTests {
System.out.println("TestCurrentJson: Validate patient-example.json in Current version"); System.out.println("TestCurrentJson: Validate patient-example.json in Current version");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4b.core#4.3.0", DEF_TX, FhirPublication.R4, "4.3.0"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r4b.core#4.3.0", DEF_TX, FhirPublication.R4, "4.3.0");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "patient-example.json"), null); OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "patient-example.json"), null);
int e = errors(op); int e = errors(op);
int w = warnings(op); int w = warnings(op);
@ -126,7 +126,7 @@ public class ValidationEngineTests {
System.out.println("Test140: Validate patient-example.xml in v1.4.0 version"); System.out.println("Test140: Validate patient-example.xml in v1.4.0 version");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, FhirPublication.DSTU2016May, "1.4.0"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, FhirPublication.DSTU2016May, "1.4.0");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient140.xml"), null); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient140.xml"), null);
if (!TestUtilities.silent) if (!TestUtilities.silent)
for (OperationOutcomeIssueComponent iss : op.getIssue()) { for (OperationOutcomeIssueComponent iss : op.getIssue()) {
@ -154,7 +154,7 @@ public class ValidationEngineTests {
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, FhirPublication.DSTU2, "1.0.2"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, FhirPublication.DSTU2, "1.0.2");
ve.setNoInvariantChecks(true); ve.setNoInvariantChecks(true);
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient102.xml"), null); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient102.xml"), null);
if (!TestUtilities.silent) if (!TestUtilities.silent)
for (OperationOutcomeIssueComponent iss : op.getIssue()) { for (OperationOutcomeIssueComponent iss : op.getIssue()) {
@ -182,7 +182,7 @@ public class ValidationEngineTests {
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, FhirPublication.DSTU2, "1.0.2"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, FhirPublication.DSTU2, "1.0.2");
ve.setNoInvariantChecks(true); ve.setNoInvariantChecks(true);
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "observation102.json"), null); OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "observation102.json"), null);
if (!TestUtilities.silent) if (!TestUtilities.silent)
for (OperationOutcomeIssueComponent iss : op.getIssue()) { for (OperationOutcomeIssueComponent iss : op.getIssue()) {
@ -206,7 +206,7 @@ public class ValidationEngineTests {
System.out.println("Test301: Validate observation301.xml against Core"); System.out.println("Test301: Validate observation301.xml against Core");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, FhirPublication.STU3, "3.0.2"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, FhirPublication.STU3, "3.0.2");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
if (!TestUtilities.silent) if (!TestUtilities.silent)
System.out.println(" .. load USCore"); System.out.println(" .. load USCore");
OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "observation301.xml"), null); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "observation301.xml"), null);
@ -228,7 +228,7 @@ public class ValidationEngineTests {
System.out.println("Test301USCore: Validate patient300.xml against US-Core"); System.out.println("Test301USCore: Validate patient300.xml against US-Core");
ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, FhirPublication.STU3, "3.0.2"); ValidationEngine ve = TestUtilities.getValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, FhirPublication.STU3, "3.0.2");
CacheVerificationLogger logger = new CacheVerificationLogger(); CacheVerificationLogger logger = new CacheVerificationLogger();
ve.getContext().getTxClient().setLogger(logger); ve.getContext().getTxClientManager().getMasterClient().setLogger(logger);
IgLoader igLoader = new IgLoader(ve.getPcm(), ve.getContext(), ve.getVersion(), true); IgLoader igLoader = new IgLoader(ve.getPcm(), ve.getContext(), ve.getVersion(), true);
if (!TestUtilities.silent) if (!TestUtilities.silent)
System.out.println(" .. load USCore"); System.out.println(" .. load USCore");

View File

@ -199,7 +199,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
currentVersion = version; currentVersion = version;
} }
vCurr = CLONE ? new ValidationEngine(currentEngine) : currentEngine; vCurr = CLONE ? new ValidationEngine(currentEngine) : currentEngine;
vCurr.getContext().getTxClient().setLogger(logger); vCurr.getContext().getTxClientManager().getMasterClient().setLogger(logger);
igLoader = new IgLoader(vCurr.getPcm(), vCurr.getContext(), vCurr.getVersion(), true); igLoader = new IgLoader(vCurr.getPcm(), vCurr.getContext(), vCurr.getVersion(), true);
if (content.has("close-up")) { if (content.has("close-up")) {