Better handle failure to find imported value sets when expanding, and track & report expansion source
And render supplement dependencies + correct error handling for expansion failure
This commit is contained in:
parent
74c2868cc1
commit
652cc8fba6
|
@ -240,7 +240,7 @@ public class CodeSystemUtilities {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static ConceptDefinitionComponent findCode(List<ConceptDefinitionComponent> list, String code) {
|
||||
public static ConceptDefinitionComponent findCode(List<ConceptDefinitionComponent> list, String code) {
|
||||
for (ConceptDefinitionComponent c : list) {
|
||||
if (c.getCode().equals(code))
|
||||
return c;
|
||||
|
|
|
@ -942,7 +942,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
try {
|
||||
ValueSet result = tc.getClient().expandValueset(vs, p);
|
||||
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
|
||||
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
|
||||
if (res != null && res.getValueset() != null) {
|
||||
res.getValueset().setUserData(UserDataNames.VS_EXPANSION_SOURCE, tc.getHost());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
res = new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.UNKNOWN, true);
|
||||
if (txLog != null) {
|
||||
|
@ -1012,7 +1015,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
throw new Error(formatMessage(I18nConstants.NO_URL_IN_EXPAND_VALUE_SET_2));
|
||||
}
|
||||
}
|
||||
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
|
||||
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
|
||||
if (res != null && res.getValueset() != null) {
|
||||
res.getValueset().setUserData(UserDataNames.VS_EXPANSION_SOURCE, tc.getHost());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
res = new ValueSetExpansionOutcome((e.getMessage() == null ? e.getClass().getName() : e.getMessage()), TerminologyServiceErrorClass.UNKNOWN, allErrors, true).setTxLink(txLog == null ? null : txLog.getLastId());
|
||||
}
|
||||
|
@ -1085,6 +1091,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
res = null;
|
||||
try {
|
||||
res = vse.expand(vs, p);
|
||||
if (res != null && res.getValueset() != null) {
|
||||
res.getValueset().setUserData(UserDataNames.VS_EXPANSION_SOURCE, vse.getSource());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
allErrors.addAll(vse.getAllErrors());
|
||||
e.printStackTrace();
|
||||
|
@ -1098,7 +1107,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
txCache.cacheExpansion(cacheToken, res, TerminologyCache.TRANSIENT);
|
||||
return res;
|
||||
}
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.INTERNAL_ERROR || isNoTerminologyServer()) { // this class is created specifically to say: don't consult the server
|
||||
if (res.getErrorClass() == TerminologyServiceErrorClass.INTERNAL_ERROR || isNoTerminologyServer() || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNKNOWN) { // this class is created specifically to say: don't consult the server
|
||||
return new ValueSetExpansionOutcome(res.getError(), res.getErrorClass(), false);
|
||||
}
|
||||
|
||||
|
@ -1133,6 +1142,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
res = new ValueSetExpansionOutcome((e.getMessage() == null ? e.getClass().getName() : e.getMessage()), TerminologyServiceErrorClass.UNKNOWN, allErrors, true).setTxLink(txLog == null ? null : txLog.getLastId());
|
||||
}
|
||||
}
|
||||
if (res != null && res.getValueset() != null) {
|
||||
res.getValueset().setUserData(UserDataNames.VS_EXPANSION_SOURCE, tc.getHost());
|
||||
}
|
||||
txCache.cacheExpansion(cacheToken, res, TerminologyCache.PERMANENT);
|
||||
return res;
|
||||
}
|
||||
|
@ -1698,6 +1710,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
}
|
||||
Set<String> unknownSystems = new HashSet<>();
|
||||
if ("8517006".equals(code.getCodingFirstRep().getCode())) {
|
||||
DebugUtilities.breakpoint();
|
||||
}
|
||||
|
||||
List<OperationOutcomeIssueComponent> issues = new ArrayList<>();
|
||||
|
||||
|
|
|
@ -90,7 +90,20 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
if (vs.hasCopyright())
|
||||
generateCopyright(x, r);
|
||||
}
|
||||
|
||||
if (vs.hasExtension(ToolingExtensions.EXT_VS_CS_SUPPL_NEEDED)) {
|
||||
var p = x.para();
|
||||
p.tx("This ValueSet requires the Code system Supplement ");
|
||||
String u = ToolingExtensions.readStringExtension(vs, ToolingExtensions.EXT_VS_CS_SUPPL_NEEDED);
|
||||
CodeSystem cs = context.getContext().fetchResource(CodeSystem.class, u);
|
||||
if (cs == null) {
|
||||
p.code().tx(u);
|
||||
} else if (!cs.hasWebPath()) {
|
||||
p.ah(u).tx(cs.present());
|
||||
} else {
|
||||
p.ah(cs.getWebPath()).tx(cs.present());
|
||||
}
|
||||
p.tx(".");
|
||||
}
|
||||
if (vs.hasExpansion()) {
|
||||
// for now, we just accept an expansion if there is one
|
||||
generateExpansion(status, r, x, vs, false, maps);
|
||||
|
@ -498,14 +511,26 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
if (versions.size() == 1 && versions.get(s).size() == 1) {
|
||||
for (String v : versions.get(s)) { // though there'll only be one
|
||||
XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px");
|
||||
p.tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSION)+" ");
|
||||
if (!vs.hasUserData(UserDataNames.VS_EXPANSION_SOURCE)) {
|
||||
p.tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSION)+" ");
|
||||
} else if ("internal".equals(vs.getUserString(UserDataNames.VS_EXPANSION_SOURCE))) {
|
||||
p.tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSION_INTERNAL)+" ");
|
||||
} else {
|
||||
p.tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSION_SRVR, vs.getUserString(UserDataNames.VS_EXPANSION_SOURCE))+" ");
|
||||
}
|
||||
expRef(p, s, v, vs);
|
||||
}
|
||||
} else {
|
||||
for (String v : versions.get(s)) {
|
||||
if (first) {
|
||||
div = x.div().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px");
|
||||
div.para().tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSIONS));
|
||||
if (!vs.hasUserData(UserDataNames.VS_EXPANSION_SOURCE)) {
|
||||
div.para().tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSIONS));
|
||||
} else if ("internal".equals(vs.getUserString(UserDataNames.VS_EXPANSION_SOURCE))) {
|
||||
div.para().tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSIONS_INTERNAL));
|
||||
} else {
|
||||
div.para().tx(context.formatPhrase(RenderingContext.VALUE_SET_EXPANSIONS_SRVR, vs.getUserString(UserDataNames.VS_EXPANSION_SOURCE)));
|
||||
}
|
||||
ul = div.ul();
|
||||
first = false;
|
||||
}
|
||||
|
|
|
@ -48,8 +48,10 @@ import org.hl7.fhir.r5.model.StringType;
|
|||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.Identifier;
|
||||
import org.hl7.fhir.r5.model.Meta;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
|
@ -65,6 +67,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.ConceptDefinitionComponentSorter;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.ConceptStatus;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
|
||||
import org.hl7.fhir.r5.utils.CanonicalResourceUtilities;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.UserDataNames;
|
||||
|
@ -501,4 +504,97 @@ public class ValueSetUtilities extends TerminologyUtilities {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String versionFromExpansionParams(Parameters expParameters, String system, String defaultVersion) {
|
||||
for (ParametersParameterComponent p : expParameters.getParameter()) {
|
||||
if ("system-version".equals(p.getName()) || "force-system-version".equals(p.getName())) {
|
||||
String v = p.getValue().primitiveValue();
|
||||
if (v.startsWith(system+"|")) {
|
||||
String ver = v.substring(v.indexOf("|")+1);
|
||||
if (defaultVersion == null || ver.startsWith(defaultVersion) || "force-system-version".equals(p.getName())) {
|
||||
return ver;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultVersion;
|
||||
}
|
||||
|
||||
public static boolean isImplicitLoincValueSet(String url) {
|
||||
return url.startsWith("http://loinc.org/vs");
|
||||
}
|
||||
|
||||
public static boolean isImplicitSCTValueSet(String url) {
|
||||
return url.startsWith("http://snomed.info/sct") && url.contains("?fhir_vs");
|
||||
}
|
||||
|
||||
public static ValueSet makeImplicitValueSet(String url, String version) {
|
||||
if (url.startsWith("http://snomed.info/sct")) {
|
||||
return makeImplicitSCTVS(url, version);
|
||||
} else if (url.startsWith("http://loinc.org/vs")) {
|
||||
return makeImplicitLoincVS(url, version);
|
||||
} else {
|
||||
throw new FHIRException("Unknown implicit value set URL "+url);
|
||||
}
|
||||
}
|
||||
|
||||
private static ValueSet makeImplicitSCTVS(String url, String version) {
|
||||
String query = url.substring(url.indexOf("?")+1);
|
||||
if ("fhir_vs".equals(query)) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
vs.getCompose().addInclude().setSystem("http://snomed.info/sct");
|
||||
return vs;
|
||||
} else if (query.startsWith("fhir_vs=isa/")) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
vs.getCompose().addInclude().setSystem("http://snomed.info/sct").addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue(query.substring(12));
|
||||
return vs;
|
||||
} else if (query.equals("fhir_vs=refset")) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
vs.getCompose().addInclude().setSystem("http://snomed.info/sct").addFilter().setProperty("concept").setOp(FilterOperator.ISA).setValue("refset-base");
|
||||
return vs;
|
||||
} else if (query.startsWith("fhir_vs=refset/")) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
vs.getCompose().addInclude().setSystem("http://snomed.info/sct").addFilter().setProperty("concept").setOp(FilterOperator.IN).setValue(query.substring(15));
|
||||
return vs;
|
||||
} else {
|
||||
throw new FHIRException("Unknown implicit SNOMED CT value set URL "+url);
|
||||
}
|
||||
}
|
||||
|
||||
private static ValueSet makeImplicitLoincVS(String url, String version) {
|
||||
if (url.equals("http://loinc.org/vs")) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
vs.getCompose().addInclude().setSystem("http://loinc.org");
|
||||
return vs;
|
||||
} else if (url.startsWith("http://loinc.org/vs/LP")) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
vs.getCompose().addInclude().setSystem("http://loinc.org").addFilter().setProperty("ancestor").setOp(FilterOperator.EQUAL).setValue(url.substring(21));
|
||||
return vs;
|
||||
} else if (url.startsWith("http://loinc.org/vs/LL")) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setUrl(url);
|
||||
vs.setVersion(version);
|
||||
// this isn't the actual definition, but it won't matter to us internally
|
||||
vs.getCompose().addInclude().setSystem("http://loinc.org").addFilter().setProperty("answer-list").setOp(FilterOperator.EQUAL).setValue(url.substring(21));
|
||||
return vs;
|
||||
} else {
|
||||
throw new FHIRException("Unknown implicit LOINC value set URL "+url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
package org.hl7.fhir.r5.terminologies.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
@ -218,5 +220,14 @@ public class TerminologyClientContext {
|
|||
public static void setCanUseCacheId(boolean canUseCacheId) {
|
||||
TerminologyClientContext.canUseCacheId = canUseCacheId;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
try {
|
||||
URL uri = new URL(getAddress());
|
||||
return uri.getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
return getAddress();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -70,7 +70,9 @@ import java.util.ArrayList;
|
|||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
|
@ -116,6 +118,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpander.UnknownValueSetException;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
|
||||
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext;
|
||||
|
@ -135,6 +138,26 @@ import org.hl7.fhir.utilities.i18n.I18nConstants;
|
|||
public class ValueSetExpander extends ValueSetProcessBase {
|
||||
|
||||
|
||||
public class UnknownValueSetException extends FHIRException {
|
||||
|
||||
protected UnknownValueSetException() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected UnknownValueSetException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
protected UnknownValueSetException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
protected UnknownValueSetException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Token {
|
||||
private String system;
|
||||
private String code;
|
||||
|
@ -169,6 +192,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
private boolean checkCodesWhenExpanding;
|
||||
private boolean includeAbstract = true;
|
||||
private boolean debug;
|
||||
private Set<String> sources = new HashSet<>();
|
||||
|
||||
private AcceptLanguageHeader langs;
|
||||
private List<Token> designations = new ArrayList<>();
|
||||
|
@ -612,6 +636,9 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem(), opContext.getOptions().getFhirVersion())) {
|
||||
ValueSetExpansionOutcome vse = context.expandVS(new TerminologyOperationDetails(requiredSupplements), exc, false, false);
|
||||
ValueSet valueset = vse.getValueset();
|
||||
if (valueset.hasUserData(UserDataNames.VS_EXPANSION_SOURCE)) {
|
||||
sources.add(valueset.getUserString(UserDataNames.VS_EXPANSION_SOURCE));
|
||||
}
|
||||
if (valueset == null)
|
||||
throw failTSE("Error Expanding ValueSet: "+vse.getError());
|
||||
excludeCodes(wc, valueset.getExpansion());
|
||||
|
@ -677,6 +704,8 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
}
|
||||
} catch (ETooCostly e) {
|
||||
return new ValueSetExpansionOutcome(e.getMessage(), TerminologyServiceErrorClass.TOO_COSTLY, allErrors, false);
|
||||
} catch (UnknownValueSetException e) {
|
||||
return new ValueSetExpansionOutcome(e.getMessage(), TerminologyServiceErrorClass.VALUESET_UNKNOWN, allErrors, false);
|
||||
} catch (Exception e) {
|
||||
if (debug) {
|
||||
e.printStackTrace();
|
||||
|
@ -870,9 +899,9 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
boolean pinned = !url.equals(value);
|
||||
String ver = pinned ? url.substring(value.length()+1) : null;
|
||||
if (context.fetchResource(CodeSystem.class, url, valueSet) != null) {
|
||||
throw fail(pinned ? I18nConstants.VS_EXP_IMPORT_CS_PINNED : I18nConstants.VS_EXP_IMPORT_CS, true, value, ver);
|
||||
throw failUnk(pinned ? I18nConstants.VS_EXP_IMPORT_CS_PINNED : I18nConstants.VS_EXP_IMPORT_CS, true, value, ver);
|
||||
} else {
|
||||
throw fail(pinned ? I18nConstants.VS_EXP_IMPORT_UNK_PINNED : I18nConstants.VS_EXP_IMPORT_UNK, true, value, ver);
|
||||
throw failUnk(pinned ? I18nConstants.VS_EXP_IMPORT_UNK_PINNED : I18nConstants.VS_EXP_IMPORT_UNK, true, value, ver);
|
||||
}
|
||||
}
|
||||
checkCanonical(exp, vs, focus);
|
||||
|
@ -880,13 +909,19 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
expParams = expParams.copy();
|
||||
expParams.addParameter("activeOnly", true);
|
||||
}
|
||||
ValueSetExpansionOutcome vso = new ValueSetExpander(context, opContext.copy(), allErrors).expand(vs, expParams);
|
||||
ValueSetExpander expander = new ValueSetExpander(context, opContext.copy(), allErrors);
|
||||
ValueSetExpansionOutcome vso = expander.expand(vs, expParams);
|
||||
if (vso.getError() != null) {
|
||||
addErrors(vso.getAllErrors());
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_ERROR, true, vs.getUrl(), vso.getError());
|
||||
if (vso.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNKNOWN) {
|
||||
throw failUnk(I18nConstants.VS_EXP_IMPORT_ERROR, true, vs.getUrl(), vso.getError());
|
||||
} else {
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_ERROR, true, vs.getUrl(), vso.getError());
|
||||
}
|
||||
} else if (vso.getValueset() == null) {
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_FAIL, true, vs.getUrl());
|
||||
}
|
||||
sources.addAll(expander.sources);
|
||||
if (vs.hasVersion() || REPORT_VERSION_ANYWAY) {
|
||||
UriType u = new UriType(vs.getUrl() + (vs.hasVersion() ? "|"+vs.getVersion() : ""));
|
||||
if (!existsInParams(exp.getParameter(), "used-valueset", u))
|
||||
|
@ -938,10 +973,12 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
expParams = expParams.copy();
|
||||
expParams.addParameter("activeOnly", true);
|
||||
}
|
||||
ValueSetExpansionOutcome vso = new ValueSetExpander(context, opContext.copy(), allErrors).expand(vs, expParams);
|
||||
ValueSetExpander expander = new ValueSetExpander(context, opContext.copy(), allErrors);
|
||||
ValueSetExpansionOutcome vso = expander.expand(vs, expParams);
|
||||
sources.addAll(expander.sources);
|
||||
if (vso.getError() != null) {
|
||||
addErrors(vso.getAllErrors());
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_ERROR_X, true, vs.getUrl(), vso.getError());
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_ERROR, true, vs.getUrl(), vso.getError());
|
||||
} else if (vso.getValueset() == null) {
|
||||
throw fail(I18nConstants.VS_EXP_IMPORT_FAIL_X, true, vs.getUrl());
|
||||
}
|
||||
|
@ -1055,6 +1092,9 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
throw failTSE("Unable to expand imported value set: " + vso.getError());
|
||||
}
|
||||
ValueSet vs = vso.getValueset();
|
||||
if (vs.hasUserData(UserDataNames.VS_EXPANSION_SOURCE)) {
|
||||
sources.add(vs.getUserString(UserDataNames.VS_EXPANSION_SOURCE));
|
||||
}
|
||||
if (vs.hasVersion() || REPORT_VERSION_ANYWAY) {
|
||||
UriType u = new UriType(vs.getUrl() + (vs.hasVersion() ? "|"+vs.getVersion() : ""));
|
||||
if (!existsInParams(exp.getParameter(), "used-valueset", u)) {
|
||||
|
@ -1328,6 +1368,12 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
return new FHIRException(msg);
|
||||
}
|
||||
|
||||
private UnknownValueSetException failUnk(String msgId, boolean check, Object... params) {
|
||||
String msg = context.formatMessage(msgId, params);
|
||||
allErrors.add(msg);
|
||||
return new UnknownValueSetException(msg);
|
||||
}
|
||||
|
||||
private ETooCostly failCostly(String msg) {
|
||||
allErrors.add(msg);
|
||||
return new ETooCostly(msg);
|
||||
|
@ -1371,6 +1417,14 @@ public class ValueSetExpander extends ValueSetProcessBase {
|
|||
this.debug = debug;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
if (sources.isEmpty()) {
|
||||
return "internal";
|
||||
} else {
|
||||
return CommaSeparatedStringBuilder.join(", ", Utilities.sorted(sources));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -56,6 +56,7 @@ import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
|
||||
import org.hl7.fhir.r5.utils.UserDataNames;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.IniFile;
|
||||
import org.hl7.fhir.utilities.StringPair;
|
||||
|
@ -419,7 +420,7 @@ public class TerminologyCache {
|
|||
nameCacheToken(vs, ct);
|
||||
JsonParser json = new JsonParser();
|
||||
json.setOutputStyle(OutputStyle.PRETTY);
|
||||
String expJS = json.composeString(expParameters);
|
||||
String expJS = expParameters == null ? "" : json.composeString(expParameters);
|
||||
|
||||
if (vs != null && vs.hasUrl() && vs.hasVersion()) {
|
||||
ct.request = "{\"code\" : "+json.composeString(code, "codeableConcept")+", \"url\": \""+Utilities.escapeJson(vs.getUrl())
|
||||
|
@ -699,8 +700,12 @@ public class TerminologyCache {
|
|||
sw.write("e: {\r\n");
|
||||
if (ce.e.isFromServer())
|
||||
sw.write(" \"from-server\" : true,\r\n");
|
||||
if (ce.e.getValueset() != null)
|
||||
if (ce.e.getValueset() != null) {
|
||||
if (ce.e.getValueset().hasUserData(UserDataNames.VS_EXPANSION_SOURCE)) {
|
||||
sw.write(" \"source\" : "+Utilities.escapeJson(ce.e.getValueset().getUserString(UserDataNames.VS_EXPANSION_SOURCE)).trim()+",\r\n");
|
||||
}
|
||||
sw.write(" \"valueSet\" : "+json.composeString(ce.e.getValueset()).trim()+",\r\n");
|
||||
}
|
||||
sw.write(" \"error\" : \""+Utilities.escapeJson(ce.e.getError()).trim()+"\"\r\n}\r\n");
|
||||
} else if (ce.s != null) {
|
||||
sw.write("s: {\r\n");
|
||||
|
@ -820,10 +825,14 @@ public class TerminologyCache {
|
|||
JsonObject o = (JsonObject) new com.google.gson.JsonParser().parse(resultString);
|
||||
String error = loadJS(o.get("error"));
|
||||
if (e == 'e') {
|
||||
if (o.has("valueSet"))
|
||||
if (o.has("valueSet")) {
|
||||
ce.e = new ValueSetExpansionOutcome((ValueSet) new JsonParser().parse(o.getAsJsonObject("valueSet")), error, TerminologyServiceErrorClass.UNKNOWN, o.has("from-server"));
|
||||
else
|
||||
if (o.has("source")) {
|
||||
ce.e.getValueset().setUserData(UserDataNames.VS_EXPANSION_SOURCE, o.get("source").getAsString());
|
||||
}
|
||||
} else {
|
||||
ce.e = new ValueSetExpansionOutcome(error, TerminologyServiceErrorClass.UNKNOWN, o.has("from-server"));
|
||||
}
|
||||
} else if (e == 's') {
|
||||
ce.s = new SubsumesResult(o.get("result").getAsBoolean());
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.hl7.fhir.r5.terminologies.utilities;
|
||||
|
||||
public enum TerminologyServiceErrorClass {
|
||||
UNKNOWN, NOSERVICE, SERVER_ERROR, VALUESET_UNSUPPORTED, CODESYSTEM_UNSUPPORTED, CODESYSTEM_UNSUPPORTED_VERSION, BLOCKED_BY_OPTIONS, INTERNAL_ERROR, BUSINESS_RULE, TOO_COSTLY, PROCESSING;
|
||||
UNKNOWN, NOSERVICE, SERVER_ERROR, VALUESET_UNSUPPORTED, CODESYSTEM_UNSUPPORTED, CODESYSTEM_UNSUPPORTED_VERSION, BLOCKED_BY_OPTIONS, INTERNAL_ERROR, BUSINESS_RULE, TOO_COSTLY, PROCESSING, VALUESET_UNKNOWN;
|
||||
|
||||
public boolean isInfrastructure() {
|
||||
return this == NOSERVICE || this == SERVER_ERROR || this == VALUESET_UNSUPPORTED;
|
||||
|
|
|
@ -138,6 +138,6 @@ public class UserDataNames {
|
|||
public static final String kindling_ballot_package = "ballot.package";
|
||||
public static final String archetypeSource = "archetype-source";
|
||||
public static final String archetypeName = "archetype-name";
|
||||
|
||||
public static final String VS_EXPANSION_SOURCE = "VS_EXPANSION_SOURCE";
|
||||
|
||||
}
|
||||
|
|
|
@ -865,6 +865,10 @@ public class RenderingI18nContext extends I18nBase {
|
|||
public static final String VALUE_SET_EXP = "VALUE_SET_EXP";
|
||||
public static final String VALUE_SET_EXPANSION = "VALUE_SET_EXPANSION";
|
||||
public static final String VALUE_SET_EXPANSIONS = "VALUE_SET_EXPANSIONS";
|
||||
public static final String VALUE_SET_EXPANSION_SRVR = "VALUE_SET_EXPANSION_SRVR";
|
||||
public static final String VALUE_SET_EXPANSIONS_SRVR = "VALUE_SET_EXPANSIONS_SRVR";
|
||||
public static final String VALUE_SET_EXPANSION_INTERNAL = "VALUE_SET_EXPANSION_INTERNAL";
|
||||
public static final String VALUE_SET_EXPANSIONS_INTERNAL = "VALUE_SET_EXPANSIONS_INTERNAL";
|
||||
public static final String VALUE_SET_EXP_FRAG = "VALUE_SET_EXP_FRAG";
|
||||
public static final String VALUE_SET_GENERALIZES = "VALUE_SET_GENERALIZES";
|
||||
public static final String VALUE_SET_HAS = "VALUE_SET_HAS";
|
||||
|
|
|
@ -1191,15 +1191,13 @@ VS_EXP_IMPORT_UNK = Unable to find included value set ''{0}''
|
|||
VS_EXP_IMPORT_UNK_PINNED = Unable to find included value set ''{0}'' version ''{1}''
|
||||
VS_EXP_IMPORT_NULL = Unable to find included value set with no identity
|
||||
VS_EXP_IMPORT_ERROR = Unable to expand included value set ''{0}'': {1}
|
||||
VS_EXP_IMPORT_ERROR = Unable to expand included value set ''{0}'', but no error
|
||||
VS_EXP_IMPORT_ERROR_X = Unable to expand included value set ''{0}'', but no error
|
||||
VS_EXP_IMPORT_ERROR_TOO_COSTLY = Unable to expand excluded value set ''{0}'': too costly
|
||||
VS_EXP_IMPORT_CS_X = Cannot exclude value set ''{0}'' because it's actually a code system
|
||||
VS_EXP_IMPORT_CS_PINNED_X = Cannot exclude value set ''{0}'' version ''{1}'' because it's actually a code system
|
||||
VS_EXP_IMPORT_UNK_X = Unable to find excluded value set ''{0}''
|
||||
VS_EXP_IMPORT_UNK_PINNED_X = Unable to find excluded value set ''{0}'' version ''{1}''
|
||||
VS_EXP_IMPORT_NUL_XL = Unable to find excluded value set with no identity
|
||||
VS_EXP_IMPORT_ERROR_X = Unable to expand excluded value set ''{0}'': {1}
|
||||
VS_EXP_IMPORT_ERROR_X = Unable to expand excluded value set ''{0}'', but no error
|
||||
VS_EXP_IMPORT_ERROR_TOO_COSTLY = Unable to expand excluded value set ''{0}'': too costly
|
||||
VS_EXP_FILTER_UNK = ValueSet ''{0}'' Filter by property ''{1}'' and op ''{2}'' is not supported yet
|
||||
CONCEPTMAP_VS_NOT_A_VS = Reference must be to a ValueSet, but found a {0} instead
|
||||
SD_DERIVATION_NO_CONCRETE = {0} is labeled as an abstract type, but no concrete descendants were found (check definitions - this is usually an error unless concrete definitions are in some other package)
|
||||
|
|
|
@ -851,6 +851,10 @@ VALUE_SET_EXISTS = exists
|
|||
VALUE_SET_EXP = Expansion based on example code system
|
||||
VALUE_SET_EXPANSION = Expansion based on
|
||||
VALUE_SET_EXPANSIONS = Expansion based on:
|
||||
VALUE_SET_EXPANSION_SRVR = Expansion from {0} based on
|
||||
VALUE_SET_EXPANSIONS_SRVR = Expansion from {0} based on:
|
||||
VALUE_SET_EXPANSION_INTERNAL = Expansion done internally based on
|
||||
VALUE_SET_EXPANSIONS_INTERNAL = Expansion done internally based on:
|
||||
VALUE_SET_EXP_FRAG = Expansion based on code system fragment
|
||||
VALUE_SET_GENERALIZES = generalizes
|
||||
VALUE_SET_HAS = This value set has {0} codes in it. In order to keep the publication size manageable, only a selection ({1} codes) of the whole set of codes is shown.
|
||||
|
|
|
@ -184,6 +184,9 @@ private static TxTestData testData;
|
|||
case UNKNOWN:
|
||||
e.setCode(IssueType.UNKNOWN);
|
||||
break;
|
||||
case VALUESET_UNKNOWN:
|
||||
e.setCode(IssueType.UNKNOWN);
|
||||
break;
|
||||
case VALUESET_UNSUPPORTED:
|
||||
e.setCode(IssueType.NOTSUPPORTED);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue