Merge remote-tracking branch 'origin/master' into do-20240327-language-translation-coverage

This commit is contained in:
dotasek.dev 2024-04-23 11:46:52 -04:00
commit dab6150e9a
29 changed files with 342 additions and 43 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -125,6 +125,7 @@ import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext.Termi
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.CacheToken;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedCodeSystem;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
import org.hl7.fhir.r5.terminologies.validation.VSCheckerException;
import org.hl7.fhir.r5.terminologies.validation.ValueSetValidator;
@ -3234,6 +3235,28 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
cacheResource(svs.getVs());
return (T) svs.getVs();
}
} else if (class_ == CodeSystem.class) {
SourcedCodeSystem scs = null;
if (txCache.hasCodeSystem(canonical)) {
scs = txCache.getCodeSystem(canonical);
} else {
scs = terminologyClientManager.findCodeSystemOnServer(canonical);
txCache.cacheCodeSystem(canonical, scs);
}
if (scs != null) {
String web = ToolingExtensions.readStringExtension(scs.getCs(), ToolingExtensions.EXT_WEB_SOURCE);
if (web == null) {
web = Utilities.pathURL(scs.getServer(), "ValueSet", scs.getCs().getIdBase());
}
scs.getCs().setWebPath(web);
scs.getCs().setUserData("External.Link", scs.getServer()); // so we can render it differently
}
if (scs == null) {
return null;
} else {
cacheResource(scs.getCs());
return (T) scs.getCs();
}
} else {
throw new Error("Not supported");
}

View File

@ -332,12 +332,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
loadBytes(name, stream);
}
public void connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client) {
public void connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client, boolean useEcosystem) {
terminologyClientManager.setFactory(factory);
if (txLog == null) {
txLog = client.getLogger();
}
TerminologyClientContext tcc = terminologyClientManager.setMasterClient(client);
TerminologyClientContext tcc = terminologyClientManager.setMasterClient(client, useEcosystem);
txLog("Connect to "+client.getAddress());
try {
tcc.initialize();
@ -357,7 +357,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
}
public void connectToTSServer(ITerminologyClientFactory factory, String address, String software, String log) {
public void connectToTSServer(ITerminologyClientFactory factory, String address, String software, String log, boolean useEcosystem) {
try {
terminologyClientManager.setFactory(factory);
if (log != null && (log.endsWith(".htm") || log.endsWith(".html"))) {
@ -369,7 +369,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
// txFactory.makeClient("Tx-Server", txServer, "fhir/publisher", null)
// terminologyClientManager.setLogger(txLog);
// terminologyClientManager.setUserAgent(userAgent);
connectToTSServer(factory, client);
connectToTSServer(factory, client, useEcosystem);
} catch (Exception e) {
e.printStackTrace();

View File

@ -71,9 +71,42 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
public class CodeSystemUtilities extends TerminologyUtilities {
public static class CodeSystemSorter implements Comparator<CodeSystem> {
@Override
public int compare(CodeSystem o1, CodeSystem o2) {
String url1 = o1.getUrl();
String url2 = o2.getUrl();
int c = compareString(url1, url2);
if (c == 0) {
String ver1 = o1.getVersion();
String ver2 = o2.getVersion();
c = VersionUtilities.compareVersions(ver1, ver2);
if (c == 0) {
String d1 = o1.getDateElement().asStringValue();
String d2 = o2.getDateElement().asStringValue();
c = compareString(url1, url2);
}
}
return c;
}
private int compareString(String s1, String s2) {
if (s1 == null) {
return s2 == null ? 0 : 1;
} else {
return s1.compareTo(s2);
}
}
}
public static class SystemReference {
private String link;
private String text;

View File

@ -16,19 +16,26 @@ import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
public class TerminologyClientContext {
public enum TerminologyClientContextUseType {
expand, validate, readVS
expand, validate, readVS, readCS
}
public class TerminologyClientContextUseCount {
private int expands;
private int validates;
private int readVS;
private int readCS;
public int getReadVS() {
return readVS;
}
public void setReadVS(int readVS) {
this.readVS = readVS;
}
public int getReadCS() {
return readCS;
}
public void setReadCS(int readCS) {
this.readCS = readCS;
}
public int getExpands() {
return expands;
}
@ -94,6 +101,9 @@ public class TerminologyClientContext {
case readVS:
uc.readVS++;
break;
case readCS:
uc.readCS++;
break;
case validate:
uc.validates++;
break;

View File

@ -17,15 +17,18 @@ import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.CanonicalResourceManager;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r5.model.CodeSystem;
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.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext.TerminologyClientContextUseType;
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.ServerOptionList;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedCodeSystem;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
@ -100,6 +103,8 @@ public class TerminologyClientManager {
private String monitorServiceURL;
private boolean useEcosystem;
public TerminologyClientManager(ITerminologyClientFactory factory, String cacheId) {
super();
this.factory = factory;
@ -115,6 +120,7 @@ public class TerminologyClientManager {
serverList.addAll(other.serverList);
serverMap.putAll(other.serverMap);
resMap.putAll(other.resMap);
useEcosystem = other.useEcosystem;
monitorServiceURL = other.monitorServiceURL;
factory = other.factory;
usage = other.usage;
@ -238,7 +244,7 @@ public class TerminologyClientManager {
}
private ServerOptionList decideWhichServer(String url) {
if (IGNORE_TX_REGISTRY) {
if (IGNORE_TX_REGISTRY || !useEcosystem) {
return new ServerOptionList(getMasterClient().getAddress());
}
if (expParameters != null) {
@ -315,7 +321,8 @@ public class TerminologyClientManager {
}
}
public TerminologyClientContext setMasterClient(ITerminologyClient client) {
public TerminologyClientContext setMasterClient(ITerminologyClient client, boolean useEcosystem) {
this.useEcosystem = useEcosystem;
TerminologyClientContext details = new TerminologyClientContext(client, cacheId, true);
details.setTxCache(cache);
serverList.clear();
@ -419,7 +426,7 @@ public class TerminologyClientManager {
}
public SourcedValueSet findValueSetOnServer(String canonical) {
if (IGNORE_TX_REGISTRY || getMasterClient() == null) {
if (IGNORE_TX_REGISTRY || getMasterClient() == null || !useEcosystem) {
return null;
}
String request = Utilities.pathURL(monitorServiceURL, "resolve?fhirVersion="+factory.getVersion()+"&valueSet="+Utilities.URLEncode(canonical));
@ -498,6 +505,86 @@ public class TerminologyClientManager {
}
}
public SourcedCodeSystem findCodeSystemOnServer(String canonical) {
if (IGNORE_TX_REGISTRY || getMasterClient() == null || !useEcosystem) {
return null;
}
String request = Utilities.pathURL(monitorServiceURL, "resolve?fhirVersion="+factory.getVersion()+"&url="+Utilities.URLEncode(canonical));
if (usage != null) {
request = request + "&usage="+usage;
}
String server = null;
try {
JsonObject json = JsonParser.parseObjectFromUrl(request);
for (JsonObject item : json.getJsonObjects("authoritative")) {
if (server == null) {
server = item.asString("url");
}
}
for (JsonObject item : json.getJsonObjects("candidates")) {
if (server == null) {
server = item.asString("url");
}
}
if (server == null) {
return null;
}
if (server.contains("://tx.fhir.org")) {
try {
server = server.replace("tx.fhir.org", new URL(getMasterClient().getAddress()).getHost());
} catch (MalformedURLException e) {
}
}
TerminologyClientContext client = serverMap.get(server);
if (client == null) {
try {
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.readCS);
String criteria = canonical.contains("|") ?
"?_format=json&url="+Utilities.URLEncode(canonical.substring(0, canonical.lastIndexOf("|")))+"&version="+Utilities.URLEncode(canonical.substring(canonical.lastIndexOf("|")+1)):
"?_format=json&url="+Utilities.URLEncode(canonical);
request = Utilities.pathURL(client.getAddress(), "CodeSystem"+ criteria);
Bundle bnd = client.getClient().search("CodeSystem", criteria);
String rid = null;
if (bnd.getEntry().size() == 0) {
return null;
} else if (bnd.getEntry().size() > 1) {
List<CodeSystem> cslist = new ArrayList<>();
for (BundleEntryComponent be : bnd.getEntry()) {
if (be.hasResource() && be.getResource() instanceof CodeSystem) {
cslist.add((CodeSystem) be.getResource());
}
}
Collections.sort(cslist, new CodeSystemUtilities.CodeSystemSorter());
rid = cslist.get(cslist.size()-1).getIdBase();
} else {
if (bnd.getEntryFirstRep().hasResource() && bnd.getEntryFirstRep().getResource() instanceof CodeSystem) {
rid = bnd.getEntryFirstRep().getResource().getIdBase();
}
}
if (rid == null) {
return null;
}
CodeSystem vs = (CodeSystem) client.getClient().read("CodeSystem", rid);
return new SourcedCodeSystem(server, vs);
} catch (Exception e) {
e.printStackTrace();
String msg = "Error resolving valueSet "+canonical+": "+e.getMessage()+" ("+request+")";
if (!internalLog.contains(msg)) {
internalLog.add(msg);
}
e.printStackTrace();
return null;
}
}
public boolean supportsSystem(String system) throws IOException {
for (TerminologyClientContext client : serverList) {
if (client.supportsSystem(system)) {

View File

@ -83,6 +83,42 @@ import com.google.gson.JsonPrimitive;
*/
public class TerminologyCache {
public static class SourcedCodeSystem {
private String server;
private CodeSystem cs;
public SourcedCodeSystem(String server, CodeSystem cs) {
super();
this.server = server;
this.cs = cs;
}
public String getServer() {
return server;
}
public CodeSystem getCs() {
return cs;
}
}
public static class SourcedCodeSystemEntry {
private String server;
private String filename;
public SourcedCodeSystemEntry(String server, String filename) {
super();
this.server = server;
this.filename = filename;
}
public String getServer() {
return server;
}
public String getFilename() {
return filename;
}
}
public static class SourcedValueSet {
private String server;
private ValueSet vs;
@ -253,6 +289,7 @@ public class TerminologyCache {
private Map<String, TerminologyCapabilities> terminologyCapabilitiesCache = new HashMap<>();
private Map<String, NamedCache> caches = new HashMap<String, NamedCache>();
private Map<String, SourcedValueSetEntry> vsCache = new HashMap<>();
private Map<String, SourcedCodeSystemEntry> csCache = new HashMap<>();
private Map<String, String> serverMap = new HashMap<>();
@Getter @Setter private static boolean noCaching;
@ -320,12 +357,14 @@ public class TerminologyCache {
// not useable after this is called
caches.clear();
vsCache.clear();
csCache.clear();
}
private void clear() throws IOException {
Utilities.clearDirectory(folder);
caches.clear();
vsCache.clear();
csCache.clear();
}
public boolean hasCapabilityStatement(String address) {
@ -872,6 +911,22 @@ public class TerminologyCache {
} catch (Exception e) {
System.out.println("Error loading vs external cache: "+e.getMessage());
}
try {
File f = ManagedFileAccess.file(Utilities.path(folder, "cs-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()) {
csCache.put(p.getName(), null);
} else {
org.hl7.fhir.utilities.json.model.JsonObject j = p.getValue().asJsonObject();
csCache.put(p.getName(), new SourcedCodeSystemEntry(j.asString("server"), j.asString("filename")));
}
}
}
} catch (Exception e) {
System.out.println("Error loading vs external cache: "+e.getMessage());
}
}
private String loadJS(JsonElement e) {
@ -978,6 +1033,10 @@ public class TerminologyCache {
return vsCache.containsKey(canonical);
}
public boolean hasCodeSystem(String canonical) {
return csCache.containsKey(canonical);
}
public SourcedValueSet getValueSet(String canonical) {
SourcedValueSetEntry sp = vsCache.get(canonical);
if (sp == null) {
@ -991,6 +1050,19 @@ public class TerminologyCache {
}
}
public SourcedCodeSystem getCodeSystem(String canonical) {
SourcedCodeSystemEntry sp = csCache.get(canonical);
if (sp == null) {
return null;
} else {
try {
return new SourcedCodeSystem(sp.getServer(), sp.getFilename() == null ? null : (CodeSystem) new JsonParser().parse(ManagedFileAccess.inStream(Utilities.path(folder, sp.getFilename()))));
} catch (Exception e) {
return null;
}
}
}
public void cacheValueSet(String canonical, SourcedValueSet svs) {
if (canonical == null) {
return;
@ -1024,6 +1096,39 @@ public class TerminologyCache {
}
}
public void cacheCodeSystem(String canonical, SourcedCodeSystem scs) {
if (canonical == null) {
return;
}
try {
if (scs == null) {
csCache.put(canonical, null);
} else {
String uuid = Utilities.makeUuidLC();
String fn = "cs-"+uuid+".json";
new JsonParser().compose(ManagedFileAccess.outStream(Utilities.path(folder, fn)), scs.getCs());
csCache.put(canonical, new SourcedCodeSystemEntry(scs.getServer(), fn));
}
org.hl7.fhir.utilities.json.model.JsonObject j = new org.hl7.fhir.utilities.json.model.JsonObject();
for (String k : csCache.keySet()) {
SourcedCodeSystemEntry sve = csCache.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);
}
}
org.hl7.fhir.utilities.json.parser.JsonParser.compose(j, ManagedFileAccess.file(Utilities.path(folder, "cs-externals.json")), true);
} catch (Exception e) {
e.printStackTrace();
}
}
public CacheToken generateSubsumesToken(ValidationOptions options, Coding parent, Coding child, Parameters expParameters) {
try {
CacheToken ct = new CacheToken();

View File

@ -97,7 +97,7 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(DUMMY_URL).when(terminologyClient).getAddress();
context.initTxCache(terminologyCache);
context.expParameters = expParameters;
context.terminologyClientManager.setMasterClient(terminologyClient);
context.terminologyClientManager.setMasterClient(terminologyClient, false);
context.txLog = txLog;
}
@ -437,7 +437,7 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(terminologyCapabilities).when(terminologyCache).getTerminologyCapabilities(address);
context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient);
context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient, false);
Mockito.verify(terminologyCache).getTerminologyCapabilities(address);
Mockito.verify(terminologyClient).getCapabilitiesStatementQuick();
@ -455,7 +455,7 @@ public class SimpleWorkerContextTests {
Mockito.doReturn(terminologyCapabilities).when(terminologyClient).getTerminologyCapabilities();
Mockito.doReturn(capabilitiesStatement).when(terminologyClient).getCapabilitiesStatementQuick();
context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient);
context.connectToTSServer(new TerminologyClientR5Factory(), terminologyClient, false);
Mockito.verify(terminologyCache, times(0)).getTerminologyCapabilities(address);
Mockito.verify(terminologyCache, times(0)).getCapabilityStatement(address);

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -1125,7 +1125,7 @@ CODESYSTEM_PROPERTY_WRONG_TYPE = The property ''{0}'' has the invalid type ''{1}
CODESYSTEM_DESIGNATION_DISP_CLASH_NO_LANG = The designation ''{0}'' has no use and no language, so is not differentiated from the base display (''{1}'')
CODESYSTEM_DESIGNATION_DISP_CLASH_LANG = The designation ''{0}'' has no use and is in the same language (''{2}''), so is not differentiated from the base display (''{1}'')
VALUESET_UNKNOWN_FILTER_PROPERTY = The property ''{0}'' is not known for the system ''{1}'', so may not be understood by the terminology ecosystem. Known properties for this system: {2}
VALUESET_UNKNOWN_FILTER_PROPERTY_NO_CS = No definition can be found for the system {1}, and the property ''{0}'' is not a generally known property, so the property might not be valid, or understood by the terminology ecosystem. In case it's useful, the list of generally known properties for all systems is {2}
VALUESET_UNKNOWN_FILTER_PROPERTY_NO_CS = No definition can be found for the system {1}, and the property ''{0}'' is not a generally known property, so the property might not be valid, or understood by the terminology ecosystem. In case it''s useful, the list of generally known properties for all systems is {2}
VALUESET_BAD_FILTER_VALUE_BOOLEAN = The value for a filter based on property ''{0}'' must be either ''true'' or ''false'', not ''{1}''
VALUESET_BAD_FILTER_VALUE_CODE = The value for a filter based on property ''{0}'' must be a valid code, not ''{1}''
VALUESET_BAD_FILTER_VALUE_DATETIME = The value for a filter based on property ''{0}'' must be a valid date(/time), not ''{1}''

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -161,7 +161,7 @@ public class NativeHostServices {
* @throws Exception
*/
public void connectToTxSvc(String txServer, String log) throws Exception {
validator.connectToTSServer(txServer, log, FhirPublication.R5);
validator.connectToTSServer(txServer, log, FhirPublication.R5, false);
}
/**
@ -171,7 +171,7 @@ public class NativeHostServices {
* @throws Exception
*/
public void connectToTxSvc(String txServer, String log, String txCache) throws Exception {
validator.connectToTSServer(txServer, log, txCache, FhirPublication.R5);
validator.connectToTSServer(txServer, log, txCache, FhirPublication.R5, false);
}
/**

View File

@ -325,6 +325,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
private final String txServer;
private final String txLog;
private final FhirPublication txVersion;
private final boolean useEcosystem;
@With
private final TimeTracker timeTracker;
@ -348,10 +349,11 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
txVersion = null;
timeTracker = null;
canRunWithoutTerminologyServer = false;
useEcosystem = true;
loggingService = new SystemOutLoggingService();
}
public ValidationEngineBuilder(String terminologyCachePath, String userAgent, String version, String txServer, String txLog, FhirPublication txVersion, TimeTracker timeTracker, boolean canRunWithoutTerminologyServer, ILoggingService loggingService, boolean THO) {
public ValidationEngineBuilder(String terminologyCachePath, String userAgent, String version, String txServer, String txLog, FhirPublication txVersion, boolean useEcosystem, TimeTracker timeTracker, boolean canRunWithoutTerminologyServer, ILoggingService loggingService, boolean THO) {
this.terminologyCachePath = terminologyCachePath;
this.userAgent = userAgent;
this.version = version;
@ -361,15 +363,16 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
this.timeTracker = timeTracker;
this.canRunWithoutTerminologyServer = canRunWithoutTerminologyServer;
this.loggingService = loggingService;
this.useEcosystem = true;
this.THO = THO;
}
public ValidationEngineBuilder withTxServer(String txServer, String txLog, FhirPublication txVersion) {
return new ValidationEngineBuilder(terminologyCachePath, userAgent, version, txServer, txLog, txVersion, timeTracker, canRunWithoutTerminologyServer, loggingService, THO);
public ValidationEngineBuilder withTxServer(String txServer, String txLog, FhirPublication txVersion, boolean useEcosystem) {
return new ValidationEngineBuilder(terminologyCachePath, userAgent, version, txServer, txLog, txVersion, useEcosystem, timeTracker, canRunWithoutTerminologyServer, loggingService, THO);
}
public ValidationEngineBuilder withNoTerminologyServer() {
return new ValidationEngineBuilder(terminologyCachePath, userAgent, version, null, null, txVersion, timeTracker, true, loggingService, THO);
return new ValidationEngineBuilder(terminologyCachePath, userAgent, version, null, null, txVersion, useEcosystem, timeTracker, true, loggingService, THO);
}
public ValidationEngine fromNothing() throws IOException {
@ -393,7 +396,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
engine.getContext().setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
engine.getContext().setPackageTracker(engine);
if (txServer != null) {
engine.setTerminologyServer(txServer, txLog, txVersion);
engine.setTerminologyServer(txServer, txLog, txVersion, useEcosystem);
}
engine.setVersion(version);
engine.setIgLoader(new IgLoader(engine.getPcm(), engine.getContext(), engine.getVersion(), engine.isDebug()));
@ -514,11 +517,11 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
return ep;
}
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, FhirPublication version, boolean useEcosystem) throws URISyntaxException, IOException, FHIRException {
return connectToTSServer(url, log, null, version, useEcosystem);
}
public String connectToTSServer(String url, String log, String txCachePath, FhirPublication version) throws URISyntaxException, IOException, FHIRException {
public String connectToTSServer(String url, String log, String txCachePath, FhirPublication version, boolean useEcosystem) throws URISyntaxException, IOException, FHIRException {
context.setTlogging(false);
if (url == null) {
context.setCanRunWithoutTerminology(true);
@ -527,7 +530,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
} else {
try {
TerminologyClientFactory factory = new TerminologyClientFactory(version);
context.connectToTSServer(factory, url, context.getUserAgent(), log);
context.connectToTSServer(factory, url, context.getUserAgent(), log, useEcosystem);
return "Connected to Terminology Server at "+url;
} catch (Exception e) {
if (context.isCanRunWithoutTerminology()) {
@ -1044,8 +1047,8 @@ 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, IOException {
return connectToTSServer(src, log, version);
public String setTerminologyServer(String src, String log, FhirPublication version, boolean useEcosystem) throws FHIRException, URISyntaxException, IOException {
return connectToTSServer(src, log, version, useEcosystem);
}
public ValidationEngine setMapLog(String mapLog) throws FileNotFoundException {

View File

@ -88,6 +88,8 @@ public class CliContext {
private String snomedCT = "900000000000207008";
@JsonProperty("targetVer")
private String targetVer = null;
@JsonProperty("noEcosystem")
private boolean noEcosystem = false;
@JsonProperty("extensions")
private List<String> extensions = new ArrayList<String>();
@ -245,6 +247,17 @@ public class CliContext {
return this;
}
@JsonProperty("txServer")
public boolean getNoEcosystem() {
return noEcosystem;
}
@JsonProperty("txServer")
public CliContext setNoEcosystem(boolean noEcosystem) {
this.noEcosystem = noEcosystem;
return this;
}
@JsonProperty("doNative")
public boolean isDoNative() {
return doNative;

View File

@ -493,6 +493,11 @@ public class ValidationService {
System.out.println(" - " + validationEngine.getContext().countAllCaches() + " resources (" + timeTracker.milestone() + ")");
loadIgsAndExtensions(validationEngine, cliContext, timeTracker);
if (validationEngine.getContext().getTxCache() == null) {
System.out.println(" No Terminology Cache");
} else {
System.out.println(" Terminology Cache at "+validationEngine.getContext().getTxCache().getFolder());
}
System.out.print(" Get set... ");
validationEngine.setQuestionnaireMode(cliContext.getQuestionnaireMode());
validationEngine.setLevel(cliContext.getLevel());
@ -546,7 +551,7 @@ public class ValidationService {
igLoader.loadIg(validationEngine.getIgs(), validationEngine.getBinaries(), "hl7.fhir.uv.extensions", false);
}
System.out.print(" Terminology server " + cliContext.getTxServer());
String txver = validationEngine.setTerminologyServer(cliContext.getTxServer(), cliContext.getTxLog(), ver);
String txver = validationEngine.setTerminologyServer(cliContext.getTxServer(), cliContext.getTxLog(), ver, !cliContext.getNoEcosystem());
System.out.println(" - Version " + txver + " (" + timeTracker.milestone() + ")");
validationEngine.setDebug(cliContext.isDoDebug());
validationEngine.getContext().setLogger(new SystemOutLoggingService(cliContext.isDoDebug()));

View File

@ -340,8 +340,10 @@ public class Params {
} else if (args[i].equals(TERMINOLOGY)) {
if (i + 1 == args.length)
throw new Error("Specified -tx without indicating terminology server");
else
else {
cliContext.setTxServer("n/a".equals(args[++i]) ? null : args[i]);
cliContext.setNoEcosystem(true);
}
} else if (args[i].equals(TERMINOLOGY_LOG)) {
if (i + 1 == args.length)
throw new Error("Specified -txLog without indicating file");

View File

@ -256,6 +256,10 @@ public class ValueSetValidator extends BaseValidator {
CodeSystem cs = null;
if (!Utilities.noString(system)) {
cs = context.fetchCodeSystem(system, version);
if (cs == null) {
// can we get it from a terminology server?
cs = context.findTxResource(CodeSystem.class, system, version);
}
if (cs != null) { // if it's null, we can't analyse this
switch (cs.getContent()) {
case EXAMPLE:

View File

@ -22,7 +22,7 @@ public class TestUtilities {
.withVersion(vString)
.withUserAgent(TestConstants.USER_AGENT)
.withTerminologyCachePath(getTerminologyCacheDirectory(vString))
.withTxServer(txServer, txLog, version)
.withTxServer(txServer, txLog, version, false)
.fromSource(src);
TerminologyCache.setCacheErrors(true);
@ -59,7 +59,7 @@ public class TestUtilities {
.withVersion(vString)
.withUserAgent(TestConstants.USER_AGENT)
.withTerminologyCachePath(getTerminologyCacheDirectory(vString))
.withTxServer(txServer, TestConstants.TX_CACHE_LOG, version)
.withTxServer(txServer, TestConstants.TX_CACHE_LOG, version, false)
.fromSource(src);
TerminologyCache.setCacheErrors(true);
}

View File

@ -0,0 +1,8 @@
{
"#f3b2bd36-199b-4591-b4db-f49db0912b6|null" : null,
"#c1|null" : null,
"http://something/something|null" : null,
"http://hl7.org/fhir/CodeSystem/c1|null" : null,
"http://hl7.org/fhir/uv/sdc/CodeSystem/CSPHQ9|null" : null,
"#f3b2bd36-199b-4591-b4db-f49db0912b62|null" : null
}

View File

@ -0,0 +1,6 @@
{
"#cs1|null" : null,
"#cs|null" : null,
"http://something|null" : null,
"http://snomed.info/sct|null" : null
}

View File

@ -14,14 +14,14 @@
HAPI FHIR
-->
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.6-SNAPSHOT</version>
<version>6.3.7-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<commons_compress_version>1.26.0</commons_compress_version>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.5.6-SNAPSHOT</validator_test_case_version>
<validator_test_case_version>1.5.6</validator_test_case_version>
<jackson_version>2.17.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>