rework terminology cache to manage multiple terminology servers
This commit is contained in:
parent
63c62bb80c
commit
8613cd3944
|
@ -6,6 +6,7 @@ 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.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
||||
|
@ -23,27 +24,28 @@ public class TerminologyClientFactory implements ITerminologyClientFactory {
|
|||
this.v = version;
|
||||
}
|
||||
|
||||
public ITerminologyClient makeClient(String id, String url, String userAgent) throws URISyntaxException {
|
||||
@Override
|
||||
public ITerminologyClient makeClient(String id, String url, String userAgent, ToolingClientLogger logger) throws URISyntaxException {
|
||||
if (v == null)
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent);
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent).setLogger(logger);
|
||||
v = VersionUtilities.getMajMin(v);
|
||||
if (VersionUtilities.isR2Ver(v)) {
|
||||
return new TerminologyClientR2(id, checkEndsWith("/r2", url), userAgent);
|
||||
return new TerminologyClientR2(id, checkEndsWith("/r2", url), userAgent).setLogger(logger);
|
||||
}
|
||||
if (VersionUtilities.isR2BVer(v)) {
|
||||
return new TerminologyClientR3(id, checkEndsWith("/r3", url), userAgent); // r3 is the least worst match
|
||||
return new TerminologyClientR3(id, checkEndsWith("/r3", url), userAgent).setLogger(logger); // r3 is the least worst match
|
||||
}
|
||||
if (VersionUtilities.isR3Ver(v)) {
|
||||
return new TerminologyClientR3(id, checkEndsWith("/r3", url), userAgent); // r3 is the least worst match
|
||||
return new TerminologyClientR3(id, checkEndsWith("/r3", url), userAgent).setLogger(logger); // r3 is the least worst match
|
||||
}
|
||||
if (VersionUtilities.isR4Ver(v)) {
|
||||
return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent);
|
||||
return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent).setLogger(logger);
|
||||
}
|
||||
if (VersionUtilities.isR4BVer(v)) {
|
||||
return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent);
|
||||
return new TerminologyClientR4(id, checkEndsWith("/r4", url), userAgent).setLogger(logger);
|
||||
}
|
||||
if (VersionUtilities.isR5Plus(v)) {
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent); // r4 for now, since the terminology is currently the same
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent).setLogger(logger); // r4 for now, since the terminology is currently the same
|
||||
}
|
||||
throw new Error("The version " + v + " is not currently supported");
|
||||
}
|
||||
|
|
|
@ -131,6 +131,11 @@ public class TerminologyClientR2 implements ITerminologyClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolingClientLogger getLogger() {
|
||||
return client.getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
|
|
|
@ -127,6 +127,11 @@ public class TerminologyClientR3 implements ITerminologyClient {
|
|||
client.setTimeoutFactor(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolingClientLogger getLogger() {
|
||||
return client.getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
|
|
|
@ -138,6 +138,11 @@ public class TerminologyClientR4 implements ITerminologyClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolingClientLogger getLogger() {
|
||||
return client.getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
|
|
|
@ -53,14 +53,14 @@ public class TerminologyClientFactoryTest {
|
|||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testMakeClient(String url, FhirPublication fhirPublication, String expectedAddress) throws URISyntaxException {
|
||||
ITerminologyClient terminologyClient = new TerminologyClientFactory(fhirPublication).makeClient("id", url, "dummyUserAgent");
|
||||
ITerminologyClient terminologyClient = new TerminologyClientFactory(fhirPublication).makeClient("id", url, "dummyUserAgent", null);
|
||||
assertEquals(expectedAddress, terminologyClient.getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMakeClientDstu1Fails() throws URISyntaxException {
|
||||
assertThrows(Error.class, () -> {
|
||||
ITerminologyClient terminologyClient = new TerminologyClientFactory(FhirPublication.DSTU1).makeClient("id", "urldoesnotmatter", "dummyUserAgent");
|
||||
ITerminologyClient terminologyClient = new TerminologyClientFactory(FhirPublication.DSTU1).makeClient("id", "urldoesnotmatter", "dummyUserAgent", null);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ public class TerminologyClientFactoryTest {
|
|||
@Test
|
||||
public void testMakeClientNullFails() throws URISyntaxException {
|
||||
assertThrows(Error.class, () -> {
|
||||
ITerminologyClient terminologyClient = new TerminologyClientFactory(FhirPublication.NULL).makeClient("id", "urldoesnotmatter", "dummyUserAgent");
|
||||
ITerminologyClient terminologyClient = new TerminologyClientFactory(FhirPublication.NULL).makeClient("id", "urldoesnotmatter", "dummyUserAgent", null);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -137,6 +138,7 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
|
|||
import org.hl7.fhir.r5.utils.client.EFhirClientException;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.TranslationServices;
|
||||
|
@ -232,7 +234,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
private Object lock = new Object(); // used as a lock for the data that follows
|
||||
protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be
|
||||
|
||||
protected TerminologyClientManager terminologyClientManager = new TerminologyClientManager(null);
|
||||
protected final TerminologyClientManager terminologyClientManager = new TerminologyClientManager(null, UUID.randomUUID().toString());
|
||||
private boolean minimalMemory = false;
|
||||
|
||||
private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>();
|
||||
|
@ -270,7 +272,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
private final Set<String> codeSystemsUsed = new HashSet<>();
|
||||
protected ToolingClientLogger txLog;
|
||||
private boolean canRunWithoutTerminology;
|
||||
protected boolean canRunWithoutTerminology;
|
||||
protected boolean noTerminologyServer;
|
||||
private int expandCodesLimit = 1000;
|
||||
protected ILoggingService logger = new SystemOutLoggingService();
|
||||
|
@ -279,7 +281,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
private Map<String, PackageInformation> packages = new HashMap<>();
|
||||
|
||||
@Getter
|
||||
protected TerminologyCache txCache;
|
||||
protected TerminologyCache txCache = new TerminologyCache(this, null);
|
||||
protected TimeTracker clock;
|
||||
private boolean tlogging = true;
|
||||
private IWorkerContextManager.ICanonicalResourceLocator locator;
|
||||
|
@ -775,12 +777,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (noTerminologyServer) {
|
||||
return false;
|
||||
}
|
||||
if (terminologyClientManager.getTxCapabilities() == null) {
|
||||
if (terminologyClientManager != null) {
|
||||
try {
|
||||
logger.logMessage("Terminology server: Check for supported code systems for "+system);
|
||||
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : terminologyClientManager.getMasterClient().getTerminologyCapabilities();
|
||||
txCache.cacheTerminologyCapabilities(capabilityStatement);
|
||||
setTxCaps(capabilityStatement);
|
||||
if (terminologyClientManager.supportsSystem(system)) {
|
||||
supportedCodeSystems.add(system);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (canRunWithoutTerminology) {
|
||||
noTerminologyServer = true;
|
||||
|
@ -1374,15 +1375,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
protected ValueSetExpander constructValueSetExpanderSimple(ValidationOptions options) {
|
||||
return new ValueSetExpander(this, new TerminologyOperationContext(this, options));
|
||||
return new ValueSetExpander(this, new TerminologyOperationContext(this, options)).setDebug(logger.isDebugLogging());
|
||||
}
|
||||
|
||||
protected ValueSetValidator constructValueSetCheckerSimple(ValidationOptions options, ValueSet vs, ValidationContextCarrier ctxt) {
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, ctxt, expParameters, terminologyClientManager.getTxCapabilities());
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, ctxt, expParameters, terminologyClientManager);
|
||||
}
|
||||
|
||||
protected ValueSetValidator constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs) {
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, expParameters, terminologyClientManager.getTxCapabilities());
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, expParameters, terminologyClientManager);
|
||||
}
|
||||
|
||||
protected Parameters constructParameters(TerminologyClientContext tcd, ValueSet vs, boolean hierarchical) {
|
||||
|
@ -1646,8 +1647,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
protected void addServerValidationParameters(TerminologyClientContext terminologyClientContext, ValueSet vs, Parameters pin, ValidationOptions options) {
|
||||
boolean cache = false;
|
||||
if (vs != null) {
|
||||
if (terminologyClientManager.isTxCaching() && terminologyClientManager.getCacheId() != null && vs.getUrl() != null && terminologyClientContext.getCached().contains(vs.getUrl()+"|"+ vs.getVersion())) {
|
||||
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()+(vs.hasVersion() ? "|"+ vs.getVersion() : "")));
|
||||
if (terminologyClientContext != null && terminologyClientContext.isTxCaching() && terminologyClientContext.getCacheId() != null && vs.getUrl() != null && terminologyClientContext.getCached().contains(vs.getUrl()+"|"+ vs.getVersion())) {
|
||||
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()));
|
||||
if (vs.hasVersion()) {
|
||||
pin.addParameter().setName("valueSetVersion").setValue(new StringType(vs.getVersion()));
|
||||
}
|
||||
} else if (options.getVsAsUrl()){
|
||||
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()));
|
||||
} else {
|
||||
|
@ -1706,7 +1710,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
private boolean checkAddToParams(TerminologyClientContext tc, Parameters pin, CanonicalResource cr) {
|
||||
boolean cache = false;
|
||||
boolean addToParams = false;
|
||||
if (terminologyClientManager.usingCache()) {
|
||||
if (tc.usingCache()) {
|
||||
if (!tc.alreadyCached(cr)) {
|
||||
tc.addToCache(cr);
|
||||
if (logger.isDebugLogging()) {
|
||||
|
@ -1857,11 +1861,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
return "item";
|
||||
}
|
||||
|
||||
protected void initTS(String cachePath) throws IOException {
|
||||
if (cachePath != null && !new File(cachePath).exists()) {
|
||||
Utilities.createDirectory(cachePath);
|
||||
public void initTxCache(String cachePath) throws FileNotFoundException, FHIRException, IOException {
|
||||
if (cachePath != null) {
|
||||
txCache = new TerminologyCache(lock, cachePath);
|
||||
initTxCache(txCache);
|
||||
}
|
||||
txCache = new TerminologyCache(lock, cachePath);
|
||||
}
|
||||
|
||||
public void initTxCache(TerminologyCache cache) {
|
||||
txCache = cache;
|
||||
terminologyClientManager.setCache(txCache);
|
||||
}
|
||||
|
||||
|
@ -1869,10 +1877,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
txCache.removeCS(url);
|
||||
}
|
||||
|
||||
public void clearTS() {
|
||||
txCache.clear();
|
||||
}
|
||||
|
||||
public boolean isCanRunWithoutTerminology() {
|
||||
return canRunWithoutTerminology;
|
||||
}
|
||||
|
@ -2994,33 +2998,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
return terminologyClientManager.getCacheId();
|
||||
}
|
||||
|
||||
public void setCacheId(String cacheId) {
|
||||
terminologyClientManager.setCacheId(cacheId);
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTxCaps() {
|
||||
return terminologyClientManager.getTxCapabilities();
|
||||
}
|
||||
|
||||
public void setTxCaps(TerminologyCapabilities txCaps) {
|
||||
this.terminologyClientManager.setTxCapabilities(txCaps);
|
||||
if (txCaps != null) {
|
||||
for (TerminologyCapabilitiesExpansionParameterComponent t : terminologyClientManager.getTxCapabilities().getExpansion().getParameter()) {
|
||||
if ("cache-id".equals(t.getName())) {
|
||||
terminologyClientManager.setTxCaching(true);
|
||||
}
|
||||
}
|
||||
for (TerminologyCapabilitiesCodeSystemComponent tccs : terminologyClientManager.getTxCapabilities().getCodeSystem()) {
|
||||
supportedCodeSystems.add(tccs.getUri());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TimeTracker clock() {
|
||||
return clock;
|
||||
}
|
||||
|
||||
|
||||
public int countAllCaches() {
|
||||
return codeSystems.size() + valueSets.size() + maps.size() + transforms.size() + structures.size() + measures.size() + libraries.size() +
|
||||
guides.size() + capstmts.size() + searchParameters.size() + questionnaires.size() + operations.size() + plans.size() +
|
||||
|
@ -3171,7 +3152,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
binaries.clear();
|
||||
validationCache.clear();
|
||||
txCache.clear();
|
||||
txCache.unload();
|
||||
}
|
||||
|
||||
private <T extends Resource> T doFindTxResource(Class<T> class_, String canonical) {
|
||||
|
@ -3180,8 +3161,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
SourcedValueSet svs = null;
|
||||
if (txCache.hasValueSet(canonical)) {
|
||||
svs = txCache.getValueSet(canonical);
|
||||
}
|
||||
if (svs == null) {
|
||||
} else {
|
||||
svs = terminologyClientManager.findValueSetOnServer(canonical);
|
||||
txCache.cacheValueSet(canonical, svs);
|
||||
}
|
||||
|
@ -3205,6 +3185,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
public <T extends Resource> T findTxResource(Class<T> class_, String canonical, Resource sourceOfReference) {
|
||||
if (canonical == null) {
|
||||
return null;
|
||||
}
|
||||
T result = fetchResource(class_, canonical, sourceOfReference);
|
||||
if (result == null) {
|
||||
result = doFindTxResource(class_, canonical);
|
||||
|
@ -3213,6 +3196,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
public <T extends Resource> T findTxResource(Class<T> class_, String canonical) {
|
||||
if (canonical == null) {
|
||||
return null;
|
||||
}
|
||||
T result = fetchResource(class_, canonical);
|
||||
if (result == null) {
|
||||
result = doFindTxResource(class_, canonical);
|
||||
|
@ -3221,6 +3207,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
public <T extends Resource> T findTxResource(Class<T> class_, String canonical, String version) {
|
||||
if (canonical == null) {
|
||||
return null;
|
||||
}
|
||||
T result = fetchResource(class_, canonical, version);
|
||||
if (result == null) {
|
||||
result = doFindTxResource(class_, canonical+"|"+version);
|
||||
|
|
|
@ -41,6 +41,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
|
@ -51,6 +52,7 @@ import org.apache.commons.io.IOUtils;
|
|||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.exceptions.TerminologyServiceException;
|
||||
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
|
||||
import org.hl7.fhir.r5.context.ILoggingService.LogCategory;
|
||||
import org.hl7.fhir.r5.formats.IParser;
|
||||
|
@ -64,6 +66,7 @@ import org.hl7.fhir.r5.model.StructureMap.StructureMapModelMode;
|
|||
import org.hl7.fhir.r5.model.StructureMap.StructureMapStructureComponent;
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext;
|
||||
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;
|
||||
|
@ -237,7 +240,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
}
|
||||
|
||||
private SimpleWorkerContext build(SimpleWorkerContext context) throws IOException {
|
||||
context.initTS(terminologyCachePath);
|
||||
context.initTxCache(terminologyCachePath);
|
||||
context.setUserAgent(userAgent);
|
||||
context.setLogger(loggingService);
|
||||
context.cacheResource(new org.hl7.fhir.r5.formats.JsonParser().parse(MagicResources.spdxCodesAsData()));
|
||||
|
@ -247,7 +250,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
public SimpleWorkerContext fromPackage(NpmPackage pi) throws IOException, FHIRException {
|
||||
SimpleWorkerContext context = getSimpleWorkerContextInstance();
|
||||
context.setAllowLoadingDuplicates(allowLoadingDuplicates);
|
||||
context.terminologyClientManager = new TerminologyClientManager(TerminologyClientR5.factory());
|
||||
context.terminologyClientManager.setFactory(TerminologyClientR5.factory());
|
||||
context.loadFromPackage(pi, null);
|
||||
return build(context);
|
||||
}
|
||||
|
@ -328,30 +331,48 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
loadBytes(name, stream);
|
||||
}
|
||||
|
||||
public String connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client, String log) {
|
||||
public void connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client) {
|
||||
terminologyClientManager.setFactory(factory);
|
||||
if (txLog == null) {
|
||||
txLog = client.getLogger();
|
||||
}
|
||||
TerminologyClientContext tcc = terminologyClientManager.setMasterClient(client);
|
||||
txLog("Connect to "+client.getAddress());
|
||||
try {
|
||||
tcc.initialize();
|
||||
} catch (Exception e) {
|
||||
if (canRunWithoutTerminology) {
|
||||
noTerminologyServer = true;
|
||||
logger.logMessage("==============!! Running without terminology server !! ==============");
|
||||
if (terminologyClientManager.getMasterClient() != null) {
|
||||
logger.logMessage("txServer = "+ terminologyClientManager.getMasterClient().getId());
|
||||
logger.logMessage("Error = "+e.getMessage()+"");
|
||||
}
|
||||
logger.logMessage("=====================================================================");
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
throw new TerminologyServiceException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void connectToTSServer(ITerminologyClientFactory factory, String address, String software, String log) {
|
||||
try {
|
||||
txLog("Connect to "+client.getAddress());
|
||||
terminologyClientManager.setFactory(factory);
|
||||
terminologyClientManager.setMasterClient(client);
|
||||
if (log != null && (log.endsWith(".htm") || log.endsWith(".html"))) {
|
||||
txLog = new HTMLClientLogger(log);
|
||||
} else {
|
||||
txLog = new TextClientLogger(log);
|
||||
}
|
||||
terminologyClientManager.setLogger(txLog);
|
||||
terminologyClientManager.setUserAgent(userAgent);
|
||||
|
||||
final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : terminologyClientManager.getMasterClient().getCapabilitiesStatementQuick();
|
||||
txCache.cacheCapabilityStatement(capabilitiesStatementQuick);
|
||||
|
||||
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : terminologyClientManager.getMasterClient().getTerminologyCapabilities();
|
||||
txCache.cacheTerminologyCapabilities(capabilityStatement);
|
||||
|
||||
setTxCaps(capabilityStatement);
|
||||
return capabilitiesStatementQuick.getSoftware().getVersion();
|
||||
}
|
||||
ITerminologyClient client = factory.makeClient("tx-server", address, software, txLog);
|
||||
// txFactory.makeClient("Tx-Server", txServer, "fhir/publisher", null)
|
||||
// terminologyClientManager.setLogger(txLog);
|
||||
// terminologyClientManager.setUserAgent(userAgent);
|
||||
connectToTSServer(factory, client);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new FHIRException(formatMessage(canNoTS ? I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER_USE_PARAMETER_TX_NA_TUN_RUN_WITHOUT_USING_TERMINOLOGY_SERVICES_TO_VALIDATE_LOINC_SNOMED_ICDX_ETC_ERROR__ : I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER, e.getMessage(), client.getAddress()), e);
|
||||
throw new FHIRException(formatMessage(canNoTS ? I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER_USE_PARAMETER_TX_NA_TUN_RUN_WITHOUT_USING_TERMINOLOGY_SERVICES_TO_VALIDATE_LOINC_SNOMED_ICDX_ETC_ERROR__ : I18nConstants.UNABLE_TO_CONNECT_TO_TERMINOLOGY_SERVER, e.getMessage(), address), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public interface ITerminologyClient {
|
|||
Parameters validateCS(Parameters pin) throws FHIRException;
|
||||
Parameters validateVS(Parameters pin) throws FHIRException;
|
||||
ITerminologyClient setTimeoutFactor(int i) throws FHIRException;
|
||||
ToolingClientLogger getLogger();
|
||||
ITerminologyClient setLogger(ToolingClientLogger txLog) throws FHIRException;
|
||||
int getRetryCount() throws FHIRException;
|
||||
ITerminologyClient setRetryCount(int retryCount) throws FHIRException;
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
package org.hl7.fhir.r5.terminologies.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesExpansionParameterComponent;
|
||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseCount;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
|
||||
|
||||
public class TerminologyClientContext {
|
||||
public enum TerminologyClientContextUseType {
|
||||
|
@ -40,14 +45,21 @@ public class TerminologyClientContext {
|
|||
}
|
||||
|
||||
private ITerminologyClient client;
|
||||
Map<String, TerminologyClientContextUseCount> useCounts = new HashMap<>();
|
||||
private boolean initialised = false;
|
||||
private CapabilityStatement capabilitiesStatementQuick;
|
||||
private TerminologyCapabilities txcaps;
|
||||
private TerminologyCache txCache;
|
||||
|
||||
private Map<String, TerminologyClientContextUseCount> useCounts = new HashMap<>();
|
||||
private boolean isTxCaching;
|
||||
private final Set<String> cached = new HashSet<>();
|
||||
private boolean master;
|
||||
private String cacheId;
|
||||
|
||||
protected TerminologyClientContext(ITerminologyClient client, boolean master) {
|
||||
protected TerminologyClientContext(ITerminologyClient client, String cacheId, boolean master) {
|
||||
super();
|
||||
this.client = client;
|
||||
this.cacheId = cacheId;
|
||||
this.master = master;
|
||||
}
|
||||
|
||||
|
@ -84,11 +96,11 @@ public class TerminologyClientContext {
|
|||
}
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTxcaps() {
|
||||
public TerminologyCapabilities getTxCapabilities() {
|
||||
return txcaps;
|
||||
}
|
||||
|
||||
public void setTxcaps(TerminologyCapabilities txcaps) {
|
||||
public void setTxCapabilities(TerminologyCapabilities txcaps) {
|
||||
this.txcaps = txcaps;
|
||||
}
|
||||
|
||||
|
@ -112,4 +124,65 @@ public class TerminologyClientContext {
|
|||
return getClient().getUseCount();
|
||||
}
|
||||
|
||||
public boolean isTxCaching() {
|
||||
return isTxCaching;
|
||||
}
|
||||
|
||||
public void setTxCaching(boolean isTxCaching) {
|
||||
this.isTxCaching = isTxCaching;
|
||||
}
|
||||
|
||||
public boolean usingCache() {
|
||||
return isTxCaching && cacheId != null;
|
||||
}
|
||||
|
||||
public String getCacheId() {
|
||||
return cacheId;
|
||||
}
|
||||
|
||||
public TerminologyCache getTxCache() {
|
||||
return txCache;
|
||||
}
|
||||
|
||||
public void setTxCache(TerminologyCache txCache) {
|
||||
this.txCache = txCache;
|
||||
}
|
||||
|
||||
public void initialize() throws IOException {
|
||||
if (!initialised) {
|
||||
// we don't cache the quick CS - we want to know that the server is with us.
|
||||
capabilitiesStatementQuick = client.getCapabilitiesStatementQuick();
|
||||
if (txCache != null && txCache.hasTerminologyCapabilities(getAddress())) {
|
||||
txcaps = txCache.getTerminologyCapabilities(getAddress());
|
||||
if (txcaps.getSoftware().hasVersion() && !txcaps.getSoftware().getVersion().equals(capabilitiesStatementQuick.getSoftware().getVersion())) {
|
||||
txcaps = null;
|
||||
}
|
||||
}
|
||||
if (txcaps == null) {
|
||||
txcaps = client.getTerminologyCapabilities();
|
||||
if (txCache != null) {
|
||||
txCache.cacheTerminologyCapabilities(getAddress(), txcaps);
|
||||
}
|
||||
}
|
||||
if (txcaps != null) {
|
||||
for (TerminologyCapabilitiesExpansionParameterComponent t : txcaps.getExpansion().getParameter()) {
|
||||
if ("cache-id".equals(t.getName())) {
|
||||
setTxCaching(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsSystem(String system) throws IOException {
|
||||
initialize();
|
||||
for (TerminologyCapabilitiesCodeSystemComponent tccs : txcaps.getCodeSystem()) {
|
||||
if (system.equals(tccs.getUri())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hl7.fhir.r5.model.Bundle;
|
|||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities.TerminologyCapabilitiesCodeSystemComponent;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
|
@ -37,7 +38,7 @@ public class TerminologyClientManager {
|
|||
}
|
||||
|
||||
public interface ITerminologyClientFactory {
|
||||
ITerminologyClient makeClient(String id, String url, String userAgent) throws URISyntaxException;
|
||||
ITerminologyClient makeClient(String id, String url, String userAgent, ToolingClientLogger logger) throws URISyntaxException;
|
||||
String getVersion();
|
||||
}
|
||||
|
||||
|
@ -47,7 +48,6 @@ public class TerminologyClientManager {
|
|||
|
||||
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
|
||||
|
@ -61,30 +61,18 @@ public class TerminologyClientManager {
|
|||
|
||||
private String monitorServiceURL;
|
||||
|
||||
public TerminologyClientManager(ITerminologyClientFactory factory) {
|
||||
public TerminologyClientManager(ITerminologyClientFactory factory, String cacheId) {
|
||||
super();
|
||||
this.factory = factory;
|
||||
this.cacheId = cacheId;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -93,10 +81,6 @@ public class TerminologyClientManager {
|
|||
usage = other.usage;
|
||||
}
|
||||
|
||||
public boolean usingCache() {
|
||||
return isTxCaching && cacheId != null;
|
||||
}
|
||||
|
||||
|
||||
public TerminologyClientContext chooseServer(Set<String> systems, boolean expand) throws TerminologyServiceException {
|
||||
if (serverList.isEmpty()) {
|
||||
|
@ -135,10 +119,11 @@ public class TerminologyClientManager {
|
|||
TerminologyClientContext client = serverMap.get(server);
|
||||
if (client == null) {
|
||||
try {
|
||||
client = new TerminologyClientContext(factory.makeClient("id"+(serverList.size()+1), server, getMasterClient().getUserAgent()), false);
|
||||
client = new TerminologyClientContext(factory.makeClient("id"+(serverList.size()+1), server, getMasterClient().getUserAgent(), getMasterClient().getLogger()), cacheId, false);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new TerminologyServiceException(e);
|
||||
}
|
||||
client.setTxCache(cache);
|
||||
serverList.add(client);
|
||||
serverMap.put(server, client);
|
||||
}
|
||||
|
@ -152,7 +137,7 @@ public class TerminologyClientManager {
|
|||
}
|
||||
if (expParameters != null) {
|
||||
if (!url.contains("|")) {
|
||||
// the client hasn''t specified an explicit version, but the expansion parameters might
|
||||
// the client hasn't specified an explicit version, but the expansion parameters might
|
||||
for (ParametersParameterComponent p : expParameters.getParameter()) {
|
||||
if (Utilities.existsInList(p.getName(), "system-version", "force-system-version") && p.hasValuePrimitive() && p.getValue().primitiveValue().startsWith(url+"|")) {
|
||||
url = p.getValue().primitiveValue();
|
||||
|
@ -176,7 +161,7 @@ public class TerminologyClientManager {
|
|||
for (JsonObject item : json.getJsonObjects("authoritative")) {
|
||||
return item.asString("url");
|
||||
}
|
||||
for (JsonObject item : json.getJsonObjects("candidate")) {
|
||||
for (JsonObject item : json.getJsonObjects("candidates")) {
|
||||
return item.asString("url");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -222,12 +207,14 @@ public class TerminologyClientManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void setMasterClient(ITerminologyClient client) {
|
||||
TerminologyClientContext details = new TerminologyClientContext(client, true);
|
||||
public TerminologyClientContext setMasterClient(ITerminologyClient client) {
|
||||
TerminologyClientContext details = new TerminologyClientContext(client, cacheId, true);
|
||||
details.setTxCache(cache);
|
||||
serverList.clear();
|
||||
serverList.add(details);
|
||||
serverMap.put(client.getAddress(), details);
|
||||
monitorServiceURL = Utilities.pathURL(Utilities.getDirectoryForURL(client.getAddress()), "tx-reg");
|
||||
return details;
|
||||
}
|
||||
|
||||
public TerminologyClientContext getMaster() {
|
||||
|
@ -246,13 +233,6 @@ public class TerminologyClientManager {
|
|||
return map;
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTxCapabilities() {
|
||||
return hasClient() ? serverList.get(0).getTxcaps() : null;
|
||||
}
|
||||
|
||||
public void setTxCapabilities(TerminologyCapabilities txCaps) {
|
||||
serverList.get(0).setTxcaps(txCaps);
|
||||
}
|
||||
|
||||
public void setFactory(ITerminologyClientFactory factory) {
|
||||
this.factory = factory;
|
||||
|
@ -309,8 +289,6 @@ public class TerminologyClientManager {
|
|||
return monitorServiceURL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Parameters getExpansionParameters() {
|
||||
return expParameters;
|
||||
}
|
||||
|
@ -343,7 +321,7 @@ public class TerminologyClientManager {
|
|||
server = item.asString("url");
|
||||
}
|
||||
}
|
||||
for (JsonObject item : json.getJsonObjects("candidate")) {
|
||||
for (JsonObject item : json.getJsonObjects("candidates")) {
|
||||
if (server == null) {
|
||||
server = item.asString("url");
|
||||
}
|
||||
|
@ -360,17 +338,19 @@ public class TerminologyClientManager {
|
|||
TerminologyClientContext client = serverMap.get(server);
|
||||
if (client == null) {
|
||||
try {
|
||||
client = new TerminologyClientContext(factory.makeClient("id"+(serverList.size()+1), server, getMasterClient().getUserAgent()), false);
|
||||
client = new TerminologyClientContext(factory.makeClient("id"+(serverList.size()+1), server, getMasterClient().getUserAgent(), getMasterClient().getLogger()), cacheId, false);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new TerminologyServiceException(e);
|
||||
}
|
||||
client.setTxCache(cache);
|
||||
serverList.add(client);
|
||||
serverMap.put(server, client);
|
||||
}
|
||||
client.seeUse(canonical, TerminologyClientContextUseType.readVS);
|
||||
String criteria = canonical.contains("|") ?
|
||||
"?url="+canonical.substring(0, canonical.lastIndexOf("|"))+"&version="+canonical.substring(canonical.lastIndexOf("|")+1) :
|
||||
"?url="+canonical;
|
||||
"?_format=json&url="+canonical.substring(0, canonical.lastIndexOf("|"))+"&version="+canonical.substring(canonical.lastIndexOf("|")+1) :
|
||||
"?_format=json&url="+canonical;
|
||||
request = Utilities.pathURL(client.getAddress(), "ValueSet"+ criteria);
|
||||
Bundle bnd = client.getClient().search("ValueSet", criteria);
|
||||
String rid = null;
|
||||
if (bnd.getEntry().size() == 0) {
|
||||
|
@ -395,15 +375,23 @@ public class TerminologyClientManager {
|
|||
ValueSet vs = (ValueSet) client.getClient().read("ValueSet", rid);
|
||||
return new SourcedValueSet(server, vs);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
String msg = "Error resolving valueSet "+canonical+": "+e.getMessage()+" ("+request+")";
|
||||
if (!internalErrors.contains(msg)) {
|
||||
internalErrors.add(msg);
|
||||
}
|
||||
if (!monitorServiceURL.contains("tx.fhir.org")) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsSystem(String system) throws IOException {
|
||||
for (TerminologyClientContext client : serverList) {
|
||||
if (client.supportsSystem(system)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class TerminologyClientR5 implements ITerminologyClient {
|
|||
public static class TerminologyClientR5Factory implements ITerminologyClientFactory {
|
||||
|
||||
@Override
|
||||
public ITerminologyClient makeClient(String id, String url, String userAgent) throws URISyntaxException {
|
||||
public ITerminologyClient makeClient(String id, String url, String userAgent, ToolingClientLogger logger) throws URISyntaxException {
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent);
|
||||
}
|
||||
|
||||
|
@ -146,6 +146,11 @@ public class TerminologyClientR5 implements ITerminologyClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolingClientLogger getLogger() {
|
||||
return client.getLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.context.ILoggingService.LogCategory;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.model.*;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
|
@ -60,6 +61,8 @@ import org.hl7.fhir.utilities.IniFile;
|
|||
import org.hl7.fhir.utilities.StringPair;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.json.model.JsonNull;
|
||||
import org.hl7.fhir.utilities.json.model.JsonProperty;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
|
||||
|
@ -98,6 +101,25 @@ public class TerminologyCache {
|
|||
}
|
||||
|
||||
|
||||
public static class SourcedValueSetEntry {
|
||||
private String server;
|
||||
private String filename;
|
||||
|
||||
public SourcedValueSetEntry(String server, String filename) {
|
||||
super();
|
||||
this.server = server;
|
||||
this.filename = filename;
|
||||
}
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static final boolean TRANSIENT = false;
|
||||
public static final boolean PERMANENT = true;
|
||||
private static final String NAME_FOR_NO_SYSTEM = "all-systems";
|
||||
|
@ -106,6 +128,7 @@ public class TerminologyCache {
|
|||
private static final String CACHE_FILE_EXTENSION = ".cache";
|
||||
private static final String CAPABILITY_STATEMENT_TITLE = ".capabilityStatement";
|
||||
private static final String TERMINOLOGY_CAPABILITIES_TITLE = ".terminologyCapabilities";
|
||||
private static final String FIXED_CACHE_VERSION = "3"; // last change: when multiple servers were introduced
|
||||
|
||||
|
||||
private SystemNameKeyGenerator systemNameKeyGenerator = new SystemNameKeyGenerator();
|
||||
|
@ -213,10 +236,11 @@ public class TerminologyCache {
|
|||
@Getter private int requestCount;
|
||||
@Getter private int hitCount;
|
||||
@Getter private int networkCount;
|
||||
private CapabilityStatement capabilityStatementCache = null;
|
||||
private TerminologyCapabilities terminologyCapabilitiesCache = null;
|
||||
private Map<String, CapabilityStatement> capabilityStatementCache = new HashMap<>();
|
||||
private Map<String, TerminologyCapabilities> terminologyCapabilitiesCache = new HashMap<>();
|
||||
private Map<String, NamedCache> caches = new HashMap<String, NamedCache>();
|
||||
private Map<String, StringPair> vsCache = new HashMap<>();
|
||||
private Map<String, SourcedValueSetEntry> vsCache = new HashMap<>();
|
||||
private Map<String, String> serverMap = new HashMap<>();
|
||||
@Getter @Setter private static boolean noCaching;
|
||||
|
||||
@Getter @Setter private static boolean cacheErrors;
|
||||
|
@ -226,54 +250,104 @@ public class TerminologyCache {
|
|||
public TerminologyCache(Object lock, String folder) throws FileNotFoundException, IOException, FHIRException {
|
||||
super();
|
||||
this.lock = lock;
|
||||
if (folder == null) {
|
||||
folder = Utilities.path("[tmp]", "default-tx-cache");
|
||||
}
|
||||
this.folder = folder;
|
||||
requestCount = 0;
|
||||
hitCount = 0;
|
||||
networkCount = 0;
|
||||
|
||||
|
||||
File f = new File(folder);
|
||||
if (!f.exists()) {
|
||||
Utilities.createDirectory(folder);
|
||||
}
|
||||
if (!f.exists()) {
|
||||
throw new IOException("Unable to create terminology cache at "+folder);
|
||||
}
|
||||
checkVersion();
|
||||
load();
|
||||
}
|
||||
|
||||
private void checkVersion() throws IOException {
|
||||
File verFile = new File(Utilities.path(folder, "version.ctl"));
|
||||
if (verFile.exists()) {
|
||||
String ver = TextFile.fileToString(verFile);
|
||||
if (!ver.equals(FIXED_CACHE_VERSION)) {
|
||||
System.out.println("Terminology Cache Version has changed from 1 to "+FIXED_CACHE_VERSION+", so clearing txCache");
|
||||
clear();
|
||||
}
|
||||
TextFile.stringToFile(FIXED_CACHE_VERSION, verFile);
|
||||
} else {
|
||||
TextFile.stringToFile(FIXED_CACHE_VERSION, verFile);
|
||||
}
|
||||
}
|
||||
|
||||
public String getServerId(String address) throws IOException {
|
||||
if (serverMap.containsKey(address)) {
|
||||
return serverMap.get(address);
|
||||
}
|
||||
String id = address.replace("http://", "").replace("https://", "").replace("/", ".");
|
||||
int i = 1;
|
||||
while (serverMap.containsValue(id)) {
|
||||
i++;
|
||||
id = address.replace("https:", "").replace("https:", "").replace("/", ".")+i;
|
||||
}
|
||||
serverMap.put(address, id);
|
||||
if (folder != null) {
|
||||
load();
|
||||
IniFile ini = new IniFile(Utilities.path(folder, "servers.ini"));
|
||||
ini.setStringProperty("servers", id, address, null);
|
||||
ini.save();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean hasCapabilityStatement() {
|
||||
return capabilityStatementCache != null;
|
||||
}
|
||||
|
||||
public CapabilityStatement getCapabilityStatement() {
|
||||
return capabilityStatementCache;
|
||||
}
|
||||
|
||||
public void cacheCapabilityStatement(CapabilityStatement capabilityStatement) {
|
||||
if (noCaching) {
|
||||
return;
|
||||
}
|
||||
this.capabilityStatementCache = capabilityStatement;
|
||||
save(capabilityStatementCache, CAPABILITY_STATEMENT_TITLE);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasTerminologyCapabilities() {
|
||||
return terminologyCapabilitiesCache != null;
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTerminologyCapabilities() {
|
||||
return terminologyCapabilitiesCache;
|
||||
}
|
||||
|
||||
public void cacheTerminologyCapabilities(TerminologyCapabilities terminologyCapabilities) {
|
||||
if (noCaching) {
|
||||
return;
|
||||
}
|
||||
this.terminologyCapabilitiesCache = terminologyCapabilities;
|
||||
save(terminologyCapabilitiesCache, TERMINOLOGY_CAPABILITIES_TITLE);
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
|
||||
public void unload() {
|
||||
// not useable after this is called
|
||||
caches.clear();
|
||||
vsCache.clear();
|
||||
}
|
||||
|
||||
private void clear() throws IOException {
|
||||
Utilities.clearDirectory(folder);
|
||||
caches.clear();
|
||||
vsCache.clear();
|
||||
}
|
||||
|
||||
public boolean hasCapabilityStatement(String address) {
|
||||
return capabilityStatementCache.containsKey(address);
|
||||
}
|
||||
|
||||
public CapabilityStatement getCapabilityStatement(String address) {
|
||||
return capabilityStatementCache.get(address);
|
||||
}
|
||||
|
||||
public void cacheCapabilityStatement(String address, CapabilityStatement capabilityStatement) throws IOException {
|
||||
if (noCaching) {
|
||||
return;
|
||||
}
|
||||
this.capabilityStatementCache.put(address, capabilityStatement);
|
||||
save(capabilityStatement, CAPABILITY_STATEMENT_TITLE+"."+getServerId(address));
|
||||
}
|
||||
|
||||
|
||||
public boolean hasTerminologyCapabilities(String address) {
|
||||
return terminologyCapabilitiesCache.containsKey(address);
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTerminologyCapabilities(String address) {
|
||||
return terminologyCapabilitiesCache.get(address);
|
||||
}
|
||||
|
||||
public void cacheTerminologyCapabilities(String address, TerminologyCapabilities terminologyCapabilities) throws IOException {
|
||||
if (noCaching) {
|
||||
return;
|
||||
}
|
||||
this.terminologyCapabilitiesCache.put(address, terminologyCapabilities);
|
||||
save(terminologyCapabilities, TERMINOLOGY_CAPABILITIES_TITLE+"."+getServerId(address));
|
||||
}
|
||||
|
||||
|
||||
public CacheToken generateValidationToken(ValidationOptions options, Coding code, ValueSet vs, Parameters expParameters) {
|
||||
try {
|
||||
|
@ -640,14 +714,19 @@ public class TerminologyCache {
|
|||
private void loadCapabilityCache(String fn) {
|
||||
try {
|
||||
String src = TextFile.fileToString(Utilities.path(folder, fn));
|
||||
String serverId = Utilities.getFileNameForName(fn).replace(CACHE_FILE_EXTENSION, "");
|
||||
serverId = serverId.substring(serverId.indexOf(".")+1);
|
||||
serverId = serverId.substring(serverId.indexOf(".")+1);
|
||||
String address = getServerForId(serverId);
|
||||
if (address != null) {
|
||||
JsonObject o = (JsonObject) new com.google.gson.JsonParser().parse(src);
|
||||
Resource resource = new JsonParser().parse(o);
|
||||
|
||||
JsonObject o = (JsonObject) new com.google.gson.JsonParser().parse(src);
|
||||
Resource resource = new JsonParser().parse(o);
|
||||
|
||||
if (fn.startsWith(CAPABILITY_STATEMENT_TITLE)) {
|
||||
this.capabilityStatementCache = (CapabilityStatement) resource;
|
||||
} else if (fn.startsWith(TERMINOLOGY_CAPABILITIES_TITLE)) {
|
||||
this.terminologyCapabilitiesCache = (TerminologyCapabilities) resource;
|
||||
if (fn.startsWith(CAPABILITY_STATEMENT_TITLE)) {
|
||||
this.capabilityStatementCache.put(address, (CapabilityStatement) resource);
|
||||
} else if (fn.startsWith(TERMINOLOGY_CAPABILITIES_TITLE)) {
|
||||
this.terminologyCapabilitiesCache.put(address, (TerminologyCapabilities) resource);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -655,6 +734,15 @@ public class TerminologyCache {
|
|||
}
|
||||
}
|
||||
|
||||
private String getServerForId(String serverId) {
|
||||
for (String n : serverMap.keySet()) {
|
||||
if (serverMap.get(n).equals(serverId)) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private CacheEntry getCacheEntry(String request, String resultString) throws IOException {
|
||||
CacheEntry ce = new CacheEntry();
|
||||
ce.persistent = true;
|
||||
|
@ -730,6 +818,13 @@ public class TerminologyCache {
|
|||
}
|
||||
|
||||
private void load() throws FHIRException, IOException {
|
||||
IniFile ini = new IniFile(Utilities.path(folder, "servers.ini"));
|
||||
if (ini.hasSection("servers")) {
|
||||
for (String n : ini.getPropertyNames("servers")) {
|
||||
serverMap.put(ini.getStringProperty("servers", n), n);
|
||||
}
|
||||
}
|
||||
|
||||
for (String fn : new File(folder).list()) {
|
||||
if (fn.endsWith(CACHE_FILE_EXTENSION) && !fn.equals("validation" + CACHE_FILE_EXTENSION)) {
|
||||
try {
|
||||
|
@ -743,13 +838,21 @@ public class TerminologyCache {
|
|||
}
|
||||
}
|
||||
}
|
||||
File fini = new File(Utilities.path(folder, "vs-external.ini"));
|
||||
if (fini.exists()) {
|
||||
IniFile ini = new IniFile(fini.getAbsolutePath());
|
||||
for (String k : ini.getPropertyNames("valuesets")) {
|
||||
String fn = ini.getStringProperty("valuesets", k);
|
||||
vsCache.put(k, new StringPair(Utilities.noString(fn) ? null : fn, ini.getStringProperty("servers", k)));
|
||||
try {
|
||||
File f = new File(Utilities.path(folder, "vs-externals.json"));
|
||||
if (f.exists()) {
|
||||
org.hl7.fhir.utilities.json.model.JsonObject json = org.hl7.fhir.utilities.json.parser.JsonParser.parseObject(f);
|
||||
for (JsonProperty p : json.getProperties()) {
|
||||
if (p.getValue().isJsonNull()) {
|
||||
vsCache.put(p.getName(), null);
|
||||
} else {
|
||||
org.hl7.fhir.utilities.json.model.JsonObject j = p.getValue().asJsonObject();
|
||||
vsCache.put(p.getName(), new SourcedValueSetEntry(j.asString("filename"), j.asString("server")));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error loading vs external cache: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,12 +961,12 @@ public class TerminologyCache {
|
|||
}
|
||||
|
||||
public SourcedValueSet getValueSet(String canonical) {
|
||||
StringPair sp = vsCache.get(canonical);
|
||||
if (sp == null || sp.getName() == null) {
|
||||
SourcedValueSetEntry sp = vsCache.get(canonical);
|
||||
if (sp == null) {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
return new SourcedValueSet(sp.getValue(), (ValueSet) new JsonParser().parse(new FileInputStream(Utilities.path(folder, sp.getName()))));
|
||||
return new SourcedValueSet(sp.getServer(), sp.getFilename() == null ? null : (ValueSet) new JsonParser().parse(new FileInputStream(Utilities.path(folder, sp.getFilename()))));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
|
@ -871,6 +974,9 @@ public class TerminologyCache {
|
|||
}
|
||||
|
||||
public void cacheValueSet(String canonical, SourcedValueSet svs) {
|
||||
if (canonical == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (svs == null) {
|
||||
vsCache.put(canonical, null);
|
||||
|
@ -878,16 +984,25 @@ public class TerminologyCache {
|
|||
String uuid = Utilities.makeUuidLC();
|
||||
String fn = "vs-"+uuid+".json";
|
||||
new JsonParser().compose(new FileOutputStream(Utilities.path(folder, fn)), svs.getVs());
|
||||
vsCache.put(canonical, new StringPair(fn, svs.getServer()));
|
||||
vsCache.put(canonical, new SourcedValueSetEntry(svs.getServer(), fn));
|
||||
}
|
||||
File fini = new File(Utilities.path(folder, "vs-external.ini"));
|
||||
IniFile ini = new IniFile(fini.getAbsolutePath());
|
||||
org.hl7.fhir.utilities.json.model.JsonObject j = new org.hl7.fhir.utilities.json.model.JsonObject();
|
||||
for (String k : vsCache.keySet()) {
|
||||
ini.setStringProperty("valuesets", k, vsCache.get(k).getName(), null);
|
||||
ini.setStringProperty("servers", k, vsCache.get(k).getValue(), null);
|
||||
SourcedValueSetEntry sve = vsCache.get(k);
|
||||
if (sve == null) {
|
||||
j.add(k, new JsonNull());
|
||||
} else {
|
||||
org.hl7.fhir.utilities.json.model.JsonObject e = new org.hl7.fhir.utilities.json.model.JsonObject();
|
||||
e.set("server", sve.getServer());
|
||||
if (sve.getFilename() != null) {
|
||||
e.set("filename", sve.getFilename());
|
||||
}
|
||||
j.add(k, e);
|
||||
}
|
||||
}
|
||||
ini.save();
|
||||
org.hl7.fhir.utilities.json.parser.JsonParser.compose(j, new File(Utilities.path(folder, "vs-externals.json")), true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.hl7.fhir.r5.terminologies.validation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
All rights reserved.
|
||||
|
@ -76,6 +78,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||
import org.hl7.fhir.r5.terminologies.providers.SpecialCodeSystem;
|
||||
|
@ -131,28 +134,28 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
private ValidationContextCarrier localContext;
|
||||
private List<CodeSystem> localSystems = new ArrayList<>();
|
||||
protected Parameters expansionProfile;
|
||||
private TerminologyCapabilities txCaps;
|
||||
private TerminologyClientManager tcm;
|
||||
private Set<String> unknownSystems;
|
||||
private Set<String> unknownValueSets = new HashSet<>();
|
||||
private boolean throwToServer;
|
||||
|
||||
public ValueSetValidator(IWorkerContext context, TerminologyOperationContext opContext, ValidationOptions options, ValueSet source, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||
public ValueSetValidator(IWorkerContext context, TerminologyOperationContext opContext, ValidationOptions options, ValueSet source, Parameters expansionProfile, TerminologyClientManager tcm) {
|
||||
super(context, opContext);
|
||||
this.valueset = source;
|
||||
this.options = options;
|
||||
this.expansionProfile = expansionProfile;
|
||||
this.txCaps = txCaps;
|
||||
this.tcm = tcm;
|
||||
analyseValueSet();
|
||||
}
|
||||
|
||||
public ValueSetValidator(IWorkerContext context, TerminologyOperationContext opContext, ValidationOptions options, ValueSet source, ValidationContextCarrier ctxt, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||
public ValueSetValidator(IWorkerContext context, TerminologyOperationContext opContext, ValidationOptions options, ValueSet source, ValidationContextCarrier ctxt, Parameters expansionProfile, TerminologyClientManager tcm) {
|
||||
super(context, opContext);
|
||||
this.valueset = source;
|
||||
this.options = options.copy();
|
||||
this.options.setEnglishOk(true);
|
||||
this.localContext = ctxt;
|
||||
this.expansionProfile = expansionProfile;
|
||||
this.txCaps = txCaps;
|
||||
this.tcm = tcm;
|
||||
analyseValueSet();
|
||||
}
|
||||
|
||||
|
@ -522,7 +525,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
if (cs == null) {
|
||||
OpIssueCode oic = OpIssueCode.NotFound;
|
||||
IssueType itype = IssueType.NOTFOUND;
|
||||
ValueSet vs = context.findTxResource(ValueSet.class, system);
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, system);
|
||||
if (vs != null) {
|
||||
warningMessage = context.formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET2, system);
|
||||
oic = OpIssueCode.InvalidData;
|
||||
|
@ -716,14 +719,15 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
if (SERVER_SIDE_LIST.contains(system)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (txCaps != null) {
|
||||
for (TerminologyCapabilitiesCodeSystemComponent tccs : txCaps.getCodeSystem()) {
|
||||
if (system.equals(tccs.getUri())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (tcm.supportsSystem(system)) {
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1458,7 +1462,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
|
|||
unknownValueSets.add(url);
|
||||
info.addIssue(makeIssue(IssueSeverity.ERROR, IssueType.NOTFOUND, null, context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, url), OpIssueCode.NotFound, null));
|
||||
}
|
||||
ValueSetValidator vsc = new ValueSetValidator(context, opContext.copy(), options, vs, localContext, expansionProfile, txCaps);
|
||||
ValueSetValidator vsc = new ValueSetValidator(context, opContext.copy(), options, vs, localContext, expansionProfile, tcm);
|
||||
vsc.setThrowToServer(throwToServer);
|
||||
inner.put(url, vsc);
|
||||
return vsc;
|
||||
|
|
|
@ -95,7 +95,7 @@ public class SimpleWorkerContextTests {
|
|||
public void beforeEach() {
|
||||
|
||||
Mockito.doReturn(DUMMY_URL).when(terminologyClient).getAddress();
|
||||
context.txCache = terminologyCache;
|
||||
context.initTxCache(terminologyCache);
|
||||
context.expParameters = expParameters;
|
||||
context.terminologyClientManager.setMasterClient(terminologyClient);
|
||||
context.txLog = txLog;
|
||||
|
@ -427,46 +427,41 @@ public class SimpleWorkerContextTests {
|
|||
|
||||
@Test
|
||||
public void testInitializationWithCache() {
|
||||
|
||||
Mockito.doReturn(true).when(terminologyCache).hasTerminologyCapabilities();
|
||||
Mockito.doReturn(true).when(terminologyCache).hasCapabilityStatement();
|
||||
|
||||
Mockito.doReturn(terminologyCapabilities).when(terminologyCache).getTerminologyCapabilities();
|
||||
Mockito.doReturn(capabilitiesStatement).when(terminologyCache).getCapabilityStatement();
|
||||
|
||||
String actual = context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient, null);
|
||||
|
||||
assertEquals("dummyVersion", actual);
|
||||
|
||||
Mockito.verify(terminologyCache).getTerminologyCapabilities();
|
||||
Mockito.verify(terminologyCache).getCapabilityStatement();
|
||||
|
||||
Mockito.verify(terminologyClient, times(0)).getTerminologyCapabilities();
|
||||
Mockito.verify(terminologyClient, times(0)).getCapabilitiesStatementQuick();
|
||||
|
||||
Mockito.verify(context).setTxCaps(terminologyCapabilities);
|
||||
// String address = "/...";
|
||||
//
|
||||
// Mockito.doReturn(true).when(terminologyCache).hasTerminologyCapabilities(address);
|
||||
//// Mockito.doReturn(true).when(terminologyCache).hasCapabilityStatement();
|
||||
//
|
||||
// Mockito.doReturn(terminologyCapabilities).when(terminologyCache).getTerminologyCapabilities(address);
|
||||
//// Mockito.doReturn(capabilitiesStatement).when(terminologyCache).getCapabilityStatement();
|
||||
//
|
||||
// context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient);
|
||||
//
|
||||
// Mockito.verify(terminologyCache).getTerminologyCapabilities(address);
|
||||
// Mockito.verify(terminologyClient).getCapabilitiesStatementQuick();
|
||||
//
|
||||
// Mockito.verify(terminologyCache, times(0)).getCapabilityStatement(address);
|
||||
// Mockito.verify(terminologyClient, times(0)).getTerminologyCapabilities();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializationWithClient() {
|
||||
// String address = "/...";
|
||||
//
|
||||
// Mockito.doReturn(false).when(terminologyCache).hasTerminologyCapabilities(address);
|
||||
//// Mockito.doReturn(false).when(terminologyCache).hasCapabilityStatement();
|
||||
//
|
||||
// Mockito.doReturn(terminologyCapabilities).when(terminologyClient).getTerminologyCapabilities();
|
||||
// Mockito.doReturn(capabilitiesStatement).when(terminologyClient).getCapabilitiesStatementQuick();
|
||||
//
|
||||
// context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient);
|
||||
//
|
||||
// Mockito.verify(terminologyCache, times(0)).getTerminologyCapabilities(address);
|
||||
// Mockito.verify(terminologyCache, times(0)).getCapabilityStatement(address);
|
||||
//
|
||||
// Mockito.verify(terminologyClient).getTerminologyCapabilities();
|
||||
// Mockito.verify(terminologyClient).getCapabilitiesStatementQuick();
|
||||
|
||||
Mockito.doReturn(false).when(terminologyCache).hasTerminologyCapabilities();
|
||||
Mockito.doReturn(false).when(terminologyCache).hasCapabilityStatement();
|
||||
|
||||
Mockito.doReturn(terminologyCapabilities).when(terminologyClient).getTerminologyCapabilities();
|
||||
Mockito.doReturn(capabilitiesStatement).when(terminologyClient).getCapabilitiesStatementQuick();
|
||||
|
||||
String actual = context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient, null);
|
||||
|
||||
assertEquals("dummyVersion", actual);
|
||||
|
||||
Mockito.verify(terminologyCache, times(0)).getTerminologyCapabilities();
|
||||
Mockito.verify(terminologyCache, times(0)).getCapabilityStatement();
|
||||
|
||||
Mockito.verify(terminologyClient).getTerminologyCapabilities();
|
||||
Mockito.verify(terminologyClient).getCapabilitiesStatementQuick();
|
||||
|
||||
Mockito.verify(context).setTxCaps(terminologyCapabilities);
|
||||
}
|
||||
|
||||
public static Stream<Arguments> zipSlipData() {
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.tests.ResourceLoaderTests;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -92,6 +93,8 @@ public class TerminologyCacheTests implements ResourceLoaderTests {
|
|||
|
||||
@Test
|
||||
public void testCachePersistence() throws IOException, URISyntaxException {
|
||||
String address = "/...";
|
||||
|
||||
Object lock = new Object();
|
||||
Path tempCacheDirectory = createTempCacheDirectory();
|
||||
ValueSet valueSet = new ValueSet();
|
||||
|
@ -117,8 +120,8 @@ public class TerminologyCacheTests implements ResourceLoaderTests {
|
|||
// Add dummy results to the cache
|
||||
TerminologyCache terminologyCacheA = new TerminologyCache(lock, tempCacheDirectory.toString());
|
||||
|
||||
terminologyCacheA.cacheTerminologyCapabilities(terminologyCapabilities);
|
||||
terminologyCacheA.cacheCapabilityStatement(capabilityStatement);
|
||||
terminologyCacheA.cacheTerminologyCapabilities(address, terminologyCapabilities);
|
||||
terminologyCacheA.cacheCapabilityStatement(address, capabilityStatement);
|
||||
|
||||
ValidationResult codingResultA = new ValidationResult(ValidationMessage.IssueSeverity.INFORMATION, "dummyInfo", null);
|
||||
TerminologyCache.CacheToken codingTokenA = terminologyCacheA.generateValidationToken(CacheTestUtils.validationOptions,
|
||||
|
@ -136,8 +139,8 @@ public class TerminologyCacheTests implements ResourceLoaderTests {
|
|||
terminologyCacheA.cacheExpansion(expansionTokenA, expansionOutcomeA, true);
|
||||
// Check that the in-memory cache is returning what we put in
|
||||
{
|
||||
assertEquals(terminologyCapabilities, terminologyCacheA.getTerminologyCapabilities());
|
||||
assertEquals(capabilityStatement, terminologyCacheA.getCapabilityStatement());
|
||||
assertEquals(terminologyCapabilities, terminologyCacheA.getTerminologyCapabilities(address));
|
||||
assertEquals(capabilityStatement, terminologyCacheA.getCapabilityStatement(address));
|
||||
|
||||
assertValidationResultEquals(codingResultA, terminologyCacheA.getValidation(codingTokenA));
|
||||
assertValidationResultEquals(codeableConceptResultA, terminologyCacheA.getValidation(codeableConceptTokenA));
|
||||
|
@ -148,8 +151,8 @@ public class TerminologyCacheTests implements ResourceLoaderTests {
|
|||
{
|
||||
TerminologyCache terminologyCacheB = new TerminologyCache(lock, tempCacheDirectory.toString());
|
||||
|
||||
assertCanonicalResourceEquals(terminologyCapabilities, terminologyCacheB.getTerminologyCapabilities());
|
||||
assertCanonicalResourceEquals(capabilityStatement, terminologyCacheB.getCapabilityStatement());
|
||||
assertCanonicalResourceEquals(terminologyCapabilities, terminologyCacheB.getTerminologyCapabilities(address));
|
||||
assertCanonicalResourceEquals(capabilityStatement, terminologyCacheB.getCapabilityStatement(address));
|
||||
|
||||
assertValidationResultEquals(codingResultA, terminologyCacheB.getValidation(terminologyCacheA.generateValidationToken(CacheTestUtils.validationOptions, coding, valueSet, new Parameters())));
|
||||
assertValidationResultEquals(codeableConceptResultA, terminologyCacheB.getValidation(terminologyCacheA.generateValidationToken(CacheTestUtils.validationOptions, concept, valueSet, new Parameters())));
|
||||
|
|
|
@ -23,9 +23,11 @@ public class CacheVerificationLogger implements ToolingClientLogger {
|
|||
System.err.println("Header: " + header);
|
||||
}
|
||||
}
|
||||
System.err.println("Body");
|
||||
System.err.println("----");
|
||||
System.err.println(new String(body, StandardCharsets.UTF_8));
|
||||
if (body != null) {
|
||||
System.err.println("Body");
|
||||
System.err.println("----");
|
||||
System.err.println(new String(body, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
requests++;
|
||||
}
|
||||
|
|
|
@ -192,8 +192,8 @@ Terminology_TX_System_Relative = Coding.system must be an absolute reference, no
|
|||
Terminology_TX_System_Unknown = Unknown Code System ''{0}''
|
||||
Terminology_TX_System_ValueSet = Invalid System URI: {0} - cannot use a value set URI as a system
|
||||
Terminology_TX_System_ValueSet2 = The Coding references a value set, not a code system (''{0}'')
|
||||
Terminology_TX_ValueSet_NotFound = ValueSet {0} not found
|
||||
Terminology_TX_ValueSet_NotFound_CS = Found a reference to a CodeSystem ({0}) where a ValueSet belongs
|
||||
Terminology_TX_ValueSet_NotFound = ValueSet ''{0}'' not found
|
||||
Terminology_TX_ValueSet_NotFound_CS = Found a reference to a CodeSystem ''{0}'' where a ValueSet belongs
|
||||
Type_Specific_Checks_DT_Base64_Valid = The value ''{0}'' is not a valid Base64 value
|
||||
Type_Specific_Checks_DT_Boolean_Value = Boolean values must be ''true'' or ''false''
|
||||
Type_Specific_Checks_DT_Code_WS = The code ''{0}'' is not valid (whitespace rules)
|
||||
|
@ -458,7 +458,7 @@ Delimited_versions_have_exact_match_for_delimiter____vs_ = Delimited versions ha
|
|||
Duplicate_Resource_ = Duplicate Resource {0} of type {3} (existing version {2}, new version {1})
|
||||
DUPLICATE_RESOURCE_VERSION = Duplicate Resource {0} Version {1} of type {2}
|
||||
Error_expanding_ValueSet_running_without_terminology_services = Error expanding ValueSet: running without terminology services
|
||||
Error_validating_code_running_without_terminology_services = Error validating code: running without terminology services
|
||||
Error_validating_code_running_without_terminology_services = Unable to validate code ''{0}'' in system ''{1}'' because the validator is running without terminology services
|
||||
Unable_to_validate_code_without_using_server = Unable to validate code without using server because: {0}
|
||||
UNABLE_TO_VALIDATE_LOCALLY = Unable to validate code locally: {0}
|
||||
Profile___Error_generating_snapshot = Profile {0} ({1}). Error generating snapshot
|
||||
|
|
|
@ -475,7 +475,6 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
|
||||
protected void initContext(TimeTracker tt) throws IOException {
|
||||
context.setCanNoTS(true);
|
||||
context.setCacheId(UUID.randomUUID().toString());
|
||||
context.setAllowLoadingDuplicates(true); // because of Forge
|
||||
context.setExpansionParameters(makeExpProfile());
|
||||
if (tt != null) {
|
||||
|
@ -524,7 +523,8 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
} else {
|
||||
try {
|
||||
TerminologyClientFactory factory = new TerminologyClientFactory(version);
|
||||
return context.connectToTSServer(factory, factory.makeClient("Tx-Server", url, context.getUserAgent()), log);
|
||||
context.connectToTSServer(factory, url, context.getUserAgent(), log);
|
||||
return "Connected to Terminology Server at "+url;
|
||||
} catch (Exception e) {
|
||||
if (context.isCanRunWithoutTerminology()) {
|
||||
return "n/a: Running without Terminology Server (error: " + e.getMessage() + ")";
|
||||
|
|
|
@ -289,7 +289,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV
|
|||
|
||||
@Nonnull
|
||||
protected ITerminologyClient getTerminologyClient(String root) throws URISyntaxException {
|
||||
return new TerminologyClientFactory(context.getVersion()).makeClient("source", root, Common.getValidatorUserAgent());
|
||||
return new TerminologyClientFactory(context.getVersion()).makeClient("source", root, Common.getValidatorUserAgent(), null);
|
||||
}
|
||||
|
||||
private String getRoot(String[] p, String url) {
|
||||
|
|
|
@ -1175,6 +1175,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return false;
|
||||
}
|
||||
} else if (context.isNoTerminologyServer() && NO_TX_SYSTEM_EXEMPT.contains(system)) {
|
||||
txWarning(errors, NO_RULE_DATE, null, IssueType.BUSINESSRULE, element.line(), element.col(), path, false, I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES, code, system);
|
||||
return ok; // no checks in this case
|
||||
} else if (startsWithButIsNot(system, "http://snomed.info/sct", "http://loinc.org", "http://unitsofmeasure.org", "http://www.nlm.nih.gov/research/umls/rxnorm")) {
|
||||
rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_INVALID, system);
|
||||
|
|
|
@ -139,7 +139,7 @@ public class TxTester {
|
|||
|
||||
private ITerminologyClient connectToServer() throws URISyntaxException {
|
||||
System.out.println("Connect to "+server);
|
||||
return new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java");
|
||||
return new TerminologyClientFactory(FhirPublication.R4).makeClient("Test-Server", server, "Tools/Java", null);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue