cache CapabilityStatement and TerminologyCapabilities
This commit is contained in:
parent
6e0b14b0b6
commit
d9d0f22ff3
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -363,12 +401,29 @@ public class TerminologyCache {
|
|||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}]
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}]
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}]
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}]
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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"
|
||||
}]
|
||||
}]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue