Fix bug handling filter, and refactor terminology code
This commit is contained in:
parent
551fe6d7c0
commit
b402fd1c45
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.convertors.misc;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
|
@ -2,7 +2,7 @@ package org.hl7.fhir.convertors.txClient;
|
|||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
@ -10,7 +10,7 @@ import org.hl7.fhir.utilities.VersionUtilities;
|
|||
|
||||
public class TerminologyClientFactory {
|
||||
|
||||
public static TerminologyClient makeClient(String id, String url, String userAgent, FhirPublication v) throws URISyntaxException {
|
||||
public static ITerminologyClient makeClient(String id, String url, String userAgent, FhirPublication v) throws URISyntaxException {
|
||||
if (v == null)
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent);
|
||||
switch (v) {
|
||||
|
@ -33,7 +33,7 @@ public class TerminologyClientFactory {
|
|||
}
|
||||
}
|
||||
|
||||
public static TerminologyClient makeClient(String id, String url, String userAgent, String v) throws URISyntaxException {
|
||||
public static ITerminologyClient makeClient(String id, String url, String userAgent, String v) throws URISyntaxException {
|
||||
if (v == null)
|
||||
return new TerminologyClientR5(id, checkEndsWith("/r4", url), userAgent);
|
||||
v = VersionUtilities.getMajMin(v);
|
||||
|
|
|
@ -45,13 +45,13 @@ import org.hl7.fhir.r5.model.CapabilityStatement;
|
|||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class TerminologyClientR2 implements TerminologyClient {
|
||||
public class TerminologyClientR2 implements ITerminologyClient {
|
||||
|
||||
private final FHIRToolingClient client; // todo: use the R2 client
|
||||
private String id;
|
||||
|
@ -125,19 +125,19 @@ public class TerminologyClientR2 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setTimeout(int i) {
|
||||
public ITerminologyClient setTimeout(int i) {
|
||||
client.setTimeout(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
public ITerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
client.setRetryCount(retryCount);
|
||||
return this;
|
||||
}
|
||||
|
@ -190,12 +190,12 @@ public class TerminologyClientR2 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setUserAgent(String userAgent) {
|
||||
public ITerminologyClient setUserAgent(String userAgent) {
|
||||
client.setUserAgent(userAgent);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -45,13 +45,13 @@ import org.hl7.fhir.r5.model.CapabilityStatement;
|
|||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class TerminologyClientR3 implements TerminologyClient {
|
||||
public class TerminologyClientR3 implements ITerminologyClient {
|
||||
|
||||
private final FHIRToolingClient client; // todo: use the R2 client
|
||||
private ClientHeaders clientHeaders;
|
||||
|
@ -123,19 +123,19 @@ public class TerminologyClientR3 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setTimeout(int i) {
|
||||
public ITerminologyClient setTimeout(int i) {
|
||||
client.setTimeout(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
public ITerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
client.setRetryCount(retryCount);
|
||||
return this;
|
||||
}
|
||||
|
@ -188,14 +188,14 @@ public class TerminologyClientR3 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
this.clientHeaders = clientHeaders;
|
||||
this.client.setClientHeaders(this.clientHeaders.headers());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setUserAgent(String userAgent) {
|
||||
public ITerminologyClient setUserAgent(String userAgent) {
|
||||
client.setUserAgent(userAgent);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -48,13 +48,13 @@ import org.hl7.fhir.r5.model.CapabilityStatement;
|
|||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class TerminologyClientR4 implements TerminologyClient {
|
||||
public class TerminologyClientR4 implements ITerminologyClient {
|
||||
|
||||
private final FHIRToolingClient client; // todo: use the R2 client
|
||||
private ClientHeaders clientHeaders;
|
||||
|
@ -139,19 +139,19 @@ public class TerminologyClientR4 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setTimeout(int i) {
|
||||
public ITerminologyClient setTimeout(int i) {
|
||||
client.setTimeout(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
public ITerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
client.setRetryCount(retryCount);
|
||||
return this;
|
||||
}
|
||||
|
@ -204,14 +204,14 @@ public class TerminologyClientR4 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
this.clientHeaders = clientHeaders;
|
||||
this.client.setClientHeaders(this.clientHeaders.headers());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setUserAgent(String userAgent) {
|
||||
public ITerminologyClient setUserAgent(String userAgent) {
|
||||
client.setUserAgent(userAgent);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -43,14 +43,14 @@ import org.hl7.fhir.r5.model.Parameters;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class TerminologyClientR5 implements TerminologyClient {
|
||||
public class TerminologyClientR5 implements ITerminologyClient {
|
||||
|
||||
private final FHIRToolingClient client;
|
||||
private ClientHeaders clientHeaders;
|
||||
|
@ -117,13 +117,13 @@ public class TerminologyClientR5 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setTimeout(int i) {
|
||||
public ITerminologyClient setTimeout(int i) {
|
||||
client.setTimeout(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
public ITerminologyClient setLogger(ToolingClientLogger txLog) {
|
||||
client.setLogger(txLog);
|
||||
return this;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public class TerminologyClientR5 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
public ITerminologyClient setRetryCount(int retryCount) throws FHIRException {
|
||||
client.setRetryCount(retryCount);
|
||||
return this;
|
||||
}
|
||||
|
@ -178,14 +178,14 @@ public class TerminologyClientR5 implements TerminologyClient {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
public ITerminologyClient setClientHeaders(ClientHeaders clientHeaders) {
|
||||
this.clientHeaders = clientHeaders;
|
||||
this.client.setClientHeaders(this.clientHeaders.headers());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerminologyClient setUserAgent(String userAgent) {
|
||||
public ITerminologyClient setUserAgent(String userAgent) {
|
||||
client.setUserAgent(userAgent);
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.hl7.fhir.convertors.txClient;
|
||||
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
@ -52,14 +52,14 @@ public class TerminologyClientFactoryTest {
|
|||
@ParameterizedTest
|
||||
@MethodSource("data")
|
||||
public void testMakeClient(String url, FhirPublication fhirPublication, String expectedAddress) throws URISyntaxException {
|
||||
TerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", url, "dummyUserAgent", fhirPublication);
|
||||
ITerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", url, "dummyUserAgent", fhirPublication);
|
||||
assertEquals(expectedAddress, terminologyClient.getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMakeClientDstu1Fails() throws URISyntaxException {
|
||||
assertThrows(Error.class, () -> {
|
||||
TerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", "urldoesnotmatter", "dummyUserAgent", FhirPublication.DSTU1);
|
||||
ITerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", "urldoesnotmatter", "dummyUserAgent", FhirPublication.DSTU1);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class TerminologyClientFactoryTest {
|
|||
@Test
|
||||
public void testMakeClientNullFails() throws URISyntaxException {
|
||||
assertThrows(Error.class, () -> {
|
||||
TerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", "urldoesnotmatter", "dummyUserAgent", FhirPublication.NULL);
|
||||
ITerminologyClient terminologyClient = TerminologyClientFactory.makeClient("id", "urldoesnotmatter", "dummyUserAgent", FhirPublication.NULL);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
|
|
@ -41,7 +41,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.model.*;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.stringtemplate.v4.ST;
|
||||
|
||||
|
@ -1848,7 +1848,7 @@ public class ShExGenerator {
|
|||
*/
|
||||
private String genValueSet(ValueSet vs) {
|
||||
ST vsd = tmplt(VALUE_SET_DEFINITION).add("vsuri", vsprefix(vs.getUrl())).add("comment", vs.getDescription());
|
||||
ValueSetExpander.ValueSetExpansionOutcome vse = context.expandVS(vs, true, false);
|
||||
ValueSetExpansionOutcome vse = context.expandVS(vs, true, false);
|
||||
List<String> valid_codes = new ArrayList<String>();
|
||||
if(vse != null &&
|
||||
vse.getValueset() != null &&
|
||||
|
|
|
@ -89,7 +89,7 @@ import org.hl7.fhir.r5.model.UriType;
|
|||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.TranslatingUtilities;
|
||||
|
|
|
@ -110,12 +110,14 @@ import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
|||
import org.hl7.fhir.r5.profilemodel.PEBuilder;
|
||||
import org.hl7.fhir.r5.renderers.OperationOutcomeRenderer;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetCheckerSimple;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetCheckerSimple.VSCheckerException;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpander;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.validation.VSCheckerException;
|
||||
import org.hl7.fhir.r5.terminologies.validation.ValueSetValidator;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientContext;
|
||||
import org.hl7.fhir.r5.utils.PackageHackerR5;
|
||||
import org.hl7.fhir.r5.utils.ResourceUtilities;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
@ -205,11 +207,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
private Object lock = new Object(); // used as a lock for the data that follows
|
||||
protected String version; // although the internal resources are all R5, the version of FHIR they describe may not be
|
||||
private String cacheId;
|
||||
private boolean isTxCaching;
|
||||
@Getter
|
||||
private int serverQueryCount = 0;
|
||||
private final Set<String> cached = new HashSet<>();
|
||||
|
||||
protected TerminologyClientContext tcc = new TerminologyClientContext();
|
||||
|
||||
private Map<String, Map<String, ResourceProxy>> allResourcesById = new HashMap<String, Map<String, ResourceProxy>>();
|
||||
// all maps are to the full URI
|
||||
|
@ -239,14 +238,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
protected Map<String, String> oidCache = new HashMap<>();
|
||||
|
||||
protected Map<String, Map<String, ValidationResult>> validationCache = new HashMap<String, Map<String,ValidationResult>>();
|
||||
protected String tsServer;
|
||||
protected String name;
|
||||
private boolean allowLoadingDuplicates;
|
||||
|
||||
protected TerminologyClient txClient;
|
||||
private final Set<String> codeSystemsUsed = new HashSet<>();
|
||||
protected ToolingClientLogger txLog;
|
||||
private TerminologyCapabilities txcaps;
|
||||
private boolean canRunWithoutTerminology;
|
||||
protected boolean noTerminologyServer;
|
||||
private int expandCodesLimit = 1000;
|
||||
|
@ -288,7 +284,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
allResourcesById.putAll(other.allResourcesById);
|
||||
translator = other.translator;
|
||||
codeSystems.copy(other.codeSystems);
|
||||
txcaps = other.txcaps;
|
||||
valueSets.copy(other.valueSets);
|
||||
maps.copy(other.maps);
|
||||
transforms.copy(other.transforms);
|
||||
|
@ -305,11 +300,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
libraries.copy(libraries);
|
||||
|
||||
allowLoadingDuplicates = other.allowLoadingDuplicates;
|
||||
tsServer = other.tsServer;
|
||||
name = other.name;
|
||||
txClient = other.txClient;
|
||||
txLog = other.txLog;
|
||||
txcaps = other.txcaps;
|
||||
canRunWithoutTerminology = other.canRunWithoutTerminology;
|
||||
noTerminologyServer = other.noTerminologyServer;
|
||||
if (other.txCache != null)
|
||||
|
@ -318,9 +310,6 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
logger = other.logger;
|
||||
expParameters = other.expParameters;
|
||||
version = other.version;
|
||||
cacheId = other.cacheId;
|
||||
isTxCaching = other.isTxCaching;
|
||||
cached.addAll(other.cached);
|
||||
supportedCodeSystems.addAll(other.supportedCodeSystems);
|
||||
unsupportedCodeSystems.addAll(other.unsupportedCodeSystems);
|
||||
codeSystemsUsed.addAll(other.codeSystemsUsed);
|
||||
|
@ -331,6 +320,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
tlogging = other.tlogging;
|
||||
locator = other.locator;
|
||||
userAgent = other.userAgent;
|
||||
tcc.copy(other.tcc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,18 +687,18 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (noTerminologyServer) {
|
||||
return false;
|
||||
}
|
||||
if (txcaps == null) {
|
||||
if (tcc.getTxcaps() == null) {
|
||||
try {
|
||||
logger.logMessage("Terminology server: Check for supported code systems for "+system);
|
||||
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : txClient.getTerminologyCapabilities();
|
||||
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : tcc.getClient().getTerminologyCapabilities();
|
||||
txCache.cacheTerminologyCapabilities(capabilityStatement);
|
||||
setTxCaps(capabilityStatement);
|
||||
} catch (Exception e) {
|
||||
if (canRunWithoutTerminology) {
|
||||
noTerminologyServer = true;
|
||||
logger.logMessage("==============!! Running without terminology server !! ==============");
|
||||
if (txClient!=null) {
|
||||
logger.logMessage("txServer = "+txClient.getId());
|
||||
if (tcc.getClient() != null) {
|
||||
logger.logMessage("txServer = "+tcc.getClient().getId());
|
||||
logger.logMessage("Error = "+e.getMessage()+"");
|
||||
}
|
||||
logger.logMessage("=====================================================================");
|
||||
|
@ -787,7 +777,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
params.put("_incomplete", "true");
|
||||
txLog("$expand on "+txCache.summary(vs));
|
||||
try {
|
||||
ValueSet result = txClient.expandValueset(vs, p, params);
|
||||
ValueSet result = tcc.getClient().expandValueset(vs, p, params);
|
||||
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
|
||||
} catch (Exception e) {
|
||||
res = new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.UNKNOWN);
|
||||
|
@ -855,7 +845,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
List<String> allErrors = new ArrayList<>();
|
||||
|
||||
// ok, first we try to expand locally
|
||||
ValueSetExpanderSimple vse = constructValueSetExpanderSimple();
|
||||
ValueSetExpander vse = constructValueSetExpanderSimple();
|
||||
res = null;
|
||||
try {
|
||||
res = vse.expand(vs, p);
|
||||
|
@ -878,7 +868,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
// if that failed, we try to expand on the server
|
||||
if (addDependentResources(p, vs)) {
|
||||
p.addParameter().setName("cache-id").setValue(new StringType(cacheId));
|
||||
p.addParameter().setName("cache-id").setValue(new StringType(tcc.getCacheId()));
|
||||
}
|
||||
|
||||
if (noTerminologyServer) {
|
||||
|
@ -889,7 +879,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
params.put("_incomplete", "true");
|
||||
txLog("$expand on "+txCache.summary(vs));
|
||||
try {
|
||||
ValueSet result = txClient.expandValueset(vs, p, params);
|
||||
ValueSet result = tcc.getClient().expandValueset(vs, p, params);
|
||||
if (!result.hasUrl()) {
|
||||
result.setUrl(vs.getUrl());
|
||||
}
|
||||
|
@ -952,7 +942,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
for (CodingValidationRequest t : codes) {
|
||||
if (!t.hasResult()) {
|
||||
try {
|
||||
ValueSetCheckerSimple vsc = constructValueSetCheckerSimple(options, vs);
|
||||
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs);
|
||||
ValidationResult res = vsc.validateCode("Coding", t.getCoding());
|
||||
if (txCache != null) {
|
||||
txCache.cacheValidation(t.getCacheToken(), res, TerminologyCache.TRANSIENT);
|
||||
|
@ -997,13 +987,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
if (batch.getEntry().size() > 0) {
|
||||
txLog("$batch validate for "+batch.getEntry().size()+" codes on systems "+systems.toString());
|
||||
if (txClient == null) {
|
||||
if (tcc.getClient() == null) {
|
||||
throw new FHIRException(formatMessage(I18nConstants.ATTEMPT_TO_USE_TERMINOLOGY_SERVER_WHEN_NO_TERMINOLOGY_SERVER_IS_AVAILABLE));
|
||||
}
|
||||
if (txLog != null) {
|
||||
txLog.clearLastId();
|
||||
}
|
||||
Bundle resp = txClient.validateBatch(batch);
|
||||
Bundle resp = tcc.getClient().validateBatch(batch);
|
||||
if (resp == null) {
|
||||
throw new FHIRException(formatMessage(I18nConstants.TX_SERVER_NO_BATCH_RESPONSE));
|
||||
}
|
||||
|
@ -1074,8 +1064,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (options.isUseClient()) {
|
||||
// ok, first we try to validate locally
|
||||
try {
|
||||
ValueSetCheckerSimple vsc = constructValueSetCheckerSimple(options, vs, ctxt);
|
||||
if (!vsc.isServerSide(code.getSystem())) {
|
||||
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs, ctxt);
|
||||
if (!ValueSetUtilities.isServerSide(code.getSystem())) {
|
||||
res = vsc.validateCode(path, code);
|
||||
if (txCache != null) {
|
||||
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
|
||||
|
@ -1093,7 +1083,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
}
|
||||
|
||||
if (localError != null && txClient == null) {
|
||||
if (localError != null && tcc.getClient() == null) {
|
||||
return new ValidationResult(IssueSeverity.ERROR, localError, TerminologyServiceErrorClass.UNKNOWN, issues);
|
||||
}
|
||||
if (!options.isUseServer()) {
|
||||
|
@ -1130,16 +1120,16 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
return res;
|
||||
}
|
||||
|
||||
protected ValueSetExpanderSimple constructValueSetExpanderSimple() {
|
||||
return new ValueSetExpanderSimple(this);
|
||||
protected ValueSetExpander constructValueSetExpanderSimple() {
|
||||
return new ValueSetExpander(this);
|
||||
}
|
||||
|
||||
protected ValueSetCheckerSimple constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs, ValidationContextCarrier ctxt) {
|
||||
return new ValueSetCheckerSimple(options, vs, this, ctxt, expParameters, txcaps);
|
||||
protected ValueSetValidator constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs, ValidationContextCarrier ctxt) {
|
||||
return new ValueSetValidator(options, vs, this, ctxt, expParameters, tcc.getTxcaps());
|
||||
}
|
||||
|
||||
protected ValueSetCheckerSimple constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs) {
|
||||
return new ValueSetCheckerSimple(options, vs, this, expParameters, txcaps);
|
||||
protected ValueSetValidator constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs) {
|
||||
return new ValueSetValidator(options, vs, this, expParameters, tcc.getTxcaps());
|
||||
}
|
||||
|
||||
protected Parameters constructParameters(ValueSet vs, boolean hierarchical) {
|
||||
|
@ -1149,7 +1139,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
boolean cached = addDependentResources(p, vs);
|
||||
if (cached) {
|
||||
p.addParameter().setName("cache-id").setValue(new StringType(cacheId));
|
||||
p.addParameter().setName("cache-id").setValue(new StringType(tcc.getCacheId()));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
@ -1218,7 +1208,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (options.isUseClient()) {
|
||||
// ok, first we try to validate locally
|
||||
try {
|
||||
ValueSetCheckerSimple vsc = constructValueSetCheckerSimple(options, vs);
|
||||
ValueSetValidator vsc = constructValueSetCheckerSimple(options, vs);
|
||||
res = vsc.validateCode("CodeableConcept", code);
|
||||
txCache.cacheValidation(cacheToken, res, TerminologyCache.TRANSIENT);
|
||||
return res;
|
||||
|
@ -1259,22 +1249,23 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
codeSystemsUsed.add(inc.getSystem());
|
||||
}
|
||||
}
|
||||
|
||||
if (vs != null) {
|
||||
if (isTxCaching && cacheId != null && vs.getUrl() != null && cached.contains(vs.getUrl()+"|"+vs.getVersion())) {
|
||||
if (tcc.isTxCaching() && tcc.getCacheId() != null && vs.getUrl() != null && tcc.getCached().contains(vs.getUrl()+"|"+vs.getVersion())) {
|
||||
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()+(vs.hasVersion() ? "|"+vs.getVersion() : "")));
|
||||
} else if (options.getVsAsUrl()){
|
||||
pin.addParameter().setName("url").setValue(new UriType(vs.getUrl()));
|
||||
} else {
|
||||
pin.addParameter().setName("valueSet").setResource(vs);
|
||||
if (vs.getUrl() != null) {
|
||||
cached.add(vs.getUrl()+"|"+vs.getVersion());
|
||||
tcc.getCached().add(vs.getUrl()+"|"+vs.getVersion());
|
||||
}
|
||||
}
|
||||
cache = true;
|
||||
addDependentResources(pin, vs);
|
||||
}
|
||||
if (cache) {
|
||||
pin.addParameter().setName("cache-id").setValue(new StringType(cacheId));
|
||||
pin.addParameter().setName("cache-id").setValue(new StringType(tcc.getCacheId()));
|
||||
}
|
||||
for (ParametersParameterComponent pp : pin.getParameter()) {
|
||||
if (pp.getName().equals("profile")) {
|
||||
|
@ -1288,14 +1279,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
if (txLog != null) {
|
||||
txLog.clearLastId();
|
||||
}
|
||||
if (txClient == null) {
|
||||
if (tcc.getClient() == null) {
|
||||
throw new FHIRException(formatMessage(I18nConstants.ATTEMPT_TO_USE_TERMINOLOGY_SERVER_WHEN_NO_TERMINOLOGY_SERVER_IS_AVAILABLE));
|
||||
}
|
||||
Parameters pOut;
|
||||
if (vs == null) {
|
||||
pOut = txClient.validateCS(pin);
|
||||
pOut = tcc.getClient().validateCS(pin);
|
||||
} else {
|
||||
pOut = txClient.validateVS(pin);
|
||||
pOut = tcc.getClient().validateVS(pin);
|
||||
}
|
||||
return processValidationResult(pOut);
|
||||
}
|
||||
|
@ -1317,8 +1308,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
ValueSet vs = fetchResource(ValueSet.class, c.getValue(), src);
|
||||
if (vs != null) {
|
||||
pin.addParameter().setName("tx-resource").setResource(vs);
|
||||
if (isTxCaching && cacheId == null || !cached.contains(vs.getVUrl())) {
|
||||
cached.add(vs.getVUrl());
|
||||
if (tcc.isTxCaching() && tcc.getCacheId() == null || !tcc.getCached().contains(vs.getVUrl())) {
|
||||
tcc.getCached().add(vs.getVUrl());
|
||||
cache = true;
|
||||
}
|
||||
addDependentResources(pin, vs);
|
||||
|
@ -1327,8 +1318,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem(), src);
|
||||
if (cs != null && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
|
||||
pin.addParameter().setName("tx-resource").setResource(cs);
|
||||
if (isTxCaching && cacheId == null || !cached.contains(cs.getVUrl())) {
|
||||
cached.add(cs.getVUrl());
|
||||
if (tcc.isTxCaching() && tcc.getCacheId() == null || !tcc.getCached().contains(cs.getVUrl())) {
|
||||
tcc.getCached().add(cs.getVUrl());
|
||||
cache = true;
|
||||
}
|
||||
// todo: supplements
|
||||
|
@ -1376,9 +1367,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
}
|
||||
if (!ok) {
|
||||
return new ValidationResult(IssueSeverity.ERROR, message+" (from "+txClient.getId()+")", err, null).setTxLink(txLog.getLastId());
|
||||
return new ValidationResult(IssueSeverity.ERROR, message+" (from "+tcc.getClient().getId()+")", err, null).setTxLink(txLog.getLastId());
|
||||
} else if (message != null && !message.equals("No Message returned")) {
|
||||
return new ValidationResult(IssueSeverity.WARNING, message+" (from "+txClient.getId()+")", system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display, null).setTxLink(txLog.getLastId());
|
||||
return new ValidationResult(IssueSeverity.WARNING, message+" (from "+tcc.getClient().getId()+")", system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display, null).setTxLink(txLog.getLastId());
|
||||
} else if (display != null) {
|
||||
return new ValidationResult(system, version, new ConceptDefinitionComponent().setDisplay(display).setCode(code), display).setTxLink(txLog.getLastId());
|
||||
} else {
|
||||
|
@ -1425,7 +1416,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
@Override
|
||||
public boolean isNoTerminologyServer() {
|
||||
return noTerminologyServer || txClient == null;
|
||||
return noTerminologyServer || tcc.getClient() == null;
|
||||
}
|
||||
|
||||
public void setNoTerminologyServer(boolean noTerminologyServer) {
|
||||
|
@ -2376,41 +2367,41 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
public int getClientRetryCount() {
|
||||
return txClient == null ? 0 : txClient.getRetryCount();
|
||||
return tcc.getClient() == null ? 0 : tcc.getClient().getRetryCount();
|
||||
}
|
||||
|
||||
public IWorkerContext setClientRetryCount(int value) {
|
||||
if (txClient != null) {
|
||||
txClient.setRetryCount(value);
|
||||
if (tcc.getClient() != null) {
|
||||
tcc.getClient().setRetryCount(value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TerminologyClient getTxClient() {
|
||||
return txClient;
|
||||
public ITerminologyClient getTxClient() {
|
||||
return tcc.getClient();
|
||||
}
|
||||
|
||||
public String getCacheId() {
|
||||
return cacheId;
|
||||
return tcc.getCacheId();
|
||||
}
|
||||
|
||||
public void setCacheId(String cacheId) {
|
||||
this.cacheId = cacheId;
|
||||
tcc.setCacheId(cacheId);
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTxCaps() {
|
||||
return txcaps;
|
||||
return tcc.getTxcaps();
|
||||
}
|
||||
|
||||
public void setTxCaps(TerminologyCapabilities txCaps) {
|
||||
this.txcaps = txCaps;
|
||||
this.tcc.setTxcaps(txCaps);
|
||||
if (txCaps != null) {
|
||||
for (TerminologyCapabilitiesExpansionParameterComponent t : txcaps.getExpansion().getParameter()) {
|
||||
for (TerminologyCapabilitiesExpansionParameterComponent t : tcc.getTxcaps().getExpansion().getParameter()) {
|
||||
if ("cache-id".equals(t.getName())) {
|
||||
isTxCaching = true;
|
||||
tcc.setTxCaching(true);
|
||||
}
|
||||
}
|
||||
for (TerminologyCapabilitiesCodeSystemComponent tccs : txcaps.getCodeSystem()) {
|
||||
for (TerminologyCapabilitiesCodeSystemComponent tccs : tcc.getTxcaps().getCodeSystem()) {
|
||||
supportedCodeSystems.add(tccs.getUri());
|
||||
}
|
||||
}
|
||||
|
@ -2445,8 +2436,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
protected void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
if (txClient != null)
|
||||
txClient.setUserAgent(userAgent);
|
||||
if (tcc.getClient() != null)
|
||||
tcc.getClient().setUserAgent(userAgent);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -71,8 +71,8 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
|||
import org.hl7.fhir.r5.profilemodel.PEDefinition;
|
||||
import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
|
||||
import org.hl7.fhir.r5.profilemodel.PEBuilder;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.utilities.TimeTracker;
|
||||
|
|
|
@ -67,7 +67,7 @@ import org.hl7.fhir.r5.profilemodel.PEDefinition;
|
|||
import org.hl7.fhir.r5.profilemodel.PEBuilder;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.R5Hacker;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
|
@ -316,22 +316,22 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
loadBytes(name, stream);
|
||||
}
|
||||
|
||||
public String connectToTSServer(TerminologyClient client, String log) {
|
||||
public String connectToTSServer(ITerminologyClient client, String log) {
|
||||
try {
|
||||
txLog("Connect to "+client.getAddress());
|
||||
txClient = client;
|
||||
tcc.setClient(client);
|
||||
if (log != null && (log.endsWith(".htm") || log.endsWith(".html"))) {
|
||||
txLog = new HTMLClientLogger(log);
|
||||
} else {
|
||||
txLog = new TextClientLogger(log);
|
||||
}
|
||||
txClient.setLogger(txLog);
|
||||
txClient.setUserAgent(userAgent);
|
||||
tcc.getClient().setLogger(txLog);
|
||||
tcc.getClient().setUserAgent(userAgent);
|
||||
|
||||
final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : txClient.getCapabilitiesStatementQuick();
|
||||
final CapabilityStatement capabilitiesStatementQuick = txCache.hasCapabilityStatement() ? txCache.getCapabilityStatement() : tcc.getClient().getCapabilitiesStatementQuick();
|
||||
txCache.cacheCapabilityStatement(capabilitiesStatementQuick);
|
||||
|
||||
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : txClient.getTerminologyCapabilities();
|
||||
final TerminologyCapabilities capabilityStatement = txCache.hasTerminologyCapabilities() ? txCache.getTerminologyCapabilities() : tcc.getClient().getTerminologyCapabilities();
|
||||
txCache.cacheTerminologyCapabilities(capabilityStatement);
|
||||
|
||||
setTxCaps(capabilityStatement);
|
||||
|
|
|
@ -51,8 +51,8 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
|
|
@ -57,7 +57,7 @@ import org.hl7.fhir.r5.model.StructureDefinition;
|
|||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||
import org.hl7.fhir.r5.model.TypeConvertor;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.ElementDecoration;
|
||||
import org.hl7.fhir.utilities.ElementDecoration.DecorationType;
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
|||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
||||
|
|
|
@ -43,8 +43,8 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
|||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.LoincLinker;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
|
|
@ -844,5 +844,20 @@ public class CodeSystemUtilities {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasPropertyDef(CodeSystem cs, String property) {
|
||||
for (PropertyComponent pd : cs.getProperty()) {
|
||||
if (pd.getCode().equals(property)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static DataType getProperty(CodeSystem cs, String code, String property) {
|
||||
ConceptDefinitionComponent def = getCode(cs, code);
|
||||
ConceptPropertyComponent cp = getProperty(def, property);
|
||||
return cp == null ? null : cp.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
/*
|
||||
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 org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
|
||||
|
||||
/**
|
||||
* The value set system has a collection of value sets
|
||||
* that define code systems, and construct value sets from
|
||||
* them
|
||||
*
|
||||
* Large external terminologies - LOINC, Snomed, etc - are too big, and
|
||||
* trying to represent their definition as a native value set is too
|
||||
* large. (e.g. LOINC + properties ~ 500MB). So we don't try. Instead.
|
||||
* we assume that there's some external server that provides these
|
||||
* services, using this interface
|
||||
*
|
||||
* The FHIR build tool uses http://fhir.healthintersections.com.au for
|
||||
* these services
|
||||
*
|
||||
* @author Grahame
|
||||
*
|
||||
*/
|
||||
public interface ITerminologyServices {
|
||||
/**
|
||||
* return true if the service handles code or value set resolution on the system
|
||||
*/
|
||||
public boolean supportsSystem(String system);
|
||||
|
||||
/**
|
||||
* given a system|code, return a definition for it. Nil means not valid
|
||||
*/
|
||||
public ConceptDefinitionComponent getCodeDefinition(String system, String code);
|
||||
|
||||
public class ValidationResult {
|
||||
private IssueSeverity severity;
|
||||
private String message;
|
||||
public ValidationResult(IssueSeverity severity, String message) {
|
||||
super();
|
||||
this.severity = severity;
|
||||
this.message = message;
|
||||
}
|
||||
public IssueSeverity getSeverity() {
|
||||
return severity;
|
||||
}
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* for this system|code and display, validate the triple against the rules of
|
||||
* the underlying code system
|
||||
*/
|
||||
public ValidationResult validateCode(String system, String code, String display);
|
||||
|
||||
/**
|
||||
* Expand the value set fragment (system | codes | filters). Note that this
|
||||
* might fail if the expansion is very large. If the expansion fails, then the
|
||||
* checkVS will be called instead
|
||||
*/
|
||||
public ValueSetExpansionComponent expandVS(ConceptSetComponent inc) throws Exception;
|
||||
// public ValueSet expandVS(ValueSet vs) throws Exception;
|
||||
public ValueSetExpansionOutcome expand(ValueSet vs);
|
||||
|
||||
/**
|
||||
* Test the value set fragment (system | codes | filters).
|
||||
*/
|
||||
public boolean checkVS(ConceptSetComponent vsi, String system, String code);
|
||||
|
||||
public boolean verifiesSystem(String system);
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
|
||||
|
||||
public class TerminologyServerDetails {
|
||||
public enum ServerAuthorizationMethod {
|
||||
OPEN,
|
||||
TOKEN,
|
||||
SMART_ON_FHIR
|
||||
}
|
||||
private String name;
|
||||
private ServerAuthorizationMethod auth;
|
||||
private Map<FHIRVersion, String> endpoints = new HashMap<>();
|
||||
private List<String> codeSystems = new ArrayList<>();
|
||||
|
||||
public boolean handlesSystem(String uri, String version) {
|
||||
for (String s : codeSystems) {
|
||||
if (s.contains("|")) {
|
||||
String u = s.substring(0, s.lastIndexOf("|"));
|
||||
String v = s.substring(s.lastIndexOf("|")+1);
|
||||
if (v.equals(version) && (s.equals(uri) || uri.matches(s))) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (s.equals(uri) || uri.matches(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ServerAuthorizationMethod getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public Map<FHIRVersion, String> getEndpoints() {
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
public List<String> getCodeSystems() {
|
||||
return codeSystems;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public class TerminologyServiceCache {
|
||||
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
|
||||
/*
|
||||
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 org.hl7.fhir.r5.terminologies.ValueSetExpander.ETooCostly;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
|
||||
public interface ValueSetChecker {
|
||||
|
||||
public static class ValidationProcessInfo {
|
||||
private TerminologyServiceErrorClass err;
|
||||
private List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
public TerminologyServiceErrorClass getErr() {
|
||||
return err;
|
||||
}
|
||||
public void setErr(TerminologyServiceErrorClass err) {
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
public List<OperationOutcomeIssueComponent> getIssues() {
|
||||
return issues;
|
||||
}
|
||||
public void addIssue(List<OperationOutcomeIssueComponent> issues) {
|
||||
issues.addAll(issues);
|
||||
|
||||
}
|
||||
public boolean hasErrors() {
|
||||
for (OperationOutcomeIssueComponent issue : issues) {
|
||||
if (issue.getSeverity() == IssueSeverity.FATAL || issue.getSeverity() == IssueSeverity.ERROR) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public String summary() {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("; ");
|
||||
for (OperationOutcomeIssueComponent issue : issues) {
|
||||
b.append(issue.getDetails().getText());
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
Boolean codeInValueSet(String system, String version, String code, ValidationProcessInfo info) throws ETooCostly, EOperationOutcome, Exception;
|
||||
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
/*
|
||||
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 java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
|
||||
public interface ValueSetExpander {
|
||||
public enum TerminologyServiceErrorClass {
|
||||
UNKNOWN, NOSERVICE, SERVER_ERROR, VALUESET_UNSUPPORTED, CODESYSTEM_UNSUPPORTED, BLOCKED_BY_OPTIONS, INTERNAL_ERROR, BUSINESS_RULE, TOO_COSTLY;
|
||||
|
||||
public boolean isInfrastructure() {
|
||||
return this == NOSERVICE || this == SERVER_ERROR || this == VALUESET_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
public class ETooCostly extends Exception {
|
||||
|
||||
public ETooCostly(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Some value sets are just too big to expand. Instead of an expanded value set,
|
||||
* you get back an interface that can test membership - usually on a server somewhere
|
||||
*
|
||||
* @author Grahame
|
||||
*/
|
||||
public class ValueSetExpansionOutcome {
|
||||
private ValueSet valueset;
|
||||
private String error;
|
||||
private TerminologyServiceErrorClass errorClass;
|
||||
private String txLink;
|
||||
private List<String> allErrors = new ArrayList<>();
|
||||
|
||||
public ValueSetExpansionOutcome(ValueSet valueset) {
|
||||
super();
|
||||
this.valueset = valueset;
|
||||
this.error = null;
|
||||
}
|
||||
public ValueSetExpansionOutcome(ValueSet valueset, String error, TerminologyServiceErrorClass errorClass) {
|
||||
super();
|
||||
this.valueset = valueset;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
allErrors.add(error);
|
||||
}
|
||||
public ValueSetExpansionOutcome(ValueSetChecker service, String error, TerminologyServiceErrorClass errorClass) {
|
||||
super();
|
||||
this.valueset = null;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
allErrors.add(error);
|
||||
}
|
||||
public ValueSetExpansionOutcome(String error, TerminologyServiceErrorClass errorClass) {
|
||||
this.valueset = null;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
allErrors.add(error);
|
||||
}
|
||||
public ValueSetExpansionOutcome(String error, TerminologyServiceErrorClass errorClass, List<String> errList) {
|
||||
this.valueset = null;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
this.allErrors.addAll(errList);
|
||||
if (!allErrors.contains(error)) {
|
||||
allErrors.add(error);
|
||||
}
|
||||
if (!errList.contains(error)) {
|
||||
errList.add(error);
|
||||
}
|
||||
}
|
||||
|
||||
public ValueSet getValueset() {
|
||||
return valueset;
|
||||
}
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
public TerminologyServiceErrorClass getErrorClass() {
|
||||
return errorClass;
|
||||
}
|
||||
public String getTxLink() {
|
||||
return txLink;
|
||||
}
|
||||
public ValueSetExpansionOutcome setTxLink(String txLink) {
|
||||
this.txLink = txLink;
|
||||
return this;
|
||||
}
|
||||
public List<String> getAllErrors() {
|
||||
return allErrors;
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return (allErrors.isEmpty() || (allErrors.size() == 1 && allErrors.get(0) == null)) && error == null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param source the value set definition to expand
|
||||
* @param profile a set of parameters affecting the outcome. If you don't supply parameters, the default internal parameters will be used.
|
||||
*
|
||||
* @return
|
||||
* @throws ETooCostly
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ValueSetExpansionOutcome expand(ValueSet source, Parameters parameters) throws ETooCostly, FileNotFoundException, IOException;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
public interface ValueSetExpanderFactory {
|
||||
public ValueSetExpander getExpander();
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
/*
|
||||
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 java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||
|
||||
public class ValueSetExpansionCache implements ValueSetExpanderFactory {
|
||||
|
||||
public class CacheAwareExpander implements ValueSetExpander {
|
||||
|
||||
@Override
|
||||
public ValueSetExpansionOutcome expand(ValueSet source, Parameters expParams) throws ETooCostly, IOException {
|
||||
String cacheKey = makeCacheKey(source, expParams);
|
||||
if (expansions.containsKey(cacheKey))
|
||||
return expansions.get(cacheKey);
|
||||
ValueSetExpander vse = new ValueSetExpanderSimple(context);
|
||||
ValueSetExpansionOutcome vso = vse.expand(source, expParams);
|
||||
if (vso.getError() != null) {
|
||||
// well, we'll see if the designated server can expand it, and if it can, we'll cache it locally
|
||||
vso = context.expandVS(source, false, expParams == null || !expParams.getParameterBool("excludeNested"));
|
||||
if (cacheFolder != null) {
|
||||
FileOutputStream s = new FileOutputStream(Utilities.path(cacheFolder, makeFileName(source.getUrl())));
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(s, vso.getValueset());
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
if (vso.getValueset() != null)
|
||||
expansions.put(cacheKey, vso);
|
||||
return vso;
|
||||
}
|
||||
|
||||
private String makeCacheKey(ValueSet source, Parameters expParams) throws IOException {
|
||||
if (expParams == null)
|
||||
return source.getUrl();
|
||||
JsonParser p = new JsonParser();
|
||||
String r = p.composeString(expParams);
|
||||
return source.getUrl() + " " + r.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String VS_ID_EXT = "http://tools/cache";
|
||||
|
||||
private final Map<String, ValueSetExpansionOutcome> expansions = new HashMap<String, ValueSetExpansionOutcome>();
|
||||
private final Map<String, CanonicalResource> canonicals = new HashMap<String, CanonicalResource>();
|
||||
private final IWorkerContext context;
|
||||
private final String cacheFolder;
|
||||
|
||||
private Object lock;
|
||||
|
||||
public ValueSetExpansionCache(IWorkerContext context, Object lock) {
|
||||
super();
|
||||
cacheFolder = null;
|
||||
this.lock = lock;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public ValueSetExpansionCache(IWorkerContext context, String cacheFolder, Object lock) throws FHIRFormatError, IOException {
|
||||
super();
|
||||
this.context = context;
|
||||
this.cacheFolder = cacheFolder;
|
||||
this.lock = lock;
|
||||
if (this.cacheFolder != null)
|
||||
loadCache();
|
||||
}
|
||||
|
||||
private String makeFileName(String url) {
|
||||
return url.replace("$", "").replace(":", "").replace("|", ".").replace("//", "/").replace("/", "_")+".xml";
|
||||
}
|
||||
|
||||
private void loadCache() throws FHIRFormatError, IOException {
|
||||
File[] files = new File(cacheFolder).listFiles();
|
||||
for (File f : files) {
|
||||
if (f.getName().endsWith(".xml")) {
|
||||
final FileInputStream is = new FileInputStream(f);
|
||||
try {
|
||||
Resource r = new XmlParser().setOutputStyle(OutputStyle.PRETTY).parse(is);
|
||||
if (r instanceof OperationOutcome) {
|
||||
OperationOutcome oo = (OperationOutcome) r;
|
||||
expansions.put(ToolingExtensions.getExtension(oo,VS_ID_EXT).getValue().toString(),
|
||||
new ValueSetExpansionOutcome(new XhtmlComposer(XhtmlComposer.XML, false).composePlainText(oo.getText().getDiv()), TerminologyServiceErrorClass.UNKNOWN));
|
||||
} else if (r instanceof ValueSet) {
|
||||
ValueSet vs = (ValueSet) r;
|
||||
if (vs.hasExpansion())
|
||||
expansions.put(vs.getUrl(), new ValueSetExpansionOutcome(vs));
|
||||
else {
|
||||
canonicals.put(vs.getUrl(), vs);
|
||||
if (vs.hasVersion())
|
||||
canonicals.put(vs.getUrl()+"|"+vs.getVersion(), vs);
|
||||
}
|
||||
} else if (r instanceof CanonicalResource) {
|
||||
CanonicalResource md = (CanonicalResource) r;
|
||||
canonicals.put(md.getUrl(), md);
|
||||
if (md.hasVersion())
|
||||
canonicals.put(md.getUrl()+"|"+md.getVersion(), md);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSetExpander getExpander() {
|
||||
return new CacheAwareExpander();
|
||||
// return new ValueSetExpander(valuesets, codesystems);
|
||||
}
|
||||
|
||||
public CanonicalResource getStoredResource(String canonicalUri) {
|
||||
synchronized (lock) {
|
||||
return canonicals.get(canonicalUri);
|
||||
}
|
||||
}
|
||||
|
||||
public void storeResource(CanonicalResource md) throws IOException {
|
||||
synchronized (lock) {
|
||||
canonicals.put(md.getUrl(), md);
|
||||
if (md.hasVersion())
|
||||
canonicals.put(md.getUrl()+"|"+md.getVersion(), md);
|
||||
}
|
||||
if (cacheFolder != null) {
|
||||
FileOutputStream s = new FileOutputStream(Utilities.path(cacheFolder, makeFileName(md.getUrl()+"|"+md.getVersion())));
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(s, md);
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -68,6 +68,11 @@ import org.hl7.fhir.utilities.Utilities;
|
|||
|
||||
public class ValueSetUtilities {
|
||||
|
||||
|
||||
public static boolean isServerSide(String url) {
|
||||
return Utilities.existsInList(url, "http://hl7.org/fhir/sid/cvx");
|
||||
}
|
||||
|
||||
public static ValueSet makeShareable(ValueSet vs) {
|
||||
if (!vs.hasExperimental()) {
|
||||
vs.setExperimental(false);
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class ValueSetWorker {
|
||||
|
||||
public boolean isServerSide(String url) {
|
||||
return Utilities.existsInList(url, "http://hl7.org/fhir/sid/cvx");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.r5.terminologies.client;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -40,7 +40,7 @@ import org.hl7.fhir.utilities.ToolingClientLogger;
|
|||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
|
||||
public interface TerminologyClient {
|
||||
public interface ITerminologyClient {
|
||||
|
||||
EnumSet<FhirPublication> supportableVersions();
|
||||
void setAllowedVersions(EnumSet<FhirPublication> versions);
|
||||
|
@ -54,15 +54,15 @@ public interface TerminologyClient {
|
|||
ValueSet expandValueset(ValueSet vs, Parameters p, Map<String, String> params) throws FHIRException;
|
||||
Parameters validateCS(Parameters pin) throws FHIRException;
|
||||
Parameters validateVS(Parameters pin) throws FHIRException;
|
||||
TerminologyClient setTimeout(int i) throws FHIRException;
|
||||
TerminologyClient setLogger(ToolingClientLogger txLog) throws FHIRException;
|
||||
ITerminologyClient setTimeout(int i) throws FHIRException;
|
||||
ITerminologyClient setLogger(ToolingClientLogger txLog) throws FHIRException;
|
||||
int getRetryCount() throws FHIRException;
|
||||
TerminologyClient setRetryCount(int retryCount) throws FHIRException;
|
||||
ITerminologyClient setRetryCount(int retryCount) throws FHIRException;
|
||||
CapabilityStatement getCapabilitiesStatementQuick() throws FHIRException;
|
||||
Parameters lookupCode(Map<String, String> params) throws FHIRException;
|
||||
Bundle validateBatch(Bundle batch);
|
||||
CanonicalResource read(String type, String id);
|
||||
ClientHeaders getClientHeaders();
|
||||
TerminologyClient setClientHeaders(ClientHeaders clientHeaders);
|
||||
TerminologyClient setUserAgent(String userAgent);
|
||||
ITerminologyClient setClientHeaders(ClientHeaders clientHeaders);
|
||||
ITerminologyClient setUserAgent(String userAgent);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package org.hl7.fhir.r5.terminologies.client;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
|
||||
public class TerminologyClientContext {
|
||||
private String cacheId;
|
||||
private boolean isTxCaching;
|
||||
private int serverQueryCount = 0;
|
||||
private final Set<String> cached = new HashSet<>();
|
||||
// protected String tsServer;
|
||||
private ITerminologyClient client;
|
||||
private TerminologyCapabilities txcaps;
|
||||
|
||||
public String getCacheId() {
|
||||
return cacheId;
|
||||
}
|
||||
|
||||
public void setCacheId(String cacheId) {
|
||||
this.cacheId = cacheId;
|
||||
}
|
||||
|
||||
public boolean isTxCaching() {
|
||||
return isTxCaching;
|
||||
}
|
||||
|
||||
public void setTxCaching(boolean isTxCaching) {
|
||||
this.isTxCaching = isTxCaching;
|
||||
}
|
||||
|
||||
public int getServerQueryCount() {
|
||||
return serverQueryCount;
|
||||
}
|
||||
|
||||
public void setServerQueryCount(int serverQueryCount) {
|
||||
this.serverQueryCount = serverQueryCount;
|
||||
}
|
||||
|
||||
public Set<String> getCached() {
|
||||
return cached;
|
||||
}
|
||||
|
||||
// public String getTsServer() {
|
||||
// return tsServer;
|
||||
// }
|
||||
//
|
||||
// public void setTsServer(String tsServer) {
|
||||
// this.tsServer = tsServer;
|
||||
// }
|
||||
|
||||
public ITerminologyClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(ITerminologyClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public TerminologyCapabilities getTxcaps() {
|
||||
return txcaps;
|
||||
}
|
||||
|
||||
public void setTxcaps(TerminologyCapabilities txcaps) {
|
||||
this.txcaps = txcaps;
|
||||
}
|
||||
|
||||
public void copy(TerminologyClientContext other) {
|
||||
cacheId = other.cacheId;
|
||||
isTxCaching = other.isTxCaching;
|
||||
cached.addAll(other.cached);
|
||||
// tsServer = other.tsServer;
|
||||
client = other.client;
|
||||
txcaps = other.txcaps;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
|
||||
public class AllConceptsFilter extends ConceptFilter {
|
||||
|
||||
public AllConceptsFilter(List<String> allErrors) {
|
||||
super(allErrors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
|
||||
public abstract class ConceptFilter {
|
||||
|
||||
private List<String> allErrors;
|
||||
|
||||
|
||||
protected FHIRException fail(String msg) {
|
||||
allErrors.add(msg);
|
||||
return new FHIRException(msg);
|
||||
}
|
||||
|
||||
public ConceptFilter(List<String> allErrors) {
|
||||
super();
|
||||
this.allErrors = allErrors;
|
||||
}
|
||||
|
||||
|
||||
public abstract boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def);
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
||||
public class EFinished extends FHIRException {
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
public class ETooCostly extends Exception {
|
||||
|
||||
public ETooCostly(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.PropertyType;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
|
||||
public class PropertyFilter extends ConceptFilter {
|
||||
|
||||
private ConceptSetFilterComponent filter;
|
||||
private PropertyComponent property;
|
||||
|
||||
public PropertyFilter(List<String> allErrors, ConceptSetFilterComponent fc, PropertyComponent propertyDefinition) {
|
||||
super (allErrors);
|
||||
this.filter = fc;
|
||||
this.property = propertyDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def) {
|
||||
ConceptPropertyComponent pc = getPropertyForConcept(def);
|
||||
if (pc != null) {
|
||||
String v = pc.getValue().isPrimitive() ? pc.getValue().primitiveValue() : null;
|
||||
switch (filter.getOp()) {
|
||||
case DESCENDENTOF: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case EQUAL: return filter.getValue().equals(v);
|
||||
case EXISTS: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case GENERALIZES: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case IN: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case ISA: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case ISNOTA: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case NOTIN: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case NULL: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case REGEX: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
default:
|
||||
throw fail("Shouldn't get here");
|
||||
}
|
||||
} else if (property.getType() == PropertyType.BOOLEAN && filter.getOp() == FilterOperator.EQUAL) {
|
||||
return "false".equals(filter.getValue());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ConceptPropertyComponent getPropertyForConcept(ConceptDefinitionComponent def) {
|
||||
for (ConceptPropertyComponent pc : def.getProperty()) {
|
||||
if (pc.getCode().equals(property.getCode())) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
|
||||
public class RegexFilter extends ConceptFilter {
|
||||
|
||||
private String regex;
|
||||
|
||||
protected RegexFilter(List<String> allErrors, String regex) {
|
||||
super(allErrors);
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def) {
|
||||
return def.getCode().matches(regex);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -69,11 +69,7 @@ import java.util.ArrayList;
|
|||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
@ -92,7 +88,6 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
|||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.PropertyType;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||
|
@ -115,121 +110,40 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple.EFinished;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
|
||||
import com.google.errorprone.annotations.NoAllocation;
|
||||
|
||||
public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetExpander {
|
||||
import alleycats.std.all;
|
||||
|
||||
public class EFinished extends FHIRException {
|
||||
public class ValueSetExpander {
|
||||
|
||||
}
|
||||
|
||||
public interface IConceptFilter {
|
||||
|
||||
boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def);
|
||||
|
||||
}
|
||||
|
||||
public class PropertyFilter implements IConceptFilter {
|
||||
|
||||
private ConceptSetFilterComponent filter;
|
||||
private PropertyComponent property;
|
||||
|
||||
public PropertyFilter(ConceptSetFilterComponent fc, PropertyComponent propertyDefinition) {
|
||||
this.filter = fc;
|
||||
this.property = propertyDefinition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def) {
|
||||
ConceptPropertyComponent pc = getPropertyForConcept(def);
|
||||
if (pc != null) {
|
||||
String v = pc.getValue().isPrimitive() ? pc.getValue().primitiveValue() : null;
|
||||
switch (filter.getOp()) {
|
||||
case DESCENDENTOF: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case EQUAL: return filter.getValue().equals(v);
|
||||
case EXISTS: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case GENERALIZES: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case IN: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case ISA: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case ISNOTA: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case NOTIN: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case NULL: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
case REGEX: throw fail("not supported yet: "+filter.getOp().toCode());
|
||||
default:
|
||||
throw fail("Shouldn't get here");
|
||||
}
|
||||
} else if (property.getType() == PropertyType.BOOLEAN && filter.getOp() == FilterOperator.EQUAL) {
|
||||
return "false".equals(filter.getValue());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private ConceptPropertyComponent getPropertyForConcept(ConceptDefinitionComponent def) {
|
||||
for (ConceptPropertyComponent pc : def.getProperty()) {
|
||||
if (pc.getCode().equals(property.getCode())) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AllConceptsFilter implements IConceptFilter {
|
||||
|
||||
@Override
|
||||
public boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class RegexFilter implements IConceptFilter {
|
||||
|
||||
private String regex;
|
||||
|
||||
protected RegexFilter(String regex) {
|
||||
super();
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeConcept(CodeSystem cs, ConceptDefinitionComponent def) {
|
||||
return def.getCode().matches(regex);
|
||||
}
|
||||
}
|
||||
private static final boolean REPORT_VERSION_ANYWAY = false;
|
||||
|
||||
private List<ValueSetExpansionContainsComponent> codes = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private IWorkerContext context;
|
||||
private boolean canBeHeirarchy = true;
|
||||
private boolean includeAbstract = true;
|
||||
private Set<String> excludeKeys = new HashSet<String>();
|
||||
private Set<String> excludeSystems = new HashSet<String>();
|
||||
private ValueSet focus;
|
||||
private int maxExpansionSize = 1000;
|
||||
private int offset;
|
||||
private int count;
|
||||
private List<String> allErrors = new ArrayList<>();
|
||||
private List<String> requiredSupplements = new ArrayList<>();
|
||||
private int maxExpansionSize = 1000;
|
||||
private WorkingContext dwc = new WorkingContext();
|
||||
|
||||
private int total;
|
||||
private boolean checkCodesWhenExpanding;
|
||||
private boolean includeAbstract = true;
|
||||
|
||||
public ValueSetExpanderSimple(IWorkerContext context) {
|
||||
public ValueSetExpander(IWorkerContext context) {
|
||||
super();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public ValueSetExpanderSimple(IWorkerContext context, List<String> allErrors) {
|
||||
public ValueSetExpander(IWorkerContext context, List<String> allErrors) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.allErrors = allErrors;
|
||||
|
@ -239,7 +153,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
maxExpansionSize = theMaxExpansionSize;
|
||||
}
|
||||
|
||||
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, String dispLang, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
|
||||
private ValueSetExpansionContainsComponent addCode(WorkingContext wc, String system, String code, String display, String dispLang, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
|
||||
boolean isAbstract, boolean inactive, String definition, List<ValueSet> filters, boolean noInactive, boolean deprecated, List<ValueSetExpansionPropertyComponent> vsProp,
|
||||
List<ConceptPropertyComponent> csProps, List<org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent> expProps, List<Extension> csExtList, List<Extension> vsExtList) throws ETooCostly {
|
||||
|
||||
|
@ -352,27 +266,25 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
String s = key(n);
|
||||
if (map.containsKey(s) || excludeKeys.contains(s)) {
|
||||
canBeHeirarchy = false;
|
||||
if (wc.getMap().containsKey(s) || wc.getExcludeKeys().contains(s)) {
|
||||
wc.setCanBeHeirarchy(false);
|
||||
} else {
|
||||
codes.add(n);
|
||||
map.put(s, n);
|
||||
total++;
|
||||
if (total > maxExpansionSize) {
|
||||
if (offset+count > 0 && total > offset+count) {
|
||||
total = -1;
|
||||
wc.getCodes().add(n);
|
||||
wc.getMap().put(s, n);
|
||||
wc.incTotal();
|
||||
if (wc == dwc && wc.getTotal() > maxExpansionSize) {
|
||||
if (wc.getOffset()+wc.getCount() > 0 && wc.getTotal() > wc.getOffset()+wc.getCount()) {
|
||||
wc.setTotal(-1);
|
||||
throw new EFinished();
|
||||
}
|
||||
throw failCostly(context.formatMessage(I18nConstants.VALUESET_TOO_COSTLY, focus.getUrl(), ">" + Integer.toString(maxExpansionSize)));
|
||||
}
|
||||
}
|
||||
if (canBeHeirarchy && parent != null) {
|
||||
if (wc.isCanBeHeirarchy() && parent != null) {
|
||||
parent.getContains().add(n);
|
||||
} else {
|
||||
roots.add(n);
|
||||
wc.getRoots().add(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -404,12 +316,12 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
return null;
|
||||
}
|
||||
|
||||
private void addCodeAndDescendents(ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws FHIRException, ETooCostly {
|
||||
private void addCodeAndDescendents(WorkingContext wc, ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws FHIRException, ETooCostly {
|
||||
focus.checkNoModifiers("Expansion.contains", "expanding");
|
||||
ValueSetExpansionContainsComponent np = addCode(focus.getSystem(), focus.getCode(), focus.getDisplay(), vsSrc.getLanguage(), parent,
|
||||
ValueSetExpansionContainsComponent np = addCode(wc, focus.getSystem(), focus.getCode(), focus.getDisplay(), vsSrc.getLanguage(), parent,
|
||||
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), focus.getExtensionString(ToolingExtensions.EXT_DEFINITION), filters, noInactive, false, vsProps, null, focus.getProperty(), null, focus.getExtension());
|
||||
for (ValueSetExpansionContainsComponent c : focus.getContains())
|
||||
addCodeAndDescendents(c, np, expParams, filters, noInactive, vsProps, vsSrc);
|
||||
addCodeAndDescendents(wc, c, np, expParams, filters, noInactive, vsProps, vsSrc);
|
||||
}
|
||||
|
||||
private List<ConceptDefinitionDesignationComponent> convert(List<ConceptReferenceDesignationComponent> designations) {
|
||||
|
@ -424,8 +336,8 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
return list;
|
||||
}
|
||||
|
||||
private void addCodeAndDescendents(CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters,
|
||||
ConceptDefinitionComponent exclusion, IConceptFilter filterFunc, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps) throws FHIRException, ETooCostly {
|
||||
private void addCodeAndDescendents(WorkingContext wc,CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters,
|
||||
ConceptDefinitionComponent exclusion, ConceptFilter filterFunc, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, List<WorkingContext> otherFilters) throws FHIRException, ETooCostly {
|
||||
def.checkNoModifiers("Code in Code System", "expanding");
|
||||
if (exclusion != null) {
|
||||
if (exclusion.getCode().equals(def.getCode()))
|
||||
|
@ -435,20 +347,21 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
|
||||
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
||||
boolean dep = CodeSystemUtilities.isDeprecated(cs, def, false);
|
||||
if ((includeAbstract || !abs) && filterFunc.includeConcept(cs, def)) {
|
||||
np = addCode(system, def.getCode(), def.getDisplay(), cs.getLanguage(), parent, def.getDesignation(), expParams, abs, inc, def.getDefinition(), filters, noInactive, dep, vsProps, def.getProperty(), null, def.getExtension(), null);
|
||||
if ((includeAbstract || !abs) && filterFunc.includeConcept(cs, def) && passesOtherFilters(otherFilters, cs, def.getCode())) {
|
||||
np = addCode(wc, system, def.getCode(), def.getDisplay(), cs.getLanguage(), parent, def.getDesignation(), expParams, abs, inc, def.getDefinition(), filters, noInactive, dep, vsProps, def.getProperty(), null, def.getExtension(), null);
|
||||
}
|
||||
for (ConceptDefinitionComponent c : def.getConcept()) {
|
||||
addCodeAndDescendents(cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps);
|
||||
addCodeAndDescendents(wc, cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps, otherFilters);
|
||||
}
|
||||
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||
for (ConceptDefinitionComponent c : children)
|
||||
addCodeAndDescendents(cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps);
|
||||
addCodeAndDescendents(wc, cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps, otherFilters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws ETooCostly, FHIRException {
|
||||
if (expand != null) {
|
||||
if (expand.getContains().size() > maxExpansionSize)
|
||||
|
@ -462,18 +375,18 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
}
|
||||
}
|
||||
|
||||
private void excludeCode(String theSystem, String theCode) {
|
||||
private void excludeCode(WorkingContext wc, String theSystem, String theCode) {
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(theSystem);
|
||||
n.setCode(theCode);
|
||||
String s = key(n);
|
||||
excludeKeys.add(s);
|
||||
wc.getExcludeKeys().add(s);
|
||||
}
|
||||
|
||||
private void excludeCodes(ConceptSetComponent exc, List<ValueSetExpansionParameterComponent> params, String ctxt) throws FHIRException {
|
||||
private void excludeCodes(WorkingContext wc, ConceptSetComponent exc, List<ValueSetExpansionParameterComponent> params, String ctxt) throws FHIRException {
|
||||
exc.checkNoModifiers("Compose.exclude", "expanding");
|
||||
if (exc.hasSystem() && exc.getConcept().size() == 0 && exc.getFilter().size() == 0) {
|
||||
excludeSystems.add(exc.getSystem());
|
||||
wc.getExcludeSystems().add(exc.getSystem());
|
||||
}
|
||||
|
||||
if (exc.hasValueSet())
|
||||
|
@ -486,12 +399,12 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
ValueSet valueset = vse.getValueset();
|
||||
if (valueset == null)
|
||||
throw failTSE("Error Expanding ValueSet: "+vse.getError());
|
||||
excludeCodes(valueset.getExpansion(), params);
|
||||
excludeCodes(wc, valueset.getExpansion(), params);
|
||||
return;
|
||||
}
|
||||
|
||||
for (ConceptReferenceComponent c : exc.getConcept()) {
|
||||
excludeCode(exc.getSystem(), c.getCode());
|
||||
excludeCode(wc, exc.getSystem(), c.getCode());
|
||||
}
|
||||
|
||||
if (exc.getFilter().size() > 0)
|
||||
|
@ -500,9 +413,9 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
|
||||
|
||||
|
||||
private void excludeCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
private void excludeCodes(WorkingContext wc, ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params) {
|
||||
for (ValueSetExpansionContainsComponent c : expand.getContains()) {
|
||||
excludeCode(c.getSystem(), c.getCode());
|
||||
excludeCode(wc, c.getSystem(), c.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,7 +427,6 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSetExpansionOutcome expand(ValueSet source, Parameters expParams) {
|
||||
allErrors.clear();
|
||||
try {
|
||||
|
@ -557,15 +469,15 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
focus.getExpansion().addParameter().setName(p.getName()).setValue(p.getValue());
|
||||
}
|
||||
if ("offset".equals(p.getName()) && p.hasValueIntegerType()) {
|
||||
offset = p.getValueIntegerType().getValue();
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
dwc.setOffset(p.getValueIntegerType().getValue());
|
||||
if (dwc.getOffset() < 0) {
|
||||
dwc.setOffset(0);
|
||||
}
|
||||
}
|
||||
if ("count".equals(p.getName()) && p.hasValueIntegerType()) {
|
||||
count = p.getValueIntegerType().getValue();
|
||||
if (count < 0) {
|
||||
count = 0;
|
||||
dwc.setCount(p.getValueIntegerType().getValue());
|
||||
if (dwc.getCount() < 0) {
|
||||
dwc.setCount(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -586,20 +498,20 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
// nothing - we intended to trap this here
|
||||
}
|
||||
|
||||
if (canBeHeirarchy) {
|
||||
for (ValueSetExpansionContainsComponent c : roots) {
|
||||
if (dwc.isCanBeHeirarchy()) {
|
||||
for (ValueSetExpansionContainsComponent c : dwc.getRoots()) {
|
||||
focus.getExpansion().getContains().add(c);
|
||||
}
|
||||
} else {
|
||||
int i = 0;
|
||||
int cc = 0;
|
||||
for (ValueSetExpansionContainsComponent c : codes) {
|
||||
if (map.containsKey(key(c)) && (includeAbstract || !c.getAbstract())) { // we may have added abstract codes earlier while we still thought it might be heirarchical, but later we gave up, so now ignore them
|
||||
if (offset == 0 || i >= offset) {
|
||||
for (ValueSetExpansionContainsComponent c : dwc.getCodes()) {
|
||||
if (dwc.getMap().containsKey(key(c)) && (includeAbstract || !c.getAbstract())) { // we may have added abstract codes earlier while we still thought it might be heirarchical, but later we gave up, so now ignore them
|
||||
if (dwc.getOffset() == 0 || i >= dwc.getOffset()) {
|
||||
focus.getExpansion().getContains().add(c);
|
||||
c.getContains().clear(); // make sure any heirarchy is wiped
|
||||
cc++;
|
||||
if (cc == count) {
|
||||
if (cc == dwc.getCount()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -608,8 +520,8 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
}
|
||||
}
|
||||
|
||||
if (total >= 0) {
|
||||
focus.getExpansion().setTotal(total);
|
||||
if (dwc.getTotal() >= 0) {
|
||||
focus.getExpansion().setTotal(dwc.getTotal());
|
||||
}
|
||||
if (!requiredSupplements.isEmpty()) {
|
||||
return new ValueSetExpansionOutcome("Required supplements not found: "+requiredSupplements.toString(), TerminologyServiceErrorClass.BUSINESS_RULE, allErrors);
|
||||
|
@ -618,6 +530,11 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
focus.setCompose(null);
|
||||
focus.getExtension().clear();
|
||||
focus.setPublisher(null);
|
||||
focus.setDescription(null);
|
||||
focus.setPurpose(null);
|
||||
focus.getContact().clear();
|
||||
focus.setCopyright(null);
|
||||
focus.setText(null);
|
||||
}
|
||||
return new ValueSetExpansionOutcome(focus);
|
||||
}
|
||||
|
@ -645,16 +562,16 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
compose.checkNoModifiers("ValueSet.compose", "expanding");
|
||||
// Exclude comes first because we build up a map of things to exclude
|
||||
for (ConceptSetComponent inc : compose.getExclude())
|
||||
excludeCodes(inc, exp.getParameter(), ctxt);
|
||||
canBeHeirarchy = !expParams.getParameterBool("excludeNested") && excludeKeys.isEmpty() && excludeSystems.isEmpty() && offset+count == 0;
|
||||
excludeCodes(dwc, inc, exp.getParameter(), ctxt);
|
||||
dwc.setCanBeHeirarchy(!expParams.getParameterBool("excludeNested") && dwc.getExcludeKeys().isEmpty() && dwc.getExcludeSystems().isEmpty() && dwc.getOffset()+dwc.getCount() == 0);
|
||||
includeAbstract = !expParams.getParameterBool("excludeNotForUI");
|
||||
boolean first = true;
|
||||
for (ConceptSetComponent inc : compose.getInclude()) {
|
||||
if (first == true)
|
||||
first = false;
|
||||
else
|
||||
canBeHeirarchy = false;
|
||||
includeCodes(inc, exp, expParams, canBeHeirarchy, compose.hasInactive() ? !compose.getInactive() : checkNoInActiveFromParam(expParams), extensions, valueSet);
|
||||
dwc.setCanBeHeirarchy(false);
|
||||
includeCodes(inc, exp, expParams, dwc.isCanBeHeirarchy(), compose.hasInactive() ? !compose.getInactive() : checkNoInActiveFromParam(expParams), extensions, valueSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -672,7 +589,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
return false;
|
||||
}
|
||||
|
||||
private ValueSet importValueSet(String value, ValueSetExpansionComponent exp, Parameters expParams, boolean noInactive, ValueSet valueSet) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
|
||||
private ValueSet importValueSet(WorkingContext wc, String value, ValueSetExpansionComponent exp, Parameters expParams, boolean noInactive, ValueSet valueSet) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
|
||||
if (value == null)
|
||||
throw fail("unable to find value set with no identity");
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, value, valueSet);
|
||||
|
@ -687,7 +604,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
expParams = expParams.copy();
|
||||
expParams.addParameter("activeOnly", true);
|
||||
}
|
||||
ValueSetExpansionOutcome vso = new ValueSetExpanderSimple(context, allErrors).expand(vs, expParams);
|
||||
ValueSetExpansionOutcome vso = new ValueSetExpander(context, allErrors).expand(vs, expParams);
|
||||
if (vso.getError() != null) {
|
||||
addErrors(vso.getAllErrors());
|
||||
throw fail("Unable to expand imported value set "+vs.getUrl()+": " + vso.getError());
|
||||
|
@ -711,9 +628,9 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
exp.getParameter().add(p);
|
||||
}
|
||||
if (isValueSetUnionImports(valueSet)) {
|
||||
copyExpansion(vso.getValueset().getExpansion().getContains());
|
||||
copyExpansion(wc, vso.getValueset().getExpansion().getContains());
|
||||
}
|
||||
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
|
||||
wc.setCanBeHeirarchy(false); // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
|
||||
return vso.getValueset();
|
||||
}
|
||||
|
||||
|
@ -727,7 +644,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
}
|
||||
}
|
||||
|
||||
public void copyExpansion(List<ValueSetExpansionContainsComponent> list) {
|
||||
public void copyExpansion(WorkingContext wc,List<ValueSetExpansionContainsComponent> list) {
|
||||
for (ValueSetExpansionContainsComponent cc : list) {
|
||||
ValueSetExpansionContainsComponent n = new ValueSet.ValueSetExpansionContainsComponent();
|
||||
n.setSystem(cc.getSystem());
|
||||
|
@ -738,12 +655,12 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
n.getDesignation().addAll(cc.getDesignation());
|
||||
|
||||
String s = key(n);
|
||||
if (!map.containsKey(s) && !excludeKeys.contains(s)) {
|
||||
codes.add(n);
|
||||
map.put(s, n);
|
||||
total++;
|
||||
if (!wc.getMap().containsKey(s) && !wc.getExcludeKeys().contains(s)) {
|
||||
wc.getCodes().add(n);
|
||||
wc.getMap().put(s, n);
|
||||
wc.incTotal();
|
||||
}
|
||||
copyExpansion(cc.getContains());
|
||||
copyExpansion(wc, cc.getContains());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,7 +675,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filter, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc) throws FHIRException, ETooCostly {
|
||||
for (ValueSetExpansionContainsComponent c : list) {
|
||||
c.checkNoModifiers("Imported Expansion in Code System", "expanding");
|
||||
ValueSetExpansionContainsComponent np = addCode(c.getSystem(), c.getCode(), c.getDisplay(), vsSrc.getLanguage(), parent, null, expParams, c.getAbstract(), c.getInactive(), c.getExtensionString(ToolingExtensions.EXT_DEFINITION),
|
||||
ValueSetExpansionContainsComponent np = addCode(dwc, c.getSystem(), c.getCode(), c.getDisplay(), vsSrc.getLanguage(), parent, null, expParams, c.getAbstract(), c.getInactive(), c.getExtensionString(ToolingExtensions.EXT_DEFINITION),
|
||||
filter, noInactive, false, vsProps, null, c.getProperty(), null, c.getExtension());
|
||||
copyImportContains(c.getContains(), np, expParams, filter, noInactive, vsProps, vsSrc);
|
||||
}
|
||||
|
@ -768,7 +685,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
inc.checkNoModifiers("Compose.include", "expanding");
|
||||
List<ValueSet> imports = new ArrayList<ValueSet>();
|
||||
for (CanonicalType imp : inc.getValueSet()) {
|
||||
imports.add(importValueSet(imp.getValue(), exp, expParams, noInactive, valueSet));
|
||||
imports.add(importValueSet(dwc, imp.getValue(), exp, expParams, noInactive, valueSet));
|
||||
}
|
||||
|
||||
if (!inc.hasSystem()) {
|
||||
|
@ -780,7 +697,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
copyImportContains(base.getExpansion().getContains(), null, expParams, imports, noInactive, base.getExpansion().getProperty(), base);
|
||||
} else {
|
||||
CodeSystem cs = context.fetchSupplementedCodeSystem(inc.getSystem());
|
||||
if (isServerSide(inc.getSystem()) || (cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT))) {
|
||||
if (ValueSetUtilities.isServerSide(inc.getSystem()) || (cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT))) {
|
||||
doServerIncludeCodes(inc, heirarchical, exp, imports, expParams, extensions, noInactive, valueSet.getExpansion().getProperty());
|
||||
} else {
|
||||
if (cs.hasUserData("supplements.installed")) {
|
||||
|
@ -824,7 +741,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
}
|
||||
}
|
||||
for (ValueSetExpansionContainsComponent cc : vs.getExpansion().getContains()) {
|
||||
addCodeAndDescendents(cc, null, expParams, imports, noInactive, vsProps, vs);
|
||||
addCodeAndDescendents(dwc, cc, null, expParams, imports, noInactive, vsProps, vs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -847,7 +764,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||
// special case - add all the code system
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(dwc, cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), null);
|
||||
}
|
||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||
addFragmentWarning(exp, cs);
|
||||
|
@ -858,7 +775,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
}
|
||||
|
||||
if (!inc.getConcept().isEmpty()) {
|
||||
canBeHeirarchy = false;
|
||||
dwc.setCanBeHeirarchy(false);
|
||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||
c.checkNoModifiers("Code in Value Set", "expanding");
|
||||
ConceptDefinitionComponent def = CodeSystemUtilities.findCode(cs.getConcept(), c.getCode());
|
||||
|
@ -879,32 +796,45 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
inactive = CodeSystemUtilities.isInactive(cs, def);
|
||||
isAbstract = CodeSystemUtilities.isNotSelectable(cs, def);
|
||||
}
|
||||
addCode(inc.getSystem(), c.getCode(), !Utilities.noString(c.getDisplay()) ? c.getDisplay() : def == null ? null : def.getDisplay(), c.hasDisplay() ? vsSrc.getLanguage() : cs.getLanguage(), null, mergeDesignations(def, convertDesignations(c.getDesignation())),
|
||||
addCode(dwc, inc.getSystem(), c.getCode(), !Utilities.noString(c.getDisplay()) ? c.getDisplay() : def == null ? null : def.getDisplay(), c.hasDisplay() ? vsSrc.getLanguage() : cs.getLanguage(), null, mergeDesignations(def, convertDesignations(c.getDesignation())),
|
||||
expParams, isAbstract, inactive, def == null ? null : def.getDefinition(), imports, noInactive, false, exp.getProperty(), def != null ? def.getProperty() : null, null, def == null ? null : def.getExtension(), c.getExtension());
|
||||
}
|
||||
}
|
||||
if (inc.getFilter().size() > 0) {
|
||||
if (inc.getFilter().size() > 1) {
|
||||
canBeHeirarchy = false; // which will bt the case if we get around to supporting this
|
||||
throw failTSE("Multiple filters not handled yet"); // need to and them, and this isn't done yet. But this shouldn't arise in non loinc and snomed value sets
|
||||
dwc.setCanBeHeirarchy(false); // which will be the case if we get around to supporting this
|
||||
}
|
||||
if (inc.getFilter().size() == 1) {
|
||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||
addFragmentWarning(exp, cs);
|
||||
}
|
||||
List<WorkingContext> filters = new ArrayList<>();
|
||||
for (int i = 1; i < inc.getFilter().size(); i++) {
|
||||
WorkingContext wc = new WorkingContext();
|
||||
filters.add(wc);
|
||||
processFilter(inc, exp, expParams, imports, cs, noInactive, inc.getFilter().get(i), wc, null);
|
||||
}
|
||||
ConceptSetFilterComponent fc = inc.getFilter().get(0);
|
||||
WorkingContext wc = dwc;
|
||||
processFilter(inc, exp, expParams, imports, cs, noInactive, fc, wc, filters);
|
||||
}
|
||||
}
|
||||
|
||||
private void processFilter(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams,
|
||||
List<ValueSet> imports, CodeSystem cs, boolean noInactive, ConceptSetFilterComponent fc, WorkingContext wc, List<WorkingContext> filters)
|
||||
throws ETooCostly {
|
||||
if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISA) {
|
||||
// special: all codes in the target code system under the value
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (def == null)
|
||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISNOTA) {
|
||||
// special: all codes in the target code system that are not under the value
|
||||
ConceptDefinitionComponent defEx = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (defEx == null)
|
||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, defEx, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, defEx, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
}
|
||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
||||
// special: all codes in the target code system under the value
|
||||
|
@ -912,36 +842,35 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
if (def == null)
|
||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||
for (ConceptDefinitionComponent c : def.getConcept())
|
||||
addCodeAndDescendents(cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||
for (ConceptDefinitionComponent c : children)
|
||||
addCodeAndDescendents(cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(allErrors), noInactive, exp.getProperty(), filters);
|
||||
}
|
||||
|
||||
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
||||
// gg; note: wtf is this: if the filter is display=v, look up the code 'v', and see if it's diplsay is 'v'?
|
||||
canBeHeirarchy = false;
|
||||
dwc.setCanBeHeirarchy(false);
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||
if (def != null) {
|
||||
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
||||
if (def.getDisplay().contains(fc.getValue())) {
|
||||
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), cs.getLanguage(), null, def.getDesignation(), expParams, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
||||
if (def.getDisplay().contains(fc.getValue()) && passesOtherFilters(filters, cs, def.getCode())) {
|
||||
addCode(wc, inc.getSystem(), def.getCode(), def.getDisplay(), cs.getLanguage(), null, def.getDesignation(), expParams, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
||||
def.getDefinition(), imports, noInactive, false, exp.getProperty(), def.getProperty(), null, def.getExtension(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isDefinedProperty(cs, fc.getProperty())) {
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new PropertyFilter(fc, getPropertyDefinition(cs, fc.getProperty())), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new PropertyFilter(allErrors, fc, getPropertyDefinition(cs, fc.getProperty())), noInactive, exp.getProperty(), filters);
|
||||
}
|
||||
} else if ("code".equals(fc.getProperty()) && fc.getOp() == FilterOperator.REGEX) {
|
||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new RegexFilter(fc.getValue()), noInactive, exp.getProperty());
|
||||
addCodeAndDescendents(wc, cs, inc.getSystem(), def, null, expParams, imports, null, new RegexFilter(allErrors, fc.getValue()), noInactive, exp.getProperty(), filters);
|
||||
}
|
||||
} else {
|
||||
throw fail("Search by property[" + fc.getProperty() + "] and op[" + fc.getOp() + "] is not supported yet");
|
||||
}
|
||||
throw fail("Filter by property[" + fc.getProperty() + "] and op[" + fc.getOp() + "] is not supported yet");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1039,4 +968,16 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
|||
this.checkCodesWhenExpanding = checkCodesWhenExpanding;
|
||||
}
|
||||
|
||||
private boolean passesOtherFilters(List<WorkingContext> otherFilters, CodeSystem cs, String code) {
|
||||
if (otherFilters == null) {
|
||||
return true;
|
||||
}
|
||||
String key = key(cs.getUrl(), code);
|
||||
for (WorkingContext wc : otherFilters) {
|
||||
if (!wc.getMap().containsKey(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
|
||||
/**
|
||||
* Some value sets are just too big to expand. Instead of an expanded value set,
|
||||
* you get back an interface that can test membership - usually on a server somewhere
|
||||
*
|
||||
* @author Grahame
|
||||
*/
|
||||
public class ValueSetExpansionOutcome {
|
||||
private ValueSet valueset;
|
||||
private String error;
|
||||
private TerminologyServiceErrorClass errorClass;
|
||||
private String txLink;
|
||||
private List<String> allErrors = new ArrayList<>();
|
||||
|
||||
public ValueSetExpansionOutcome(ValueSet valueset) {
|
||||
super();
|
||||
this.valueset = valueset;
|
||||
this.error = null;
|
||||
}
|
||||
public ValueSetExpansionOutcome(ValueSet valueset, String error, TerminologyServiceErrorClass errorClass) {
|
||||
super();
|
||||
this.valueset = valueset;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
allErrors.add(error);
|
||||
}
|
||||
|
||||
public ValueSetExpansionOutcome(String error, TerminologyServiceErrorClass errorClass) {
|
||||
this.valueset = null;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
allErrors.add(error);
|
||||
}
|
||||
public ValueSetExpansionOutcome(String error, TerminologyServiceErrorClass errorClass, List<String> errList) {
|
||||
this.valueset = null;
|
||||
this.error = error;
|
||||
this.errorClass = errorClass;
|
||||
this.allErrors.addAll(errList);
|
||||
if (!allErrors.contains(error)) {
|
||||
allErrors.add(error);
|
||||
}
|
||||
if (!errList.contains(error)) {
|
||||
errList.add(error);
|
||||
}
|
||||
}
|
||||
|
||||
public ValueSet getValueset() {
|
||||
return valueset;
|
||||
}
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
public TerminologyServiceErrorClass getErrorClass() {
|
||||
return errorClass;
|
||||
}
|
||||
public String getTxLink() {
|
||||
return txLink;
|
||||
}
|
||||
public ValueSetExpansionOutcome setTxLink(String txLink) {
|
||||
this.txLink = txLink;
|
||||
return this;
|
||||
}
|
||||
public List<String> getAllErrors() {
|
||||
return allErrors;
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return (allErrors.isEmpty() || (allErrors.size() == 1 && allErrors.get(0) == null)) && error == null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package org.hl7.fhir.r5.terminologies.expansion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
|
||||
class WorkingContext {
|
||||
private List<ValueSetExpansionContainsComponent> codes = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
|
||||
private Set<String> excludeKeys = new HashSet<String>();
|
||||
private Set<String> excludeSystems = new HashSet<String>();
|
||||
|
||||
private boolean canBeHeirarchy = true;
|
||||
private int offset;
|
||||
private int count;
|
||||
private int total;
|
||||
|
||||
public List<ValueSetExpansionContainsComponent> getCodes() {
|
||||
return codes;
|
||||
}
|
||||
|
||||
public List<ValueSetExpansionContainsComponent> getRoots() {
|
||||
return roots;
|
||||
}
|
||||
|
||||
public Map<String, ValueSetExpansionContainsComponent> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
public Set<String> getExcludeKeys() {
|
||||
return excludeKeys;
|
||||
}
|
||||
|
||||
public Set<String> getExcludeSystems() {
|
||||
return excludeSystems;
|
||||
}
|
||||
|
||||
public boolean isCanBeHeirarchy() {
|
||||
return canBeHeirarchy;
|
||||
}
|
||||
|
||||
public void setCanBeHeirarchy(boolean canBeHeirarchy) {
|
||||
this.canBeHeirarchy = canBeHeirarchy;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(int offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public int getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(int total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public void incTotal() {
|
||||
total++;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.r5.terminologies.providers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -8,8 +8,6 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
|
||||
import org.hl7.fhir.r5.terminologies.providers.ColorRGBProvider;
|
||||
|
||||
/**
|
||||
* For special code systems where the code system resource isn't enough, but we can support them internall
|
||||
|
@ -32,6 +30,6 @@ public abstract class CodeSystemProvider {
|
|||
List<ValueSet> imports, Parameters expParams, List<Extension> extensions, boolean noInactive,
|
||||
List<ValueSetExpansionPropertyComponent> vsProps) throws CodeSystemProviderExtension;
|
||||
|
||||
protected abstract Boolean checkCode(String code);
|
||||
public abstract Boolean checkCode(String code);
|
||||
|
||||
}
|
|
@ -9,7 +9,6 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemProvider;
|
||||
|
||||
public class ColorRGBProvider extends CodeSystemProvider {
|
||||
|
||||
|
@ -21,7 +20,7 @@ public class ColorRGBProvider extends CodeSystemProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Boolean checkCode(String code) {
|
||||
public Boolean checkCode(String code) {
|
||||
return code.matches("^\\#[0-9a-fA-F]{6}$");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.r5.terminologies.providers;
|
||||
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.r5.terminologies.providers;
|
||||
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
|
@ -8,11 +8,12 @@ public class URICodeSystem extends SpecialCodeSystem {
|
|||
|
||||
@Override
|
||||
public ConceptDefinitionComponent findConcept(Coding code) {
|
||||
if (Utilities.isAbsoluteUrl(code.getCode())) {
|
||||
return new ConceptDefinitionComponent(code.getCode());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
throw new Error("This is used");
|
||||
// if (Utilities.isAbsoluteUrl(code.getCode())) {
|
||||
// return new ConceptDefinitionComponent(code.getCode());
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.hl7.fhir.r5.terminologies.utilities;
|
||||
|
||||
public enum TerminologyServiceErrorClass {
|
||||
UNKNOWN, NOSERVICE, SERVER_ERROR, VALUESET_UNSUPPORTED, CODESYSTEM_UNSUPPORTED, BLOCKED_BY_OPTIONS, INTERNAL_ERROR, BUSINESS_RULE, TOO_COSTLY;
|
||||
|
||||
public boolean isInfrastructure() {
|
||||
return this == NOSERVICE || this == SERVER_ERROR || this == VALUESET_UNSUPPORTED;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.hl7.fhir.r5.terminologies.validation;
|
||||
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||
|
||||
public class ConceptReferencePair {
|
||||
|
||||
private ValueSet valueset;
|
||||
private ConceptReferenceComponent cc;
|
||||
|
||||
public ConceptReferencePair(ValueSet valueset, ConceptReferenceComponent cc) {
|
||||
this.valueset = valueset;
|
||||
this.cc = cc;
|
||||
}
|
||||
|
||||
public ValueSet getValueset() {
|
||||
return valueset;
|
||||
}
|
||||
|
||||
public ConceptReferenceComponent getCc() {
|
||||
return cc;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.hl7.fhir.r5.terminologies.validation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
|
||||
public class VSCheckerException extends FHIRException {
|
||||
|
||||
private List<OperationOutcomeIssueComponent> issues;
|
||||
|
||||
public VSCheckerException(String message, List<OperationOutcomeIssueComponent> issues) {
|
||||
super(message);
|
||||
this.issues = issues;
|
||||
}
|
||||
|
||||
public List<OperationOutcomeIssueComponent> getIssues() {
|
||||
return issues;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -5889505119633054187L;
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.hl7.fhir.r5.terminologies.validation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
|
||||
public class ValidationProcessInfo {
|
||||
private TerminologyServiceErrorClass err;
|
||||
private List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
public TerminologyServiceErrorClass getErr() {
|
||||
return err;
|
||||
}
|
||||
public void setErr(TerminologyServiceErrorClass err) {
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
public List<OperationOutcomeIssueComponent> getIssues() {
|
||||
return issues;
|
||||
}
|
||||
public void addIssue(List<OperationOutcomeIssueComponent> issues) {
|
||||
issues.addAll(issues);
|
||||
|
||||
}
|
||||
public boolean hasErrors() {
|
||||
for (OperationOutcomeIssueComponent issue : issues) {
|
||||
if (issue.getSeverity() == IssueSeverity.FATAL || issue.getSeverity() == IssueSeverity.ERROR) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public String summary() {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("; ");
|
||||
for (OperationOutcomeIssueComponent issue : issues) {
|
||||
b.append(issue.getDetails().getText());
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminologies;
|
||||
package org.hl7.fhir.r5.terminologies.validation;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -54,12 +54,12 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
|||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
||||
import org.hl7.fhir.r5.model.PackageInformation;
|
||||
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.Transport.ParameterComponent;
|
||||
|
@ -70,10 +70,12 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetCheckerSimple.ConceptReferencePair;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetCheckerSimple.VersionInfo;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||
import org.hl7.fhir.r5.terminologies.providers.SpecialCodeSystem;
|
||||
import org.hl7.fhir.r5.terminologies.providers.URICodeSystem;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy;
|
||||
|
@ -87,117 +89,18 @@ import org.hl7.fhir.utilities.validation.ValidationOptions.ValueSetMode;
|
|||
|
||||
import com.google.j2objc.annotations.ReflectionSupport.Level;
|
||||
|
||||
public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChecker {
|
||||
|
||||
public class VersionInfo {
|
||||
private String expansionVersion;
|
||||
private String composeVersion;
|
||||
|
||||
public String getExpansionVersion() {
|
||||
return expansionVersion;
|
||||
}
|
||||
|
||||
public void setExpansionVersion(String expansionVersion) {
|
||||
this.expansionVersion = expansionVersion;
|
||||
}
|
||||
|
||||
public String getComposeVersion() {
|
||||
return composeVersion;
|
||||
}
|
||||
|
||||
public void setComposeVersion(String composeVersion) {
|
||||
this.composeVersion = composeVersion;
|
||||
}
|
||||
|
||||
public String getVersion(String system, String version) {
|
||||
String fixedVersion = getVersionParameter("force-system-version", system);
|
||||
if (fixedVersion != null) {
|
||||
return fixedVersion;
|
||||
}
|
||||
String checkVersion = getVersionParameter("check-system-version", system);
|
||||
if (version != null) {
|
||||
if (checkVersion != null && !version.equals(checkVersion)) {
|
||||
throw new FHIRException("Attempt to use version "+version+" of "+system+", when the expansion parameters limit the use to "+checkVersion);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
if (expansionVersion != null) {
|
||||
if (checkVersion != null && !expansionVersion.equals(checkVersion)) {
|
||||
throw new FHIRException("Attempt to use version "+expansionVersion+" of "+system+", when the expansion parameters limit the use to "+checkVersion);
|
||||
}
|
||||
return expansionVersion;
|
||||
}
|
||||
if (composeVersion != null) {
|
||||
if (checkVersion != null && !composeVersion.equals(checkVersion)) {
|
||||
throw new FHIRException("Attempt to use version "+composeVersion+" of "+system+", when the expansion parameters limit the use to "+checkVersion);
|
||||
}
|
||||
return composeVersion;
|
||||
}
|
||||
return getVersionParameter("system-version", system);
|
||||
}
|
||||
|
||||
private String getVersionParameter(String name, String system) {
|
||||
if (expansionProfile != null) {
|
||||
for (ParametersParameterComponent pc : expansionProfile.getParameter()) {
|
||||
if (name.equals(pc.getName()) && pc.hasValue()) {
|
||||
String v = pc.getValue().primitiveValue();
|
||||
if (v != null && v.startsWith(system+"|")) {
|
||||
return v.substring(system.length()+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
public static class VSCheckerException extends FHIRException {
|
||||
|
||||
private List<OperationOutcomeIssueComponent> issues;
|
||||
|
||||
public VSCheckerException(String message, List<OperationOutcomeIssueComponent> issues) {
|
||||
super(message);
|
||||
this.issues = issues;
|
||||
}
|
||||
|
||||
public List<OperationOutcomeIssueComponent> getIssues() {
|
||||
return issues;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -5889505119633054187L;
|
||||
|
||||
}
|
||||
public class ConceptReferencePair {
|
||||
|
||||
private ValueSet valueset;
|
||||
private ConceptReferenceComponent cc;
|
||||
|
||||
public ConceptReferencePair(ValueSet valueset, ConceptReferenceComponent cc) {
|
||||
this.valueset = valueset;
|
||||
this.cc = cc;
|
||||
}
|
||||
|
||||
public ValueSet getValueset() {
|
||||
return valueset;
|
||||
}
|
||||
|
||||
public ConceptReferenceComponent getCc() {
|
||||
return cc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ValueSetValidator {
|
||||
|
||||
private ValueSet valueset;
|
||||
private IWorkerContext context;
|
||||
private Map<String, ValueSetCheckerSimple> inner = new HashMap<>();
|
||||
private Map<String, ValueSetValidator> inner = new HashMap<>();
|
||||
private ValidationOptions options;
|
||||
private ValidationContextCarrier localContext;
|
||||
private List<CodeSystem> localSystems = new ArrayList<>();
|
||||
private Parameters expansionProfile;
|
||||
Parameters expansionProfile;
|
||||
private TerminologyCapabilities txCaps;
|
||||
|
||||
public ValueSetCheckerSimple(ValidationOptions options, ValueSet source, IWorkerContext context, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||
public ValueSetValidator(ValidationOptions options, ValueSet source, IWorkerContext context, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||
this.valueset = source;
|
||||
this.context = context;
|
||||
this.options = options;
|
||||
|
@ -205,7 +108,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
this.txCaps = txCaps;
|
||||
}
|
||||
|
||||
public ValueSetCheckerSimple(ValidationOptions options, ValueSet source, IWorkerContext context, ValidationContextCarrier ctxt, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||
public ValueSetValidator(ValidationOptions options, ValueSet source, IWorkerContext context, ValidationContextCarrier ctxt, Parameters expansionProfile, TerminologyCapabilities txCaps) {
|
||||
this.valueset = source;
|
||||
this.context = context;
|
||||
this.options = options.copy();
|
||||
|
@ -260,7 +163,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
if (!c.hasSystem()) {
|
||||
info.addIssue(makeIssue(IssueSeverity.WARNING, IssueType.UNKNOWN, path, context.formatMessage(I18nConstants.CODING_HAS_NO_SYSTEM__CANNOT_VALIDATE)));
|
||||
}
|
||||
VersionInfo vi = new VersionInfo();
|
||||
VersionInfo vi = new VersionInfo(this);
|
||||
checkExpansion(c, vi);
|
||||
checkInclude(c, vi);
|
||||
CodeSystem cs = resolveCodeSystem(c.getSystem(), vi.getVersion(c.getSystem(), c.getVersion()));
|
||||
|
@ -417,7 +320,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
ValidationResult res = null;
|
||||
boolean inExpansion = false;
|
||||
boolean inInclude = false;
|
||||
VersionInfo vi = new VersionInfo();
|
||||
VersionInfo vi = new VersionInfo(this);
|
||||
|
||||
String system = code.hasSystem() ? code.getSystem() : getValueSetSystemOrNull();
|
||||
if (options.getValueSetMode() != ValueSetMode.CHECK_MEMERSHIP_ONLY) {
|
||||
|
@ -966,7 +869,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
}
|
||||
|
||||
private boolean checkForCodeInValueSet(String code, String uri, Set<String> sys, List<String> problems) {
|
||||
ValueSetCheckerSimple vs = getVs(uri);
|
||||
ValueSetValidator vs = getVs(uri);
|
||||
return vs.scanForCodeInValueSet(code, sys, problems);
|
||||
}
|
||||
|
||||
|
@ -985,7 +888,6 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean codeInValueSet(String system, String version, String code, ValidationProcessInfo info) throws FHIRException {
|
||||
return codeInValueSet("code", system, version, code, info);
|
||||
}
|
||||
|
@ -994,7 +896,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return false;
|
||||
}
|
||||
Boolean result = false;
|
||||
VersionInfo vi = new VersionInfo();
|
||||
VersionInfo vi = new VersionInfo(this);
|
||||
|
||||
if (valueset.hasExpansion()) {
|
||||
return checkExpansion(new Coding(system, code, null), vi);
|
||||
|
@ -1126,12 +1028,36 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return codeInConceptFilter(cs, f, code);
|
||||
else if ("code".equals(f.getProperty()) && f.getOp() == FilterOperator.REGEX)
|
||||
return codeInRegexFilter(cs, f, code);
|
||||
else {
|
||||
else if (CodeSystemUtilities.hasPropertyDef(cs, f.getProperty())) {
|
||||
return codeInPropertyFilter(cs, f, code);
|
||||
} else {
|
||||
System.out.println("todo: handle filters with property = "+f.getProperty()+" "+f.getOp().toCode());
|
||||
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_HANDLE_SYSTEM__FILTER_WITH_PROPERTY__, cs.getUrl(), f.getProperty(), f.getOp().toCode()));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean codeInPropertyFilter(CodeSystem cs, ConceptSetFilterComponent f, String code) {
|
||||
switch (f.getOp()) {
|
||||
case EQUAL:
|
||||
if (f.getValue() == null) {
|
||||
return false;
|
||||
}
|
||||
DataType d = CodeSystemUtilities.getProperty(cs, code, f.getProperty());
|
||||
return d != null && f.getValue().equals(d.primitiveValue());
|
||||
case EXISTS:
|
||||
return CodeSystemUtilities.getProperty(cs, code, f.getProperty()) != null;
|
||||
case REGEX:
|
||||
if (f.getValue() == null) {
|
||||
return false;
|
||||
}
|
||||
d = CodeSystemUtilities.getProperty(cs, code, f.getProperty());
|
||||
return d != null && d.primitiveValue() != null && d.primitiveValue().matches(f.getValue());
|
||||
default:
|
||||
System.out.println("todo: handle property filters with op = "+f.getOp());
|
||||
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_HANDLE_SYSTEM__PROPERTY_FILTER_WITH_OP__, cs.getUrl(), f.getOp()));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean codeInRegexFilter(CodeSystem cs, ConceptSetFilterComponent f, String code) {
|
||||
return code.matches(f.getValue());
|
||||
}
|
||||
|
@ -1147,16 +1073,16 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
}
|
||||
}
|
||||
|
||||
private boolean codeInConceptIsAFilter(CodeSystem cs, ConceptSetFilterComponent f, String code, boolean rootOnly) {
|
||||
if (!rootOnly && code.equals(f.getProperty())) {
|
||||
private boolean codeInConceptIsAFilter(CodeSystem cs, ConceptSetFilterComponent f, String code, boolean excludeRoot) {
|
||||
if (!excludeRoot && code.equals(f.getProperty())) {
|
||||
return true;
|
||||
}
|
||||
ConceptDefinitionComponent cc = findCodeInConcept(cs.getConcept(), f.getValue());
|
||||
if (cc == null) {
|
||||
return false;
|
||||
}
|
||||
cc = findCodeInConcept(cc, code);
|
||||
return cc != null;
|
||||
ConceptDefinitionComponent cc2 = findCodeInConcept(cc, code);
|
||||
return cc2 != null && cc2 != cc;
|
||||
}
|
||||
|
||||
public boolean validateCodeInConceptList(String code, CodeSystem def, List<ConceptDefinitionComponent> list) {
|
||||
|
@ -1182,18 +1108,18 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|
|||
return false;
|
||||
}
|
||||
|
||||
private ValueSetCheckerSimple getVs(String url) {
|
||||
private ValueSetValidator getVs(String url) {
|
||||
if (inner.containsKey(url)) {
|
||||
return inner.get(url);
|
||||
}
|
||||
ValueSet vs = context.fetchResource(ValueSet.class, url, valueset);
|
||||
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(options, vs, context, localContext, expansionProfile, txCaps);
|
||||
ValueSetValidator vsc = new ValueSetValidator(options, vs, context, localContext, expansionProfile, txCaps);
|
||||
inner.put(url, vsc);
|
||||
return vsc;
|
||||
}
|
||||
|
||||
private boolean inImport(String uri, String system, String version, String code) throws FHIRException {
|
||||
ValueSetCheckerSimple vs = getVs(uri);
|
||||
ValueSetValidator vs = getVs(uri);
|
||||
if (vs == null) {
|
||||
return false;
|
||||
} else {
|
|
@ -0,0 +1,79 @@
|
|||
package org.hl7.fhir.r5.terminologies.validation;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
|
||||
public class VersionInfo {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final ValueSetValidator valueSetCheckerSimple;
|
||||
|
||||
/**
|
||||
* @param valueSetCheckerSimple
|
||||
*/
|
||||
VersionInfo(ValueSetValidator valueSetCheckerSimple) {
|
||||
this.valueSetCheckerSimple = valueSetCheckerSimple;
|
||||
}
|
||||
|
||||
private String expansionVersion;
|
||||
private String composeVersion;
|
||||
|
||||
public String getExpansionVersion() {
|
||||
return expansionVersion;
|
||||
}
|
||||
|
||||
public void setExpansionVersion(String expansionVersion) {
|
||||
this.expansionVersion = expansionVersion;
|
||||
}
|
||||
|
||||
public String getComposeVersion() {
|
||||
return composeVersion;
|
||||
}
|
||||
|
||||
public void setComposeVersion(String composeVersion) {
|
||||
this.composeVersion = composeVersion;
|
||||
}
|
||||
|
||||
public String getVersion(String system, String version) {
|
||||
String fixedVersion = getVersionParameter("force-system-version", system);
|
||||
if (fixedVersion != null) {
|
||||
return fixedVersion;
|
||||
}
|
||||
String checkVersion = getVersionParameter("check-system-version", system);
|
||||
if (version != null) {
|
||||
if (checkVersion != null && !version.equals(checkVersion)) {
|
||||
throw new FHIRException("Attempt to use version "+version+" of "+system+", when the expansion parameters limit the use to "+checkVersion);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
if (expansionVersion != null) {
|
||||
if (checkVersion != null && !expansionVersion.equals(checkVersion)) {
|
||||
throw new FHIRException("Attempt to use version "+expansionVersion+" of "+system+", when the expansion parameters limit the use to "+checkVersion);
|
||||
}
|
||||
return expansionVersion;
|
||||
}
|
||||
if (composeVersion != null) {
|
||||
if (checkVersion != null && !composeVersion.equals(checkVersion)) {
|
||||
throw new FHIRException("Attempt to use version "+composeVersion+" of "+system+", when the expansion parameters limit the use to "+checkVersion);
|
||||
}
|
||||
return composeVersion;
|
||||
}
|
||||
return getVersionParameter("system-version", system);
|
||||
}
|
||||
|
||||
private String getVersionParameter(String name, String system) {
|
||||
if (this.valueSetCheckerSimple.expansionProfile != null) {
|
||||
for (ParametersParameterComponent pc : this.valueSetCheckerSimple.expansionProfile.getParameter()) {
|
||||
if (name.equals(pc.getName()) && pc.hasValue()) {
|
||||
String v = pc.getValue().primitiveValue();
|
||||
if (v != null && v.startsWith(system+"|")) {
|
||||
return v.substring(system.length()+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -51,7 +51,7 @@ import org.hl7.fhir.r5.model.UriType;
|
|||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpander;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ import org.hl7.fhir.r5.model.StructureMap.*;
|
|||
import org.hl7.fhir.r5.model.TypeDetails.ProfiledType;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.renderers.TerminologyRenderer;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
|
|
|
@ -20,10 +20,10 @@ import org.hl7.fhir.r5.model.Enumerations;
|
|||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetCheckerSimple;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpander;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.validation.ValueSetValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
|
@ -54,7 +54,7 @@ public class SimpleWorkerContextTests {
|
|||
ToolingClientLogger txLog;
|
||||
|
||||
@Mock
|
||||
TerminologyClient terminologyClient;
|
||||
ITerminologyClient terminologyClient;
|
||||
|
||||
@Mock
|
||||
TerminologyCache.CacheToken cacheToken;
|
||||
|
@ -63,13 +63,13 @@ public class SimpleWorkerContextTests {
|
|||
IWorkerContext.ValidationResult expectedValidationResult;
|
||||
|
||||
@Mock
|
||||
ValueSetExpander.ValueSetExpansionOutcome expectedExpansionResult;
|
||||
ValueSetExpansionOutcome expectedExpansionResult;
|
||||
|
||||
@Mock
|
||||
ValueSetCheckerSimple valueSetCheckerSimple;
|
||||
ValueSetValidator valueSetCheckerSimple;
|
||||
|
||||
@Mock
|
||||
ValueSetExpanderSimple valueSetExpanderSimple;
|
||||
ValueSetExpander valueSetExpanderSimple;
|
||||
|
||||
@Mock
|
||||
Parameters pIn;
|
||||
|
@ -90,7 +90,7 @@ public class SimpleWorkerContextTests {
|
|||
public void beforeEach() {
|
||||
context.txCache = terminologyCache;
|
||||
context.expParameters = expParameters;
|
||||
context.txClient = terminologyClient;
|
||||
context.tcc.setClient(terminologyClient);
|
||||
context.txLog = txLog;
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ public class SimpleWorkerContextTests {
|
|||
Mockito.doReturn(cacheToken).when(terminologyCache).generateExpandToken(argThat(new ValueSetMatcher(vs)),eq(true));
|
||||
Mockito.doReturn(expectedExpansionResult).when(terminologyCache).getExpansion(cacheToken);
|
||||
|
||||
ValueSetExpander.ValueSetExpansionOutcome actualExpansionResult = context.expandVS(inc, true, false);
|
||||
ValueSetExpansionOutcome actualExpansionResult = context.expandVS(inc, true, false);
|
||||
|
||||
assertEquals(expectedExpansionResult, actualExpansionResult);
|
||||
|
||||
|
@ -300,7 +300,7 @@ public class SimpleWorkerContextTests {
|
|||
Mockito.doReturn(expectedValueSet).when(terminologyClient).expandValueset(argThat(new ValueSetMatcher(vs)),
|
||||
argThat(new ParametersMatcher(pInWithDependentResources)), eq(params));
|
||||
|
||||
ValueSetExpander.ValueSetExpansionOutcome actualExpansionResult = context.expandVS(inc, true, false);
|
||||
ValueSetExpansionOutcome actualExpansionResult = context.expandVS(inc, true, false);
|
||||
|
||||
assertEquals(expectedValueSet, actualExpansionResult.getValueset());
|
||||
|
||||
|
@ -319,7 +319,7 @@ public class SimpleWorkerContextTests {
|
|||
|
||||
Parameters pIn = new Parameters();
|
||||
|
||||
ValueSetExpander.ValueSetExpansionOutcome actualExpansionResult = context.expandVS(vs, true, true, true, pIn);
|
||||
ValueSetExpansionOutcome actualExpansionResult = context.expandVS(vs, true, true, true, pIn);
|
||||
|
||||
assertEquals(expectedExpansionResult, actualExpansionResult);
|
||||
|
||||
|
@ -345,7 +345,7 @@ public class SimpleWorkerContextTests {
|
|||
|
||||
Mockito.doReturn(valueSetExpanderSimple).when(context).constructValueSetExpanderSimple();
|
||||
|
||||
ValueSetExpander.ValueSetExpansionOutcome actualExpansionResult = context.expandVS(vs, true, true, true, pIn);
|
||||
ValueSetExpansionOutcome actualExpansionResult = context.expandVS(vs, true, true, true, pIn);
|
||||
|
||||
assertEquals(expectedExpansionResult, actualExpansionResult);
|
||||
|
||||
|
@ -374,7 +374,7 @@ public class SimpleWorkerContextTests {
|
|||
|
||||
Mockito.doReturn(expectedValueSet).when(terminologyClient).expandValueset(eq(vs), argThat(new ParametersMatcher(pInWithDependentResources)), eq(params));
|
||||
|
||||
ValueSetExpander.ValueSetExpansionOutcome actualExpansionResult = context.expandVS(vs, true, true, true, pIn);
|
||||
ValueSetExpansionOutcome actualExpansionResult = context.expandVS(vs, true, true, true, pIn);
|
||||
|
||||
assertEquals(expectedValueSet, actualExpansionResult.getValueset());
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.hl7.fhir.r5.model.Coding;
|
|||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.TerminologyCapabilities;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.utilities.tests.ResourceLoaderTests;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -129,7 +129,7 @@ public class TerminologyCacheTests implements ResourceLoaderTests {
|
|||
terminologyCacheA.cacheValidation(codeableConceptTokenA, codeableConceptResultA, true);
|
||||
|
||||
TerminologyCache.CacheToken expansionTokenA = terminologyCacheA.generateExpandToken(valueSet, true);
|
||||
ValueSetExpander.ValueSetExpansionOutcome expansionOutcomeA = new ValueSetExpander.ValueSetExpansionOutcome(valueSet);
|
||||
ValueSetExpansionOutcome expansionOutcomeA = new ValueSetExpansionOutcome(valueSet);
|
||||
|
||||
terminologyCacheA.cacheExpansion(expansionTokenA, expansionOutcomeA, true);
|
||||
// Check that the in-memory cache is returning what we put in
|
||||
|
@ -165,7 +165,7 @@ public class TerminologyCacheTests implements ResourceLoaderTests {
|
|||
assertEquals(a.getMessage(), b.getMessage());
|
||||
}
|
||||
|
||||
private void assertExpansionOutcomeEquals(ValueSetExpander.ValueSetExpansionOutcome a, ValueSetExpander.ValueSetExpansionOutcome b) {
|
||||
private void assertExpansionOutcomeEquals(ValueSetExpansionOutcome a, ValueSetExpansionOutcome b) {
|
||||
assertEquals(a.getValueset().getUrl(), b.getValueset().getUrl());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.terminology;
|
||||
package org.hl7.fhir.r5.terminologies;
|
||||
|
||||
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
@ -22,7 +22,7 @@ import org.hl7.fhir.r5.model.Base;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ITypeParser;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"code": {
|
||||
"coding": [
|
||||
{
|
||||
"code": "dummyCode"
|
||||
}
|
||||
]
|
||||
},
|
||||
"valueSet": {
|
||||
"resourceType": "ValueSet"
|
||||
},
|
||||
"langs": "[]",
|
||||
"useServer": "true",
|
||||
"useClient": "true",
|
||||
"guessSystem": "true",
|
||||
"valueSetMode": "ALL_CHECKS",
|
||||
"versionFlexible": "false",
|
||||
"profile":{
|
||||
"resourceType":"Parameters"
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"code": {
|
||||
"coding": [
|
||||
{
|
||||
"system": "dummySystem",
|
||||
"version": "dummyVersion",
|
||||
"code": "dummyCode"
|
||||
}
|
||||
]
|
||||
},
|
||||
"valueSet": {
|
||||
"resourceType": "ValueSet"
|
||||
},
|
||||
"langs": "[]",
|
||||
"useServer": "true",
|
||||
"useClient": "true",
|
||||
"guessSystem": "true",
|
||||
"valueSetMode": "ALL_CHECKS",
|
||||
"versionFlexible": "false",
|
||||
"profile":{
|
||||
"resourceType":"Parameters"
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"code": {
|
||||
"code": "dummyCode"
|
||||
},
|
||||
"valueSet": {
|
||||
"resourceType": "ValueSet"
|
||||
},
|
||||
"langs": "[]",
|
||||
"useServer": "true",
|
||||
"useClient": "true",
|
||||
"guessSystem": "true",
|
||||
"valueSetMode": "ALL_CHECKS",
|
||||
"versionFlexible": "false",
|
||||
"profile":{
|
||||
"resourceType":"Parameters"
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"code": {
|
||||
"system": "dummySystem",
|
||||
"version": "dummyVersion",
|
||||
"code": "dummyCode"
|
||||
},
|
||||
"valueSet": {
|
||||
"resourceType": "ValueSet"
|
||||
},
|
||||
"langs": "[]",
|
||||
"useServer": "true",
|
||||
"useClient": "true",
|
||||
"guessSystem": "true",
|
||||
"valueSetMode": "ALL_CHECKS",
|
||||
"versionFlexible": "false",
|
||||
"profile":{
|
||||
"resourceType":"Parameters"
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"hierarchical": false,
|
||||
"valueSet": {
|
||||
"resourceType": "ValueSet",
|
||||
"compose": {
|
||||
"include": [
|
||||
{
|
||||
"system": "dummyIncludeSystem",
|
||||
"version": "dummyIncludeVersion"
|
||||
}
|
||||
],
|
||||
"exclude": [
|
||||
{
|
||||
"system": "dummyExcludeSystem",
|
||||
"version": "dummyExcludeVersion"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expansion": {
|
||||
"contains": [
|
||||
{
|
||||
"system": "dummyContainsSystem",
|
||||
"version": "dummyContainsVersion"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
{
|
||||
"hierarchical": true,
|
||||
"valueSet": {
|
||||
"resourceType": "ValueSet",
|
||||
"compose": {
|
||||
"include": [
|
||||
{
|
||||
"system": "dummyIncludeSystem",
|
||||
"version": "dummyIncludeVersion"
|
||||
}
|
||||
],
|
||||
"exclude": [
|
||||
{
|
||||
"system": "dummyExcludeSystem",
|
||||
"version": "dummyExcludeVersion"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expansion": {
|
||||
"contains": [
|
||||
{
|
||||
"system": "dummyContainsSystem",
|
||||
"version": "dummyContainsVersion"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -560,6 +560,7 @@ public class I18nConstants {
|
|||
public static final String UNABLE_TO_FIND_RESOURCE__AT__RESOLVING_DISCRIMINATOR__FROM_ = "Unable_to_find_resource__at__resolving_discriminator__from_";
|
||||
public static final String UNABLE_TO_FIND__RESOLVING_DISCRIMINATOR__FROM_ = "Unable_to_find__resolving_discriminator__from_";
|
||||
public static final String UNABLE_TO_HANDLE_SYSTEM__CONCEPT_FILTER_WITH_OP__ = "Unable_to_handle_system__concept_filter_with_op__";
|
||||
public static final String UNABLE_TO_HANDLE_SYSTEM__PROPERTY_FILTER_WITH_OP__ = "UNABLE_TO_HANDLE_SYSTEM__PROPERTY_FILTER_WITH_OP__";
|
||||
public static final String UNABLE_TO_HANDLE_SYSTEM__FILTER_WITH_PROPERTY__ = "Unable_to_handle_system__filter_with_property__";
|
||||
public static final String UNABLE_TO_LOCATE_THE_PROFILE__IN_ORDER_TO_VALIDATE_AGAINST_IT = "Unable_to_locate_the_profile__in_order_to_validate_against_it";
|
||||
public static final String UNABLE_TO_PROCESS_REQUEST_FOR_RESOURCE_FOR___ = "Unable_to_process_request_for_resource_for___";
|
||||
|
|
|
@ -16,7 +16,8 @@ public class FhirSettingsPOJO {
|
|||
|
||||
protected static final String TX_SERVER_PROD = "http://tx.fhir.org";
|
||||
protected static final String TX_SERVER_DEV = "http://tx-dev.fhir.org";
|
||||
protected static final String TX_SERVER_LOCAL = "http://local.fhir.org";
|
||||
// protected static final String TX_SERVER_LOCAL = "http://local.fhir.org";
|
||||
protected static final String TX_SERVER_LOCAL = "http://localhost";
|
||||
|
||||
private String fhirDirectory;
|
||||
private Map<String, String> apiKeys;
|
||||
|
|
|
@ -471,6 +471,7 @@ None_of_the_provided_codes_are_in_the_value_set_one = The provided code {2} is n
|
|||
None_of_the_provided_codes_are_in_the_value_set_other = None of the provided codes [{2}] are in the value set ''{1}''
|
||||
Coding_has_no_system__cannot_validate = Coding has no system - cannot validate
|
||||
Unable_to_handle_system__concept_filter_with_op__ = Unable to handle system {0} concept filter with op = {1}
|
||||
UNABLE_TO_HANDLE_SYSTEM__PROPERTY_FILTER_WITH_OP__ = Unable to handle system {0} property filter with op = {1}
|
||||
Unable_to_handle_system__filter_with_property__ = Unable to handle system {0} filter with property = {1}, op = {2}
|
||||
Unable_to_resolve_system__value_set_has_include_with_no_system = Unable to resolve system - value set {0} include #{1} has no system
|
||||
UNABLE_TO_RESOLVE_SYSTEM_SYSTEM_IS_INDETERMINATE = The code system {1} referred to from value set {0} has a grammar, and the code might be valid in it
|
||||
|
|
|
@ -369,12 +369,12 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
}
|
||||
engine.setVersion(version);
|
||||
engine.setIgLoader(new IgLoader(engine.getPcm(), engine.getContext(), engine.getVersion(), engine.isDebug()));
|
||||
if (THO) {
|
||||
loadTx(engine);
|
||||
}
|
||||
if (VersionUtilities.isR5Plus(version)) {
|
||||
engine.loadPackage("hl7.fhir.uv.extensions", null);
|
||||
}
|
||||
// if (THO) {
|
||||
// loadTx(engine);
|
||||
// }
|
||||
// if (VersionUtilities.isR5Plus(version)) {
|
||||
// engine.loadPackage("hl7.fhir.uv.extensions", "1.0.0");
|
||||
// }
|
||||
return engine;
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
pid = "hl7.terminology.r5";
|
||||
}
|
||||
if (pid != null) {
|
||||
engine.loadPackage(pid, null);
|
||||
engine.loadPackage(pid, "5.0.0");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ public class ValidatorCli {
|
|||
final String version = Params.getParam(args, Params.VERSION);
|
||||
final String tx = Params.getParam(args, Params.TERMINOLOGY);
|
||||
final String filter = Params.getParam(args, Params.FILTER);
|
||||
boolean ok = new TxTester(new InternalTxLoader(source, output)).setOutput(output).execute(tx, version, filter);
|
||||
boolean ok = new TxTester(new InternalTxLoader(source, output), tx).setOutput(output).execute(version, filter);
|
||||
System.exit(ok ? 1 : 0);
|
||||
} else {
|
||||
final String testModuleParam = Params.getParam(args, Params.TEST_MODULES);
|
||||
|
|
|
@ -433,7 +433,7 @@ public class CliContext {
|
|||
|
||||
@JsonProperty("sv")
|
||||
public CliContext setSv(String sv) {
|
||||
if (sv != null && sv.startsWith("R")) {
|
||||
if (sv != null && (sv.startsWith("R") || sv.startsWith("r"))) {
|
||||
this.sv = VersionUtilities.versionFromCode(sv.toLowerCase());
|
||||
} else {
|
||||
this.sv = sv;
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.hl7.fhir.r5.model.ElementDefinition;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
||||
|
@ -258,7 +258,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV
|
|||
|
||||
String root = getRoot(p, url);
|
||||
if (root != null) {
|
||||
TerminologyClient c;
|
||||
ITerminologyClient c;
|
||||
c = TerminologyClientFactory.makeClient("source", root, "fhir/validator", context.getVersion());
|
||||
return c.read(p[p.length - 2], p[p.length - 1]);
|
||||
} else {
|
||||
|
|
|
@ -143,7 +143,7 @@ import org.hl7.fhir.r5.model.UriType;
|
|||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.renderers.DataRenderer;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.BuildExtensions;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
|
|
|
@ -20,10 +20,10 @@ import org.hl7.fhir.r5.model.Questionnaire;
|
|||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemAnswerOptionComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.TimeType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
|
|
|
@ -29,8 +29,8 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ConceptMapUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.r5.utils.structuremap.ResolvedGroup;
|
||||
|
|
|
@ -10,7 +10,7 @@ import org.hl7.fhir.r5.elementmodel.Element;
|
|||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
|
|
@ -13,10 +13,9 @@ public class FHIRPathExpressionFixer {
|
|||
// return expr;
|
||||
// }
|
||||
|
||||
//TODO is this expression below correct? @grahamegrieve
|
||||
// if ("probability is decimal implies (probability as decimal) <= 100".equals(expr)) {
|
||||
// return "probability.empty() or ((probability is decimal) implies ((probability as decimal) <= 100))";
|
||||
// }
|
||||
if ("probability is decimal implies (probability as decimal) <= 100".equals(expr)) {
|
||||
return "(probability.exists() and (probability is decimal)) implies ((probability as decimal) <= 100)";
|
||||
}
|
||||
if ("enableWhen.count() > 2 implies enableBehavior.exists()".equals(expr)) {
|
||||
return "enableWhen.count() >= 2 implies enableBehavior.exists()";
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.hl7.fhir.r5.model.Resource;
|
|||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.test.utils.CompareUtilities;
|
||||
import org.hl7.fhir.r5.utils.client.EFhirClientException;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
|
@ -57,19 +57,20 @@ public class TxTester {
|
|||
private ITxTesterLoader loader;
|
||||
private String error;
|
||||
private String output;
|
||||
private ITerminologyClient tx;
|
||||
|
||||
|
||||
public TxTester(ITxTesterLoader loader) {
|
||||
public TxTester(ITxTesterLoader loader, String server) {
|
||||
super();
|
||||
this.server = server;
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TxTester(new InternalTxLoader(args[0])).execute(args[1], args[2], args[3]);
|
||||
new TxTester(new InternalTxLoader(args[0]), args[1]).execute(args[2], args[3]);
|
||||
}
|
||||
|
||||
public boolean execute(String server, String version, String filter) throws IOException, URISyntaxException {
|
||||
this.server = server;
|
||||
public boolean execute(String version, String filter) throws IOException, URISyntaxException {
|
||||
if (output == null) {
|
||||
output = Utilities.path("[tmp]", serverId());
|
||||
}
|
||||
|
@ -89,7 +90,7 @@ public class TxTester {
|
|||
json.add("date", new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(Calendar.getInstance().getTime()) + timezone());
|
||||
try {
|
||||
JsonObject tests = loadTests();
|
||||
TerminologyClient tx = connectToServer();
|
||||
ITerminologyClient tx = connectToServer();
|
||||
boolean ok = checkClient(tx);
|
||||
for (JsonObject suite : tests.getJsonObjects("suites")) {
|
||||
ok = runSuite(suite, tx, filter, json.forceArray("suites")) && ok;
|
||||
|
@ -121,7 +122,7 @@ public class TxTester {
|
|||
return offset;
|
||||
}
|
||||
|
||||
private boolean checkClient(TerminologyClient tx) {
|
||||
private boolean checkClient(ITerminologyClient tx) {
|
||||
tx.getCapabilitiesStatementQuick();
|
||||
tx.getTerminologyCapabilities();
|
||||
return true;
|
||||
|
@ -132,17 +133,18 @@ public class TxTester {
|
|||
return JsonParser.parseObject(loader.loadContent("test-cases.json"));
|
||||
}
|
||||
|
||||
private TerminologyClient connectToServer() throws URISyntaxException {
|
||||
private ITerminologyClient connectToServer() throws URISyntaxException {
|
||||
System.out.println("Connect to "+server);
|
||||
return TerminologyClientFactory.makeClient("Test-Server", server, "Tools/Java", FhirPublication.R4);
|
||||
}
|
||||
|
||||
|
||||
public String executeTest(JsonObject suite, JsonObject test, String server) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException {
|
||||
this.server = server;
|
||||
public String executeTest(JsonObject suite, JsonObject test) throws URISyntaxException, FHIRFormatError, FileNotFoundException, IOException {
|
||||
error = null;
|
||||
TerminologyClient tx = connectToServer();
|
||||
if (tx == null) {
|
||||
tx = connectToServer();
|
||||
checkClient(tx);
|
||||
}
|
||||
List<Resource> setup = loadSetupResources(suite);
|
||||
if (runTest(test, tx, setup, "*", null)) {
|
||||
return null;
|
||||
|
@ -150,7 +152,7 @@ public class TxTester {
|
|||
return error;
|
||||
}
|
||||
}
|
||||
private boolean runSuite(JsonObject suite, TerminologyClient tx, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
|
||||
private boolean runSuite(JsonObject suite, ITerminologyClient tx, String filter, JsonArray output) throws FHIRFormatError, FileNotFoundException, IOException {
|
||||
System.out.println("Group "+suite.asString("name"));
|
||||
JsonObject outputS = new JsonObject();
|
||||
if (output != null) {
|
||||
|
@ -165,7 +167,7 @@ public class TxTester {
|
|||
return ok;
|
||||
}
|
||||
|
||||
private boolean runTest(JsonObject test, TerminologyClient tx, List<Resource> setup, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
|
||||
private boolean runTest(JsonObject test, ITerminologyClient tx, List<Resource> setup, String filter, JsonArray output) throws FHIRFormatError, DefinitionException, FileNotFoundException, FHIRException, IOException {
|
||||
JsonObject outputT = new JsonObject();
|
||||
if (output != null) {
|
||||
output.add(outputT);
|
||||
|
@ -229,7 +231,7 @@ public class TxTester {
|
|||
return new URI(server).getHost();
|
||||
}
|
||||
|
||||
private String expand(TerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile) throws IOException {
|
||||
private String expand(ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile) throws IOException {
|
||||
for (Resource r : setup) {
|
||||
p.addParameter().setName("tx-resource").setResource(r);
|
||||
}
|
||||
|
@ -253,7 +255,7 @@ public class TxTester {
|
|||
return diff;
|
||||
}
|
||||
|
||||
private String validate(TerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile) throws IOException {
|
||||
private String validate(ITerminologyClient tx, List<Resource> setup, Parameters p, String resp, String fp, Parameters profile) throws IOException {
|
||||
for (Resource r : setup) {
|
||||
p.addParameter().setName("tx-resource").setResource(r);
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
|
|||
private JsonObject test;
|
||||
}
|
||||
|
||||
private static final String SERVER = FhirSettings.getTxFhirDevelopment();
|
||||
// private static final String SERVER = FhirSettings.getTxFhirLocal();
|
||||
// private static final String SERVER = FhirSettings.getTxFhirDevelopment();
|
||||
private static final String SERVER = FhirSettings.getTxFhirLocal();
|
||||
|
||||
@Parameters(name = "{index}: id {0}")
|
||||
public static Iterable<Object[]> data() throws IOException {
|
||||
|
@ -80,6 +80,7 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
|
|||
private static org.hl7.fhir.utilities.json.model.JsonObject manifest;
|
||||
private JsonObjectPair setup;
|
||||
private String version = "5.0.0";
|
||||
private static TxTester tester;
|
||||
|
||||
public ExternalTerminologyServiceTests(String name, JsonObjectPair setup) {
|
||||
this.setup = setup;
|
||||
|
@ -89,7 +90,10 @@ public class ExternalTerminologyServiceTests implements ITxTesterLoader {
|
|||
@Test
|
||||
public void test() throws Exception {
|
||||
if (SERVER != null) {
|
||||
String err = new TxTester(this).executeTest(setup.suite, setup.test, SERVER);
|
||||
if (tester == null) {
|
||||
tester = new TxTester(this, SERVER);
|
||||
}
|
||||
String err = tester.executeTest(setup.suite, setup.test);
|
||||
Assertions.assertTrue(err == null, err);
|
||||
} else {
|
||||
Assertions.assertTrue(true);
|
||||
|
|
|
@ -35,8 +35,7 @@ import org.hl7.fhir.r5.model.ValueSet;
|
|||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.test.utils.CompareUtilities;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.terminology.tests.TerminologyServiceTests.JsonObjectPair;
|
||||
|
|
|
@ -34,7 +34,7 @@ public class TestUtilities {
|
|||
|
||||
|
||||
public static ValidationEngine getValidationEngineNoTxServer(java.lang.String src, FhirPublication version, java.lang.String vString) throws Exception {
|
||||
TestingUtilities.injectCorePackageLoader();
|
||||
// TestingUtilities.injectCorePackageLoader();
|
||||
|
||||
final ValidationEngine validationEngine = new ValidationEngine.ValidationEngineBuilder()
|
||||
.withCanRunWithoutTerminologyServer(true)
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -19,7 +19,7 @@
|
|||
|
||||
<properties>
|
||||
<hapi_fhir_version>6.4.1</hapi_fhir_version>
|
||||
<validator_test_case_version>1.3.4</validator_test_case_version>
|
||||
<validator_test_case_version>1.3.5-SNAPSHOT</validator_test_case_version>
|
||||
<jackson_version>2.14.0</jackson_version>
|
||||
<junit_jupiter_version>5.9.2</junit_jupiter_version>
|
||||
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
|
||||
|
|
Loading…
Reference in New Issue