Fix expansion related bugs and adjust tests accordingly

This commit is contained in:
Grahame Grieve 2024-01-19 10:39:29 +11:00
parent 29dbcbfb63
commit bf57789467
10 changed files with 165 additions and 82 deletions

View File

@ -866,16 +866,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (noTerminologyServer) {
return new ValueSetExpansionOutcome(formatMessage(I18nConstants.ERROR_EXPANDING_VALUESET_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, false);
}
Map<String, String> params = new HashMap<String, String>();
params.put("_limit", Integer.toString(expandCodesLimit ));
params.put("_incomplete", "true");
p.addParameter("count", expandCodesLimit);
p.addParameter("offset", 0);
txLog("$expand on "+txCache.summary(vs)+" on "+tc.getAddress());
if (addDependentResources(tc, p, vs)) {
p.addParameter().setName("cache-id").setValue(new IdType(terminologyClientManager.getCacheId()));
}
try {
ValueSet result = tc.getClient().expandValueset(vs, p, params);
ValueSet result = tc.getClient().expandValueset(vs, p, null);
res = new ValueSetExpansionOutcome(result).setTxLink(txLog.getLastId());
} catch (Exception e) {
res = new ValueSetExpansionOutcome(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), TerminologyServiceErrorClass.UNKNOWN, true);
@ -904,6 +903,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
public ValueSetExpansionOutcome expandVS(ValueSet vs, boolean cacheOk, boolean hierarchical, boolean incompleteOk, Parameters pIn) {
return expandVS(vs, cacheOk, hierarchical, incompleteOk, pIn, false);
}
public ValueSetExpansionOutcome expandVS(ValueSet vs, boolean cacheOk, boolean hierarchical, boolean incompleteOk, Parameters pIn, boolean noLimits) {
if (pIn == null) {
throw new Error(formatMessage(I18nConstants.NO_PARAMETERS_PROVIDED_TO_EXPANDVS));
}
@ -934,7 +937,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
return res;
}
}
if (!noLimits) {
p.addParameter("count", expandCodesLimit);
p.addParameter("offset", 0);
}
p.setParameter("excludeNested", !hierarchical);
if (incompleteOk) {
p.setParameter("incomplete-ok", true);
@ -973,15 +980,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
Set<String> systems = findRelevantSystems(vs);
TerminologyClientContext tc = terminologyClientManager.chooseServer(systems, true);
addDependentResources(tc, p, vs);
Map<String, String> params = new HashMap<String, String>();
params.put("_limit", Integer.toString(expandCodesLimit ));
params.put("_incomplete", "true");
txLog("$expand on "+txCache.summary(vs)+" on "+tc.getAddress());
try {
ValueSet result = tc.getClient().expandValueset(vs, p, params);
ValueSet result = tc.getClient().expandValueset(vs, p, null);
if (result != null) {
if (!result.hasUrl()) {
result.setUrl(vs.getUrl());

View File

@ -1729,6 +1729,11 @@ public String toString() {
return this;
}
public Parameters addParameter(String name, int i) {
addParameter().setName(name).setValue(new IntegerType(i));
return this;
}
public Parameters addParameter(String name, String s) {
if (s != null)
addParameter().setName(name).setValue(new StringType(s));

View File

@ -7,8 +7,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
@ -191,22 +193,35 @@ public class ValueSetRenderer extends TerminologyRenderer {
generateVersionNotice(x, vs.getExpansion(), vs);
if (ToolingExtensions.hasExtension(vs.getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY)) {
List<Extension> exl = vs.getExpansion().getExtensionsByUrl(ToolingExtensions.EXT_EXP_TOOCOSTLY);
boolean other = false;
for (Extension ex : exl) {
if (ex.getValue() instanceof BooleanType) {
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? getContext().getTooCostlyNoteEmpty() : getContext().getTooCostlyNoteNotEmpty());
} else if (!other) {
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? getContext().getTooCostlyNoteEmptyDependent() : getContext().getTooCostlyNoteNotEmptyDependent());
other = true;
}
// List<Extension> exl = vs.getExpansion().getExtensionsByUrl(ToolingExtensions.EXT_EXP_TOOCOSTLY);
// boolean other = false;
// for (Extension ex : exl) {
// if (ex.getValue() instanceof BooleanType) {
// x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? getContext().getTooCostlyNoteEmpty() : getContext().getTooCostlyNoteNotEmpty());
// } else if (!other) {
// x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(vs.getExpansion().getContains().isEmpty() ? getContext().getTooCostlyNoteEmptyDependent() : getContext().getTooCostlyNoteNotEmptyDependent());
// other = true;
// }
// }
String msg = null;
if (vs.getExpansion().getContains().isEmpty()) {
msg = "This value set cannot be expanded because of the way it is defined - it has an infinite number of members"; // not sure that's true?
} else {
msg = "This value set cannot be fully expanded, but a selection ("+countMembership(vs)+" codes) of the whole set of codes is shown here";
}
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px").addText(msg);
} else {
Integer count = countMembership(vs);
if (count == null)
x.para().tx("This value set does not contain a fixed number of concepts");
else
x.para().tx("This value set contains "+(hasFragment ? "at least " : "")+count.toString()+" concepts");
int count = conceptCount(vs.getExpansion().getContains());
if (vs.getExpansion().hasTotal()) {
if (count != vs.getExpansion().getTotal()) {
x.para().style("border: maroon 1px solid; background-color: #FFCCCC; font-weight: bold; padding: 8px")
.addText("This value set has "+(hasFragment ? "at least " : "")+vs.getExpansion().getTotal()+" codes in it. In order to keep the publication size manageable, only a selection ("+count+" codes) of the whole set of codes is shown");
} else {
x.para().tx("This value set contains "+(hasFragment ? "at least " : "")+vs.getExpansion().getTotal()+" concepts");
}
} else {
x.para().tx("This value set expansion contains "+count+" concepts");
}
}
@ -403,7 +418,6 @@ public class ValueSetRenderer extends TerminologyRenderer {
return null;
}
private Integer countMembership(ValueSet vs) {
int count = 0;
if (vs.hasExpansion())
@ -457,9 +471,11 @@ public class ValueSetRenderer extends TerminologyRenderer {
@SuppressWarnings("rawtypes")
private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion, Resource vs) {
Multimap<String, String> versions = HashMultimap.create();
Set<String> vlist = new HashSet<>();
for (ValueSetExpansionParameterComponent p : expansion.getParameter()) {
if (p.getName().startsWith("used-") || p.getName().equals("version")) {
if ((p.getName().startsWith("used-") || p.getName().equals("version")) && !vlist.contains(p.getValue().primitiveValue())) {
String name = p.getName().equals("version") ? "system" : p.getName().substring(5);
vlist.add(p.getValue().primitiveValue());
String[] parts = ((PrimitiveType) p.getValue()).asStringValue().split("\\|");
if (parts.length == 2 && !Utilities.noString(parts[0]))
versions.put(name+"|"+parts[0], parts[1]);

View File

@ -60,6 +60,7 @@ import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.ConceptDefinitionComponentSorter;
@ -456,5 +457,29 @@ public class ValueSetUtilities extends TerminologyUtilities {
}
return systems;
}
private static int conceptCount(List<ValueSetExpansionContainsComponent> list) {
int count = 0;
for (ValueSetExpansionContainsComponent c : list) {
if (!c.getAbstract())
count++;
count = count + conceptCount(c.getContains());
}
return count;
}
public static boolean isIncompleteExpansion(ValueSet valueSet) {
if (valueSet.hasExpansion()) {
ValueSetExpansionComponent exp = valueSet.getExpansion();
if (exp.hasTotal()) {
if (exp.getTotal() != conceptCount(exp.getContains())) {
return true;
}
}
}
return false;
}
}

View File

@ -35,6 +35,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.MessageFormat;
/*
* Copyright (c) 2011+, HL7, Inc
@ -186,7 +187,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
private ValueSetExpansionContainsComponent addCode(WorkingContext wc, String system, String code, String display, String dispLang, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
boolean isAbstract, boolean inactive, List<ValueSet> filters, boolean noInactive, boolean deprecated, List<ValueSetExpansionPropertyComponent> vsProp,
List<ConceptPropertyComponent> csProps, CodeSystem cs, List<org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent> expProps, List<Extension> csExtList, List<Extension> vsExtList, ValueSetExpansionComponent exp) throws ETooCostly {
List<ConceptPropertyComponent> csProps, CodeSystem cs, List<org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent> expProps, List<Extension> csExtList, List<Extension> vsExtList, ValueSetExpansionComponent exp, boolean countToTotal) throws ETooCostly {
opContext.deadCheck();
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code, exp))
@ -323,14 +324,16 @@ public class ValueSetExpander extends ValueSetProcessBase {
} else {
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 (countToTotal) {
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 (wc.isCanBeHeirarchy() && parent != null) {
parent.getContains().add(n);
@ -443,19 +446,19 @@ public class ValueSetExpander extends ValueSetProcessBase {
return null;
}
private void addCodeAndDescendents(WorkingContext wc, ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp) throws FHIRException, ETooCostly {
private void addCodeAndDescendents(WorkingContext wc, ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps, ValueSet vsSrc, ValueSetExpansionComponent exp, boolean countToTotal) throws FHIRException, ETooCostly {
opContext.deadCheck();
focus.checkNoModifiers("Expansion.contains", "expanding");
ValueSetExpansionContainsComponent np = null;
for (String code : getCodesForConcept(focus, expParams)) {
ValueSetExpansionContainsComponent t = addCode(wc, focus.getSystem(), code, focus.getDisplay(), vsSrc.getLanguage(), parent,
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), filters, noInactive, false, vsProps, makeCSProps(focus.getExtensionString(ToolingExtensions.EXT_DEFINITION), null), null, focus.getProperty(), null, focus.getExtension(), exp);
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), filters, noInactive, false, vsProps, makeCSProps(focus.getExtensionString(ToolingExtensions.EXT_DEFINITION), null), null, focus.getProperty(), null, focus.getExtension(), exp, countToTotal);
if (np == null) {
np = t;
}
}
for (ValueSetExpansionContainsComponent c : focus.getContains())
addCodeAndDescendents(wc, c, np, expParams, filters, noInactive, vsProps, vsSrc, exp);
addCodeAndDescendents(wc, c, np, expParams, filters, noInactive, vsProps, vsSrc, exp, countToTotal);
}
private List<ConceptPropertyComponent> makeCSProps(String definition, List<ConceptPropertyComponent> list) {
@ -506,7 +509,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
boolean dep = CodeSystemUtilities.isDeprecated(cs, def, false);
if ((includeAbstract || !abs) && filterFunc.includeConcept(cs, def) && passesOtherFilters(otherFilters, cs, def.getCode())) {
for (String code : getCodesForConcept(def, expParams)) {
ValueSetExpansionContainsComponent t = addCode(wc, system, code, def.getDisplay(), cs.getLanguage(), parent, def.getDesignation(), expParams, abs, inc, filters, noInactive, dep, vsProps, makeCSProps(def.getDefinition(), def.getProperty()), cs, null, def.getExtension(), null, exp);
ValueSetExpansionContainsComponent t = addCode(wc, system, code, def.getDisplay(), cs.getLanguage(), parent, def.getDesignation(), expParams, abs, inc, filters, noInactive, dep, vsProps, makeCSProps(def.getDefinition(), def.getProperty()), cs, null, def.getExtension(), null, exp, true);
if (np == null) {
np = t;
}
@ -579,7 +582,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
if (!existsInParams(params, p.getName(), p.getValue()))
params.add(p);
}
copyImportContains(expand.getContains(), null, expParams, filters, noInactive, vsProps, vsSrc, exp);
}
}
@ -707,17 +710,17 @@ public class ValueSetExpander extends ValueSetProcessBase {
if ("offset".equals(name) && value instanceof IntegerType) {
focus.getExpansion().getParameter().removeIf(p -> p.getName().equals(name));
focus.getExpansion().addParameter().setName(name).setValue(value);
dwc.setOffset(((IntegerType) value).getValue());
if (dwc.getOffset() < 0) {
dwc.setOffset(0);
dwc.setOffsetParam(((IntegerType) value).getValue());
if (dwc.getOffsetParam() < 0) {
dwc.setOffsetParam(0);
}
}
if ("count".equals(name)) {
focus.getExpansion().getParameter().removeIf(p -> p.getName().equals(name));
focus.getExpansion().addParameter().setName(name).setValue(value);
dwc.setCount(((IntegerType) value).getValue());
if (dwc.getCount() < 0) {
dwc.setCount(0);
dwc.setCountParam(((IntegerType) value).getValue());
if (dwc.getCountParam() < 0) {
dwc.setCountParam(0);
}
}
}
@ -757,7 +760,13 @@ public class ValueSetExpander extends ValueSetProcessBase {
// nothing - we intended to trap this here
}
if (dwc.isCanBeHeirarchy()) {
if (dwc.getTotal() > maxExpansionSize && dwc.getOffsetParam() + dwc.getCountParam() == 0) {
if (dwc.isNoTotal()) {
throw failCostly(context.formatMessage(I18nConstants.VALUESET_TOO_COSTLY, focus.getVersionedUrl(), ">" + MessageFormat.format("{0,number,#}", maxExpansionSize)));
} else {
throw failCostly(context.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_COUNT, focus.getVersionedUrl(), ">" + MessageFormat.format("{0,number,#}", maxExpansionSize), MessageFormat.format("{0,number,#}", dwc.getTotal())));
}
} else if (dwc.isCanBeHeirarchy() && (dwc.getCountParam() == 0) || dwc.getCountParam() > dwc.getCodes().size()) {
for (ValueSetExpansionContainsComponent c : dwc.getRoots()) {
focus.getExpansion().getContains().add(c);
}
@ -766,11 +775,11 @@ public class ValueSetExpander extends ValueSetProcessBase {
int cc = 0;
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()) {
if (dwc.getOffsetParam() == 0 || i >= dwc.getOffsetParam()) {
focus.getExpansion().getContains().add(c);
c.getContains().clear(); // make sure any heirarchy is wiped
cc++;
if (cc == dwc.getCount()) {
if (cc == dwc.getCountParam()) {
break;
}
}
@ -779,10 +788,10 @@ public class ValueSetExpander extends ValueSetProcessBase {
}
}
if (dwc.hasOffset()) {
focus.getExpansion().setOffset(dwc.getOffset());
if (dwc.hasOffsetParam()) {
focus.getExpansion().setOffset(dwc.getOffsetParam());
}
if (dwc.getTotal() >= 0) {
if (!dwc.isNoTotal()) {
focus.getExpansion().setTotal(dwc.getTotal());
}
if (!requiredSupplements.isEmpty()) {
@ -826,7 +835,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
// Exclude comes first because we build up a map of things to exclude
for (ConceptSetComponent inc : compose.getExclude())
excludeCodes(dwc, inc, expParams, exp, valueSet);
dwc.setCanBeHeirarchy(!expParams.getParameterBool("excludeNested") && dwc.getExcludeKeys().isEmpty() && dwc.getExcludeSystems().isEmpty() && dwc.getOffset()+dwc.getCount() == 0);
dwc.setCanBeHeirarchy(!expParams.getParameterBool("excludeNested") && dwc.getExcludeKeys().isEmpty() && dwc.getExcludeSystems().isEmpty() && dwc.getOffsetParam() == 0);
includeAbstract = !expParams.getParameterBool("excludeNotForUI");
boolean first = true;
for (ConceptSetComponent inc : compose.getInclude()) {
@ -878,7 +887,8 @@ public class ValueSetExpander extends ValueSetProcessBase {
if (!existsInParams(exp.getParameter(), "used-valueset", u))
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("used-valueset").setValue(u));
}
for (Extension ex : vso.getValueset().getExpansion().getExtension()) {
ValueSetExpansionComponent evs = vso.getValueset().getExpansion();
for (Extension ex : evs.getExtension()) {
if (ex.getUrl().equals(ToolingExtensions.EXT_EXP_TOOCOSTLY)) {
if (ex.getValue() instanceof BooleanType) {
exp.getExtension().add(new Extension(ToolingExtensions.EXT_EXP_TOOCOSTLY).setValue(new CanonicalType(value)));
@ -887,12 +897,17 @@ public class ValueSetExpander extends ValueSetProcessBase {
}
}
}
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
if (evs.hasTotal()) {
dwc.incTotal(evs.getTotal());
} else {
dwc.setNoTotal(true);
}
for (ValueSetExpansionParameterComponent p : evs.getParameter()) {
if (!existsInParams(exp.getParameter(), p.getName(), p.getValue()))
exp.getParameter().add(p);
}
if (isValueSetUnionImports(valueSet)) {
copyExpansion(wc, vso.getValueset().getExpansion().getContains());
copyExpansion(wc, evs.getContains());
}
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();
@ -976,7 +991,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
for (ValueSetExpansionContainsComponent c : list) {
c.checkNoModifiers("Imported Expansion in Code System", "expanding");
ValueSetExpansionContainsComponent np = addCode(dwc, c.getSystem(), c.getCode(), c.getDisplay(), vsSrc.getLanguage(), parent, null, expParams, c.getAbstract(), c.getInactive(),
filter, noInactive, false, vsProps, makeCSProps(c.getExtensionString(ToolingExtensions.EXT_DEFINITION), null), null, c.getProperty(), null, c.getExtension(), exp);
filter, noInactive, false, vsProps, makeCSProps(c.getExtensionString(ToolingExtensions.EXT_DEFINITION), null), null, c.getProperty(), null, c.getExtension(), exp, false);
copyImportContains(c.getContains(), np, expParams, filter, noInactive, vsProps, vsSrc, exp);
}
}
@ -1031,6 +1046,11 @@ public class ValueSetExpander extends ValueSetProcessBase {
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("used-valueset").setValue(u));
}
}
if (vs.getExpansion().hasTotal()) {
dwc.incTotal(vs.getExpansion().getTotal());
} else {
dwc.setNoTotal(true);
}
for (ValueSetExpansionParameterComponent p : vso.getValueset().getExpansion().getParameter()) {
if (!existsInParams(exp.getParameter(), p.getName(), p.getValue())) {
exp.getParameter().add(p);
@ -1044,7 +1064,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
}
}
for (ValueSetExpansionContainsComponent cc : vs.getExpansion().getContains()) {
addCodeAndDescendents(dwc, cc, null, expParams, imports, noInactive, vsProps, vs, exp);
addCodeAndDescendents(dwc, cc, null, expParams, imports, noInactive, vsProps, vs, exp, !vs.getExpansion().hasTotal());
}
}
@ -1109,7 +1129,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
inactive = CodeSystemUtilities.isInactive(cs, def);
isAbstract = CodeSystemUtilities.isNotSelectable(cs, def);
addCode(dwc, inc.getSystem(), c.getCode(), !Utilities.noString(c.getDisplay()) ? c.getDisplay() : def.getDisplay(), c.hasDisplay() ? vsSrc.getLanguage() : cs.getLanguage(), null, mergeDesignations(def, convertDesignations(c.getDesignation())),
expParams, isAbstract, inactive, imports, noInactive, false, exp.getProperty(), makeCSProps(def.getDefinition(), def.getProperty()), cs, null, def.getExtension(), c.getExtension(), exp);
expParams, isAbstract, inactive, imports, noInactive, false, exp.getProperty(), makeCSProps(def.getDefinition(), def.getProperty()), cs, null, def.getExtension(), c.getExtension(), exp, true);
}
}
}
@ -1193,7 +1213,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
excludeCode(wc, inc.getSystem(), code);
} else {
addCode(wc, inc.getSystem(), code, def.getDisplay(), cs.getLanguage(), null, def.getDesignation(), expParams, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
imports, noInactive, false, exp.getProperty(), makeCSProps(def.getDefinition(), def.getProperty()), cs, null, def.getExtension(), null, exp);
imports, noInactive, false, exp.getProperty(), makeCSProps(def.getDefinition(), def.getProperty()), cs, null, def.getExtension(), null, exp, true);
}
}
}

View File

@ -18,10 +18,10 @@ class WorkingContext {
private Set<String> excludeSystems = new HashSet<String>();
private boolean canBeHeirarchy = true;
private int offset;
private boolean offs;
private int count;
private int total;
private Integer offsetParam;
private Integer countParam; // allowed count. Because of internal processing, we allow more
private int total; // running count. This might be more than actually seen if we call out to an external server and only get the first 1000 codes
private boolean noTotal; // we lost count of the correct total
public List<ValueSetExpansionContainsComponent> getCodes() {
return codes;
@ -51,37 +51,48 @@ class WorkingContext {
this.canBeHeirarchy = canBeHeirarchy;
}
public int getOffset() {
return offset;
public boolean hasOffsetParam() {
return offsetParam != null;
}
public void setOffset(int offset) {
this.offs = true;
this.offset = offset;
public int getOffsetParam() {
return offsetParam == null ? 0 : offsetParam;
}
public boolean hasOffset() {
return offs;
public void setOffsetParam(int offsetParam) {
this.offsetParam = offsetParam;
}
public int getCount() {
return count;
public boolean hasCountParam() {
return countParam != null;
}
public void setCount(int count) {
this.count = count;
public int getCountParam() {
return countParam == null ? 0 : countParam;
}
public void setCountParam(int countParam) {
this.countParam = countParam;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public void incTotal() {
total++;
}
public void incTotal(int amount) {
total += amount;
}
public boolean isNoTotal() {
return noTotal;
}
public void setNoTotal(boolean noTotal) {
this.noTotal = noTotal;
}
}

View File

@ -878,6 +878,7 @@ public class I18nConstants {
public static final String UNKNOWN_CODESYSTEM = "UNKNOWN_CODESYSTEM";
public static final String UNKNOWN_CODESYSTEM_VERSION = "UNKNOWN_CODESYSTEM_VERSION";
public static final String VALUESET_TOO_COSTLY = "VALUESET_TOO_COSTLY";
public static final String VALUESET_TOO_COSTLY_COUNT = "VALUESET_TOO_COSTLY_COUNT";
public static final String VALUESET_TOO_COSTLY_TIME = "VALUESET_TOO_COSTLY_TIME";
public static final String NO_VALID_DISPLAY_FOUND = "NO_VALID_DISPLAY_FOUND";
public static final String SD_NO_CONTEXT_WHEN_NOT_EXTENSION = "SD_NO_CONTEXT_WHEN_NOT_EXTENSION";

View File

@ -933,8 +933,9 @@ SD_NO_TYPE_CODE_ON_CODE = Snapshot for {1} element {0} has type.code without a v
UNKNOWN_CODESYSTEM = A definition for CodeSystem ''{0}'' could not be found, so the code cannot be validated
UNKNOWN_CODESYSTEM_VERSION = A definition for CodeSystem ''{0}'' version ''{1}'' could not be found, so the code cannot be validated. Valid versions: {2}
UNABLE_TO_INFER_CODESYSTEM = The System URI could not be determined for the code {0} in the ValueSet {1}
VALUESET_TOO_COSTLY = The value set {0} has too many codes to display ({1})
VALUESET_TOO_COSTLY_TIME = The value set {0} took too long to process (>{1}sec)
VALUESET_TOO_COSTLY = The value set ''{0}'' expansion has too many codes to display ({1})
VALUESET_TOO_COSTLY_COUNT = The value set ''{0}'' expansion has {2} codes, which is too many to display ({1})
VALUESET_TOO_COSTLY_TIME = The value set ''{0}'' expansion took too long to process (>{1}sec)
NO_VALID_DISPLAY_FOUND_one = No valid Display Names found for {1}#{2} in the language {4}
NO_VALID_DISPLAY_FOUND_other = No valid Display Names found for {1}#{2} in the languages {4}
SD_NO_CONTEXT_WHEN_NOT_EXTENSION = The type is {0} so an extension context should not be specified

View File

@ -164,7 +164,7 @@ public class TerminologyServiceTests {
if (lang != null && !p.hasParameter("displayLanguage")) {
p.addParameter("displayLanguage", new CodeType(lang));
}
ValueSetExpansionOutcome vse = engine.getContext().expandVS(vs, false, hierarchical, false, p);
ValueSetExpansionOutcome vse = engine.getContext().expandVS(vs, false, hierarchical, false, p, true);
if (resp.contains("\"ValueSet\"")) {
if (vse.getValueset() == null) {
Assertions.fail(vse.getError());

View File

@ -20,7 +20,7 @@
<properties>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.4.25</validator_test_case_version>
<validator_test_case_version>1.4.26-SNAPSHOT</validator_test_case_version>
<jackson_version>2.16.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>