cache CapabilityStatement and TerminologyCapabilities

This commit is contained in:
dotasek 2022-01-18 16:09:59 -05:00
parent 6e0b14b0b6
commit d9d0f22ff3
20 changed files with 24714 additions and 121 deletions

View File

@ -37,21 +37,27 @@ import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URISyntaxException;
import java.util.Map;
public class TerminologyClientR5 implements TerminologyClient {
private final Logger logger = LoggerFactory.getLogger(TerminologyClientR5.class);
private final FHIRToolingClient client;
private ClientHeaders clientHeaders;
public TerminologyClientR5(String address, String userAgent) throws URISyntaxException {
logger.info("TerminologyClientR5(String address, String userAgent)");
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(new ClientHeaders());
}
public TerminologyClientR5(String address, String userAgent, ClientHeaders clientHeaders) throws URISyntaxException {
logger.info("TerminologyClientR5(String address, String userAgent, ClientHeaders clientHeaders)");
this.client = new FHIRToolingClient(address, userAgent);
setClientHeaders(clientHeaders);
}

View File

@ -1,33 +1,33 @@
package org.hl7.fhir.r4.context;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import com.google.gson.JsonObject;
@ -119,6 +119,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
public BaseWorkerContext() throws FileNotFoundException, IOException, FHIRException {
super();
//CACHE
txCache = new TerminologyCache(lock, null);
}
@ -129,6 +130,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
this.maps = maps;
this.structures = profiles;
this.guides = guides;
//CACHE
txCache = new TerminologyCache(lock, null);
}

View File

@ -1216,7 +1216,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
// --------------------------------------------------------------------------------------------------------------------------------------------------------
public void initTS(String cachePath) throws Exception {
public void initTS(String cachePath) throws IOException {
if (!new File(cachePath).exists()) {
Utilities.createDirectory(cachePath);
}

View File

@ -59,18 +59,11 @@ import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.formats.ParserType;
import org.hl7.fhir.r5.formats.XmlParser;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.Questionnaire;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.ResourceType;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.model.StructureMap;
import org.hl7.fhir.r5.model.StructureMap.StructureMapModelMode;
import org.hl7.fhir.r5.model.StructureMap.StructureMapStructureComponent;
import org.hl7.fhir.r5.terminologies.TerminologyClient;
@ -90,6 +83,8 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
import ca.uhn.fhir.parser.DataFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
* This is a stand alone implementation of worker context for use inside a tool.
@ -99,6 +94,8 @@ import ca.uhn.fhir.parser.DataFormatException;
public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerContext, ProfileKnowledgeProvider {
private final Logger dlogger = LoggerFactory.getLogger(SimpleWorkerContext.class);
public static class PackageResourceLoader extends CanonicalResourceProxy {
private String filename;
@ -292,9 +289,18 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
txClient.setLogger(txLog);
txClient.setUserAgent(userAgent);
CapabilityStatement cps = txClient.getCapabilitiesStatementQuick();
setTxCaps(txClient.getTerminologyCapabilities());
return cps.getSoftware().getVersion();
//CACHE
dlogger.info("SimpleWorkerContext.connectToTSServer");
final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : txClient.getCapabilitiesStatementQuick();
txCache.cacheCapabilityStatement(capabilitiesStatementQuick);
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : txClient.getTerminologyCapabilities();
txCache.cacheTerminologyCapabilities(capabilityStatement);
setTxCaps(capabilityStatement);
return capabilitiesStatementQuick.getSoftware().getVersion();
} catch (Exception 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()), e);
}

View File

@ -37,7 +37,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
@ -46,11 +45,8 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.UriType;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
@ -63,16 +59,15 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.validation.ValidationOptions;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
/**
* This implements a two level cache.
* - a temporary cache for remmbering previous local operations
* - a persistent cache for rembering tx server operations
* - a temporary cache for remembering previous local operations
* - a persistent cache for remembering tx server operations
*
* the cache is a series of pairs: a map, and a list. the map is the loaded cache, the list is the persiistent cache, carefully maintained in order for version control consistency
* the cache is a series of pairs: a map, and a list. the map is the loaded cache, the list is the persistent cache, carefully maintained in order for version control consistency
*
* @author graha
*
@ -84,6 +79,11 @@ public class TerminologyCache {
private static final String ENTRY_MARKER = "-------------------------------------------------------------------------------------";
private static final String BREAK = "####";
private static final String CACHE_FILE_EXTENSION = ".cache";
private static final String CAPABILITY_STATEMENT_TITLE = ".capabilityStatement";
private static final String TERMINOLOGY_CAPABILITIES_TITLE = ".terminologyCapabilities";
@Getter
private int requestCount;
@Getter
@ -121,6 +121,44 @@ public class TerminologyCache {
private Object lock;
private String folder;
private CapabilityStatement capabilityStatementCache = null;
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);
}
private TerminologyCapabilities terminologyCapabilitiesCache = null;
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);
}
private Map<String, NamedCache> caches = new HashMap<String, NamedCache>();
@Getter @Setter
private static boolean noCaching;
@ -362,13 +400,30 @@ public class TerminologyCache {
public void save() {
}
private <K extends Resource> void save(K resource, String title) {
if (folder == null)
return;
try {
OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream(Utilities.path(folder, title + CACHE_FILE_EXTENSION)), "UTF-8");
JsonParser json = new JsonParser();
json.setOutputStyle(OutputStyle.PRETTY);
sw.write(json.composeString(resource).trim());
sw.close();
} catch (Exception e) {
System.out.println("error saving capability statement "+e.getMessage());
}
}
private void save(NamedCache nc) {
if (folder == null)
return;
try {
OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream(Utilities.path(folder, nc.name+".cache")), "UTF-8");
OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream(Utilities.path(folder, nc.name+"CACHE_FILE_EXTENSION")), "UTF-8");
sw.write(ENTRY_MARKER+"\r\n");
JsonParser json = new JsonParser();
json.setOutputStyle(OutputStyle.PRETTY);
@ -421,57 +476,94 @@ public class TerminologyCache {
}
}
private boolean isCapabilityCache(String fn) {
if (fn == null) {
return false;
}
return fn.startsWith(CAPABILITY_STATEMENT_TITLE) || fn.startsWith(TERMINOLOGY_CAPABILITIES_TITLE);
}
private void loadCapabilityCache(String fn) {
try {
String src = TextFile.fileToString(Utilities.path(folder, fn));
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;
}
} catch (Exception e) {
throw new FHIRException("Error loading " + fn + ": " + e.getMessage(), e);
}
}
private void loadNamedCache(String fn) {
int c = 0;
try {
String src = TextFile.fileToString(Utilities.path(folder, fn));
String title = fn.substring(0, fn.lastIndexOf("."));
NamedCache nc = new NamedCache();
nc.name = title;
caches.put(title, nc);
if (src.startsWith("?"))
src = src.substring(1);
int i = src.indexOf(ENTRY_MARKER);
while (i > -1) {
c++;
String s = src.substring(0, i);
src = src.substring(i + ENTRY_MARKER.length() + 1);
i = src.indexOf(ENTRY_MARKER);
if (!Utilities.noString(s)) {
int j = s.indexOf(BREAK);
String q = s.substring(0, j);
String p = s.substring(j + BREAK.length() + 1).trim();
CacheEntry ce = new CacheEntry();
ce.persistent = true;
ce.request = q;
boolean e = p.charAt(0) == 'e';
p = p.substring(3);
JsonObject o = (JsonObject) new com.google.gson.JsonParser().parse(p);
String error = loadJS(o.get("error"));
if (e) {
if (o.has("valueSet"))
ce.e = new ValueSetExpansionOutcome((ValueSet) new JsonParser().parse(o.getAsJsonObject("valueSet")), error, TerminologyServiceErrorClass.UNKNOWN);
else
ce.e = new ValueSetExpansionOutcome(error, TerminologyServiceErrorClass.UNKNOWN);
} else {
String t = loadJS(o.get("severity"));
IssueSeverity severity = t == null ? null : IssueSeverity.fromCode(t);
String display = loadJS(o.get("display"));
String code = loadJS(o.get("code"));
String system = loadJS(o.get("system"));
String definition = loadJS(o.get("definition"));
t = loadJS(o.get("class"));
TerminologyServiceErrorClass errorClass = t == null ? null : TerminologyServiceErrorClass.valueOf(t);
ce.v = new ValidationResult(severity, error, system, new ConceptDefinitionComponent().setDisplay(display).setDefinition(definition).setCode(code)).setErrorClass(errorClass);
}
nc.map.put(String.valueOf(hashNWS(ce.request)), ce);
nc.list.add(ce);
}
}
} catch (Exception e) {
throw new FHIRException("Error loading " + fn + ": " + e.getMessage() + " entry " + c, e);
}
}
private void load() throws FHIRException {
for (String fn : new File(folder).list()) {
if (fn.endsWith(".cache") && !fn.equals("validation.cache")) {
int c = 0;
if (fn.endsWith(CACHE_FILE_EXTENSION) && !fn.equals("validation" + CACHE_FILE_EXTENSION)) {
try {
String title = fn.substring(0, fn.lastIndexOf("."));
NamedCache nc = new NamedCache();
nc.name = title;
caches.put(title, nc);
String src = TextFile.fileToString(Utilities.path(folder, fn));
if (src.startsWith("?"))
src = src.substring(1);
int i = src.indexOf(ENTRY_MARKER);
while (i > -1) {
c++;
String s = src.substring(0, i);
src = src.substring(i + ENTRY_MARKER.length() + 1);
i = src.indexOf(ENTRY_MARKER);
if (!Utilities.noString(s)) {
int j = s.indexOf(BREAK);
String q = s.substring(0, j);
String p = s.substring(j + BREAK.length() + 1).trim();
CacheEntry ce = new CacheEntry();
ce.persistent = true;
ce.request = q;
boolean e = p.charAt(0) == 'e';
p = p.substring(3);
JsonObject o = (JsonObject) new com.google.gson.JsonParser().parse(p);
String error = loadJS(o.get("error"));
if (e) {
if (o.has("valueSet"))
ce.e = new ValueSetExpansionOutcome((ValueSet) new JsonParser().parse(o.getAsJsonObject("valueSet")), error, TerminologyServiceErrorClass.UNKNOWN);
else
ce.e = new ValueSetExpansionOutcome(error, TerminologyServiceErrorClass.UNKNOWN);
} else {
String t = loadJS(o.get("severity"));
IssueSeverity severity = t == null ? null : IssueSeverity.fromCode(t);
String display = loadJS(o.get("display"));
String code = loadJS(o.get("code"));
String system = loadJS(o.get("system"));
String definition = loadJS(o.get("definition"));
t = loadJS(o.get("class"));
TerminologyServiceErrorClass errorClass = t == null ? null : TerminologyServiceErrorClass.valueOf(t);
ce.v = new ValidationResult(severity, error, system, new ConceptDefinitionComponent().setDisplay(display).setDefinition(definition).setCode(code)).setErrorClass(errorClass);
}
nc.map.put(String.valueOf(hashNWS(ce.request)), ce);
nc.list.add(ce);
}
if (isCapabilityCache(fn)) {
loadCapabilityCache(fn);
} else {
loadNamedCache(fn);
}
} catch (Exception e) {
throw new FHIRException("Error loading " + fn + ": " + e.getMessage() + " entry " + c, e);
} catch (FHIRException e) {
throw e;
}
}
}

View File

@ -41,6 +41,8 @@ import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.r5.utils.client.network.ResourceRequest;
import org.hl7.fhir.utilities.ToolingClientLogger;
import org.hl7.fhir.utilities.Utilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.MalformedURLException;
@ -75,6 +77,8 @@ import java.util.*;
*/
public class FHIRToolingClient {
private final Logger logger = LoggerFactory.getLogger(FHIRToolingClient.class);
public static final String DATETIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssK";
public static final String DATE_FORMAT = "yyyy-MM-dd";
public static final String hostKey = "http.proxyHost";
@ -108,7 +112,6 @@ public class FHIRToolingClient {
base = baseServiceUrl;
resourceAddress = new ResourceAddress(baseServiceUrl);
this.maxResultSetSize = -1;
checkCapabilities();
}
public Client getClient() {
@ -119,13 +122,6 @@ public class FHIRToolingClient {
this.client = client;
}
private void checkCapabilities() {
try {
capabilities = getCapabilitiesStatementQuick();
} catch (Throwable e) {
}
}
public String getPreferredResourceFormat() {
return preferredResourceFormat.getHeader();
}
@ -157,27 +153,33 @@ public class FHIRToolingClient {
}
public CapabilityStatement getCapabilitiesStatement() {
CapabilityStatement conformance = null;
logger.info("FHIRToolingClient.getCapabilitiesStatement");
CapabilityStatement capabilityStatement = null;
try {
conformance = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
capabilityStatement = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false),
getPreferredResourceFormat(),
generateHeaders(),
"CapabilitiesStatement",
TIMEOUT_NORMAL).getReference();
logger.info("FHIRToolingClient.getCapabilitiesStatement - fetched capabilities from server: " + (capabilities != null ? capabilities.getVersion() : "no version"));
} catch (Exception e) {
throw new FHIRException("Error fetching the server's conformance statement", e);
}
return conformance;
return capabilityStatement;
}
public CapabilityStatement getCapabilitiesStatementQuick() throws EFhirClientException {
logger.info("FHIRToolingClient.getCapabilitiesStatementQuick");
if (capabilities != null) return capabilities;
try {
capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
capabilities = (CapabilityStatement) client.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true),
getPreferredResourceFormat(),
generateHeaders(),
"CapabilitiesStatement-Quick",
TIMEOUT_NORMAL).getReference();
logger.info("FHIRToolingClient.getCapabilitiesStatementQuick - fetched capabilities from server: " + capabilities.getVersion());
} catch (Exception e) {
throw new FHIRException("Error fetching the server's capability statement: "+e.getMessage(), e);
}
@ -583,6 +585,13 @@ public class FHIRToolingClient {
}
public String getServerVersion() {
if (capabilities == null) {
try {
getCapabilitiesStatementQuick();
} catch (Throwable e) {
//FIXME This is creepy. Shouldn't we report this at some level?
}
}
return capabilities == null ? null : capabilities.getSoftware().getVersion();
}

View File

@ -194,19 +194,19 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
public ValidationEngine(String src, String txsrvr, String txLog, String txCachePath, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, null);
getContext().setUserAgent(userAgent);
getContext().setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
setTerminologyServer(txsrvr, txLog, version);
setTerminologyServer(txsrvr, txLog, txCachePath, version);
setVersion(vString);
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
public ValidationEngine(String src, String txsrvr, String txLog, String txCachePath, FhirPublication version, String vString, String userAgent) throws FHIRException, IOException, URISyntaxException {
loadCoreDefinitions(src, false, null);
getContext().setUserAgent(userAgent);
setTerminologyServer(txsrvr, txLog, version);
setTerminologyServer(txsrvr, txLog, txCachePath, version);
setVersion(vString);
igLoader = new IgLoader(getPcm(), getContext(), getVersion(), isDebug());
}
@ -280,7 +280,11 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
return ep;
}
public String connectToTSServer(String url, String log, FhirPublication version) throws URISyntaxException, FHIRException {
public String connectToTSServer(String url, String log, FhirPublication version) throws URISyntaxException, IOException, FHIRException {
return connectToTSServer(url, log, null, version);
}
public String connectToTSServer(String url, String log, String txCachePath, FhirPublication version) throws URISyntaxException, IOException, FHIRException {
context.setTlogging(false);
if (url == null) {
context.setCanRunWithoutTerminology(true);
@ -288,6 +292,10 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
return "n/a: No Terminology Server";
} else {
try {
//FIXME this can fail for a different reason than connectToTSServer
if (txCachePath != null) {
context.initTS(txCachePath);
}
return context.connectToTSServer(TerminologyClientFactory.makeClient(url, context.getUserAgent(), version), log);
} catch (Exception e) {
if (context.isCanRunWithoutTerminology()) {
@ -689,8 +697,12 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
throw new FHIRException("Source/Target version not supported: " + version + " -> " + targetVer);
}
public String setTerminologyServer(String src, String log, FhirPublication version) throws FHIRException, URISyntaxException {
return connectToTSServer(src, log, version);
public String setTerminologyServer(String src, String log, FhirPublication version) throws FHIRException, IOException, URISyntaxException {
return setTerminologyServer(src, log, null, version);
}
public String setTerminologyServer(String src, String log, String txCachePath, FhirPublication version) throws FHIRException, IOException, URISyntaxException {
return connectToTSServer(src, log, txCachePath, version);
}
public ValidationEngine setMapLog(String mapLog) throws FileNotFoundException {

View File

@ -15,8 +15,7 @@ public class TestUtilities {
// }
public static final ValidationEngine getValidationEngine(java.lang.String src, java.lang.String txsrvr, java.lang.String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, java.lang.String vString, java.lang.String userAgent) throws Exception {
txLog = TestConstants.TX_CACHE_LOG;
final ValidationEngine validationEngine = new ValidationEngine(src, txsrvr, txLog, version, canRunWithoutTerminologyServer, vString, userAgent);
validationEngine.getContext().initTS(Paths.get(TestConstants.TX_CACHE, vString).toString());
final ValidationEngine validationEngine = new ValidationEngine(src, txsrvr, txLog, Paths.get(TestConstants.TX_CACHE, vString).toString(), version, canRunWithoutTerminologyServer, vString, userAgent);
TerminologyCache.setCacheErrors(true);
validationEngine.getContext().setUserAgent("fhir/test-cases");
return validationEngine;
@ -24,8 +23,7 @@ public class TestUtilities {
public static ValidationEngine getValidationEngine(java.lang.String src, java.lang.String txsrvr, java.lang.String txLog, FhirPublication version, java.lang.String vString, java.lang.String userAgent) throws Exception {
txLog = TestConstants.TX_CACHE_LOG;
final ValidationEngine validationEngine = new ValidationEngine(src, txsrvr, txLog, version, vString, userAgent);
validationEngine.getContext().initTS(Paths.get(TestConstants.TX_CACHE, vString).toString());
final ValidationEngine validationEngine = new ValidationEngine(src, txsrvr, txLog, Paths.get(TestConstants.TX_CACHE, vString).toString(), version, vString, userAgent);
TerminologyCache.setCacheErrors(true);
validationEngine.getContext().setUserAgent("fhir/test-cases");
return validationEngine;

View File

@ -0,0 +1,39 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"extension" : [{
"url" : "http://hl7.org/fhir/3.0/StructureDefinition/extension-CapabilityStatement.acceptUnknown",
"valueCode" : "both"
}],
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "1.0.2-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-06T15:44:28.286Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"description" : "Standard Conformance Statement for the open source Reference FHIR Server provided by Health Intersections",
"kind" : "instance",
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "1.0.2",
"format" : ["application/xml+fhir",
"application/json+fhir"],
"rest" : [{
"mode" : "server"
}]
}

View File

@ -0,0 +1,66 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"extension" : [{
"url" : "http://hl7.org/fhir/3.0/StructureDefinition/extension-CapabilityStatement.acceptUnknown",
"valueCode" : "both"
}],
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "3.0.2-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:02:52.097Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "3.0.2",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}

View File

@ -0,0 +1,66 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"extension" : [{
"url" : "http://hl7.org/fhir/3.0/StructureDefinition/extension-CapabilityStatement.acceptUnknown",
"valueCode" : "both"
}],
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "3.0.2-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:02:52.097Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "3.0.2",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}

View File

@ -0,0 +1,62 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "4.0.1-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:07:19.254Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "4.0.1",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}

View File

@ -0,0 +1,62 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "4.0.1-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:07:19.254Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "4.0.1",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}

View File

@ -0,0 +1,62 @@
{
"resourceType" : "CapabilityStatement",
"id" : "FhirServer",
"meta" : {
"tag" : [{
"system" : "http://hl7.org/fhir/v3/ObservationValue",
"code" : "SUBSETTED",
"display" : "Subsetted"
}]
},
"url" : "http://fhir.healthintersections.com.au/open/metadata",
"version" : "4.0.1-2.0.12-SNAPSHOT",
"name" : "FHIR Reference Server Conformance Statement",
"status" : "active",
"date" : "2022-01-10T11:07:19.254Z",
"contact" : [{
"telecom" : [{
"system" : "other",
"value" : "http://healthintersections.com.au/"
}]
}],
"kind" : "instance",
"instantiates" : ["http://hl7.org/fhir/CapabilityStatement/terminology-server"],
"software" : {
"name" : "Reference Server",
"version" : "2.0.12-SNAPSHOT",
"releaseDate" : "2021-12-20T02:28:03.769Z"
},
"fhirVersion" : "4.0.1",
"format" : ["application/fhir+xml",
"application/fhir+json"],
"rest" : [{
"mode" : "server",
"security" : {
"cors" : true
},
"operation" : [{
"name" : "expand",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-expand"
},
{
"name" : "lookup",
"definition" : "http://hl7.org/fhir/OperationDefinition/ValueSet-lookup"
},
{
"name" : "validate-code",
"definition" : "http://hl7.org/fhir/OperationDefinition/Resource-validate"
},
{
"name" : "translate",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-translate"
},
{
"name" : "closure",
"definition" : "http://hl7.org/fhir/OperationDefinition/ConceptMap-closure"
},
{
"name" : "versions",
"definition" : "/OperationDefinition/fso-versions"
}]
}]
}