FHIR-25206 handle deprecated concepts properly when expanding value sets
This commit is contained in:
parent
fdb15b8951
commit
ae285401ae
|
@ -14,6 +14,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hamcrest.beans.HasProperty;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
|
@ -36,6 +37,7 @@ import org.hl7.fhir.r5.model.PrimitiveType;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.UriType;
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ConceptPropertyComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||||
|
@ -44,6 +46,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
|
@ -158,6 +161,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
boolean hasExtensions = false;
|
boolean hasExtensions = false;
|
||||||
List<String> langs = new ArrayList<String>();
|
List<String> langs = new ArrayList<String>();
|
||||||
Map<String, String> designations = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list
|
Map<String, String> designations = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list
|
||||||
|
Map<String, String> properties = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list
|
||||||
|
|
||||||
if (header) {
|
if (header) {
|
||||||
XhtmlNode h = x.addTag(getHeader());
|
XhtmlNode h = x.addTag(getHeader());
|
||||||
|
@ -198,40 +202,32 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean doSystem = true; // checkDoSystem(vs, src);
|
|
||||||
boolean doDefinition = checkDoDefinition(vs.getExpansion().getContains());
|
boolean doDefinition = checkDoDefinition(vs.getExpansion().getContains());
|
||||||
if (doSystem && allFromOneSystem(vs)) {
|
|
||||||
doSystem = false;
|
|
||||||
XhtmlNode p = x.para();
|
|
||||||
p.tx("All codes in this table are from the system ");
|
|
||||||
allCS = getContext().getWorker().fetchCodeSystem(vs.getExpansion().getContains().get(0).getSystem());
|
|
||||||
String ref = null;
|
|
||||||
if (allCS != null)
|
|
||||||
ref = getCsRef(allCS);
|
|
||||||
if (ref == null)
|
|
||||||
p.code(vs.getExpansion().getContains().get(0).getSystem());
|
|
||||||
else
|
|
||||||
p.ah(context.fixReference(ref)).code(vs.getExpansion().getContains().get(0).getSystem());
|
|
||||||
}
|
|
||||||
XhtmlNode t = x.table( "codes");
|
XhtmlNode t = x.table( "codes");
|
||||||
XhtmlNode tr = t.tr();
|
XhtmlNode tr = t.tr();
|
||||||
if (doLevel)
|
if (doLevel)
|
||||||
tr.td().b().tx("Level");
|
tr.td().b().tx("Level");
|
||||||
tr.td().attribute("style", "white-space:nowrap").b().tx("Code");
|
tr.td().attribute("style", "white-space:nowrap").b().tx("Code");
|
||||||
if (doSystem)
|
tr.td().b().tx("System");
|
||||||
tr.td().b().tx("System");
|
|
||||||
XhtmlNode tdDisp = tr.td();
|
XhtmlNode tdDisp = tr.td();
|
||||||
tdDisp.b().tx("Display");
|
tdDisp.b().tx("Display");
|
||||||
boolean doDesignations = false;
|
boolean doDesignations = false;
|
||||||
for (ValueSetExpansionContainsComponent c : vs.getExpansion().getContains()) {
|
for (ValueSetExpansionContainsComponent c : vs.getExpansion().getContains()) {
|
||||||
scanForDesignations(c, langs, designations);
|
scanForDesignations(c, langs, designations);
|
||||||
}
|
}
|
||||||
|
scanForProperties(vs.getExpansion(), langs, properties);
|
||||||
if (doDefinition) {
|
if (doDefinition) {
|
||||||
tr.td().b().tx("Definition");
|
tr.td().b().tx("Definition");
|
||||||
doDesignations = false;
|
doDesignations = false;
|
||||||
|
for (String n : Utilities.sorted(properties.keySet())) {
|
||||||
|
tr.td().b().ah(properties.get(n)).addText(n);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
for (String n : Utilities.sorted(properties.keySet())) {
|
||||||
|
tr.td().b().ah(properties.get(n)).addText(n);
|
||||||
|
}
|
||||||
// if we're not doing definitions and we don't have too many languages, we'll do them in line
|
// if we're not doing definitions and we don't have too many languages, we'll do them in line
|
||||||
doDesignations = langs.size() + designations.size() < MAX_DESIGNATIONS_IN_LINE;
|
doDesignations = langs.size() + properties.size() + designations.size() < MAX_DESIGNATIONS_IN_LINE;
|
||||||
|
|
||||||
if (doDesignations) {
|
if (doDesignations) {
|
||||||
if (vs.hasLanguage()) {
|
if (vs.hasLanguage()) {
|
||||||
|
@ -249,7 +245,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
addMapHeaders(tr, maps);
|
addMapHeaders(tr, maps);
|
||||||
for (ValueSetExpansionContainsComponent c : vs.getExpansion().getContains()) {
|
for (ValueSetExpansionContainsComponent c : vs.getExpansion().getContains()) {
|
||||||
addExpansionRowToTable(t, c, 1, doLevel, doSystem, doDefinition, maps, allCS, langs, designations, doDesignations);
|
addExpansionRowToTable(t, c, 1, doLevel, true, doDefinition, maps, allCS, langs, designations, doDesignations, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
// now, build observed languages
|
// now, build observed languages
|
||||||
|
@ -280,6 +276,30 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
return hasExtensions;
|
return hasExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void scanForProperties(ValueSetExpansionComponent exp, List<String> langs, Map<String, String> properties) {
|
||||||
|
properties.clear();
|
||||||
|
for (ValueSetExpansionPropertyComponent pp : exp.getProperty()) {
|
||||||
|
if (pp.hasCode() && pp.hasUri() && anyActualproperties(exp.getContains(), pp.getCode())) {
|
||||||
|
properties.put(pp.getCode(), pp.getUri());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean anyActualproperties(List<ValueSetExpansionContainsComponent> contains, String pp) {
|
||||||
|
for (ValueSetExpansionContainsComponent c : contains) {
|
||||||
|
for (ConceptPropertyComponent cp : c.getProperty()) {
|
||||||
|
if (pp.equals(cp.getCode())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (anyActualproperties(c.getContains(), pp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void generateContentModeNotices(XhtmlNode x, ValueSetExpansionComponent expansion) {
|
private void generateContentModeNotices(XhtmlNode x, ValueSetExpansionComponent expansion) {
|
||||||
generateContentModeNotice(x, expansion, "example", "Expansion based on example code system");
|
generateContentModeNotice(x, expansion, "example", "Expansion based on example code system");
|
||||||
generateContentModeNotice(x, expansion, "fragment", "Expansion based on code system fragment");
|
generateContentModeNotice(x, expansion, "fragment", "Expansion based on code system fragment");
|
||||||
|
@ -715,7 +735,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addExpansionRowToTable(XhtmlNode t, ValueSetExpansionContainsComponent c, int i, boolean doLevel, boolean doSystem, boolean doDefinition, List<UsedConceptMap> maps, CodeSystem allCS, List<String> langs, Map<String, String> designations, boolean doDesignations) {
|
private void addExpansionRowToTable(XhtmlNode t, ValueSetExpansionContainsComponent c, int i, boolean doLevel, boolean doSystem, boolean doDefinition, List<UsedConceptMap> maps, CodeSystem allCS, List<String> langs, Map<String, String> designations, boolean doDesignations, Map<String, String> properties) {
|
||||||
XhtmlNode tr = t.tr();
|
XhtmlNode tr = t.tr();
|
||||||
XhtmlNode td = tr.td();
|
XhtmlNode td = tr.td();
|
||||||
|
|
||||||
|
@ -745,6 +765,13 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
if (cs != null)
|
if (cs != null)
|
||||||
td.addText(CodeSystemUtilities.getCodeDefinition(cs, c.getCode()));
|
td.addText(CodeSystemUtilities.getCodeDefinition(cs, c.getCode()));
|
||||||
}
|
}
|
||||||
|
for (String n : Utilities.sorted(properties.keySet())) {
|
||||||
|
td = tr.td();
|
||||||
|
String ps = getPropertyValue(c, n);
|
||||||
|
if (!Utilities.noString(ps)) {
|
||||||
|
td.addText(ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (UsedConceptMap m : maps) {
|
for (UsedConceptMap m : maps) {
|
||||||
td = tr.td();
|
td = tr.td();
|
||||||
List<TargetElementComponentWrapper> mappings = findMappingsForCode(c.getCode(), m.getMap());
|
List<TargetElementComponentWrapper> mappings = findMappingsForCode(c.getCode(), m.getMap());
|
||||||
|
@ -765,7 +792,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
addLangaugesToRow(c, langs, tr);
|
addLangaugesToRow(c, langs, tr);
|
||||||
}
|
}
|
||||||
for (ValueSetExpansionContainsComponent cc : c.getContains()) {
|
for (ValueSetExpansionContainsComponent cc : c.getContains()) {
|
||||||
addExpansionRowToTable(t, cc, i+1, doLevel, doSystem, doDefinition, maps, allCS, langs, designations, doDesignations);
|
addExpansionRowToTable(t, cc, i+1, doLevel, doSystem, doDefinition, maps, allCS, langs, designations, doDesignations, properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,6 +800,15 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String getPropertyValue(ValueSetExpansionContainsComponent c, String n) {
|
||||||
|
for (ConceptPropertyComponent cp : c.getProperty()) {
|
||||||
|
if (n.equals(cp.getCode())) {
|
||||||
|
return cp.getValue().primitiveValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkSystemMatches(String system, ValueSetExpansionContainsComponent cc) {
|
private boolean checkSystemMatches(String system, ValueSetExpansionContainsComponent cc) {
|
||||||
if (!system.equals(cc.getSystem()))
|
if (!system.equals(cc.getSystem()))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -241,12 +241,34 @@ public class CodeSystemUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isInactive(CodeSystem cs, ConceptDefinitionComponent def, boolean ignoreStatus) {
|
||||||
|
try {
|
||||||
|
for (ConceptPropertyComponent p : def.getProperty()) {
|
||||||
|
if (!ignoreStatus) {
|
||||||
|
if ("status".equals(p.getCode()) && p.hasValue() && p.hasValueCodeType() && "inactive".equals(p.getValueCodeType().getCode()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// legacy
|
||||||
|
if ("inactive".equals(p.getCode()) && p.hasValue() && p.getValue() instanceof BooleanType)
|
||||||
|
return ((BooleanType) p.getValue()).getValue();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (FHIRException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void setDeprecated(CodeSystem cs, ConceptDefinitionComponent concept, DateTimeType date) throws FHIRFormatError {
|
public static void setDeprecated(CodeSystem cs, ConceptDefinitionComponent concept, DateTimeType date) throws FHIRFormatError {
|
||||||
setStatus(cs, concept, ConceptStatus.Deprecated);
|
setStatus(cs, concept, ConceptStatus.Deprecated);
|
||||||
defineDeprecatedProperty(cs);
|
defineDeprecatedProperty(cs);
|
||||||
concept.addProperty().setCode("deprecationDate").setValue(date);
|
concept.addProperty().setCode("deprecationDate").setValue(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void setDeprecated(CodeSystem cs, ConceptDefinitionComponent concept) throws FHIRFormatError {
|
||||||
|
setStatus(cs, concept, ConceptStatus.Deprecated);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isInactive(CodeSystem cs, ConceptDefinitionComponent def) throws FHIRException {
|
public static boolean isInactive(CodeSystem cs, ConceptDefinitionComponent def) throws FHIRException {
|
||||||
for (ConceptPropertyComponent p : def.getProperty()) {
|
for (ConceptPropertyComponent p : def.getProperty()) {
|
||||||
if ("status".equals(p.getCode()) && p.hasValueStringType())
|
if ("status".equals(p.getCode()) && p.hasValueStringType())
|
||||||
|
|
|
@ -108,6 +108,7 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetComposeComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
|
||||||
|
@ -207,7 +208,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
|
private ValueSetExpansionContainsComponent addCode(String system, String code, String display, ValueSetExpansionContainsComponent parent, List<ConceptDefinitionDesignationComponent> designations, Parameters expParams,
|
||||||
boolean isAbstract, boolean inactive, List<ValueSet> filters, boolean noInactive) {
|
boolean isAbstract, boolean inactive, List<ValueSet> filters, boolean noInactive, boolean deprecated, List<ValueSetExpansionPropertyComponent> vsProp) {
|
||||||
|
|
||||||
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code))
|
if (filters != null && !filters.isEmpty() && !filterContainsCode(filters, system, code))
|
||||||
return null;
|
return null;
|
||||||
|
@ -222,6 +223,9 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
n.setAbstract(true);
|
n.setAbstract(true);
|
||||||
if (inactive)
|
if (inactive)
|
||||||
n.setInactive(true);
|
n.setInactive(true);
|
||||||
|
if (deprecated) {
|
||||||
|
ValueSetUtilities.setDeprecated(vsProp, n);
|
||||||
|
}
|
||||||
|
|
||||||
if (expParams.getParameterBool("includeDesignations") && designations != null) {
|
if (expParams.getParameterBool("includeDesignations") && designations != null) {
|
||||||
for (ConceptDefinitionDesignationComponent t : designations) {
|
for (ConceptDefinitionDesignationComponent t : designations) {
|
||||||
|
@ -285,12 +289,12 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodeAndDescendents(ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive) throws FHIRException {
|
private void addCodeAndDescendents(ValueSetExpansionContainsComponent focus, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps) throws FHIRException {
|
||||||
focus.checkNoModifiers("Expansion.contains", "expanding");
|
focus.checkNoModifiers("Expansion.contains", "expanding");
|
||||||
ValueSetExpansionContainsComponent np = addCode(focus.getSystem(), focus.getCode(), focus.getDisplay(), parent,
|
ValueSetExpansionContainsComponent np = addCode(focus.getSystem(), focus.getCode(), focus.getDisplay(), parent,
|
||||||
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), filters, noInactive);
|
convert(focus.getDesignation()), expParams, focus.getAbstract(), focus.getInactive(), filters, noInactive, false, vsProps);
|
||||||
for (ValueSetExpansionContainsComponent c : focus.getContains())
|
for (ValueSetExpansionContainsComponent c : focus.getContains())
|
||||||
addCodeAndDescendents(focus, np, expParams, filters, noInactive);
|
addCodeAndDescendents(focus, np, expParams, filters, noInactive, vsProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ConceptDefinitionDesignationComponent> convert(List<ConceptReferenceDesignationComponent> designations) {
|
private List<ConceptDefinitionDesignationComponent> convert(List<ConceptReferenceDesignationComponent> designations) {
|
||||||
|
@ -305,41 +309,31 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodeAndDescendents(CodeSystem cs, String system, ConceptDefinitionComponent def, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filters, ConceptDefinitionComponent exclusion, IConceptFilter filterFunc, boolean noInactive) throws FHIRException {
|
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 {
|
||||||
def.checkNoModifiers("Code in Code System", "expanding");
|
def.checkNoModifiers("Code in Code System", "expanding");
|
||||||
if (exclusion != null) {
|
if (exclusion != null) {
|
||||||
if (exclusion.getCode().equals(def.getCode()))
|
if (exclusion.getCode().equals(def.getCode()))
|
||||||
return; // excluded.
|
return; // excluded.
|
||||||
}
|
}
|
||||||
if (!CodeSystemUtilities.isDeprecated(cs, def, false)) {
|
ValueSetExpansionContainsComponent np = null;
|
||||||
ValueSetExpansionContainsComponent np = null;
|
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
|
||||||
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
|
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
||||||
boolean inc = CodeSystemUtilities.isInactive(cs, def);
|
boolean dep = CodeSystemUtilities.isDeprecated(cs, def, false);
|
||||||
if ((includeAbstract || !abs) && filterFunc.includeConcept(cs, def)) {
|
if ((includeAbstract || !abs) && filterFunc.includeConcept(cs, def)) {
|
||||||
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), expParams, abs, inc, filters, noInactive);
|
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), expParams, abs, inc, filters, noInactive, dep, vsProps);
|
||||||
}
|
}
|
||||||
for (ConceptDefinitionComponent c : def.getConcept()) {
|
for (ConceptDefinitionComponent c : def.getConcept()) {
|
||||||
addCodeAndDescendents(cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive);
|
addCodeAndDescendents(cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps);
|
||||||
}
|
}
|
||||||
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||||
for (ConceptDefinitionComponent c : children)
|
for (ConceptDefinitionComponent c : children)
|
||||||
addCodeAndDescendents(cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive);
|
addCodeAndDescendents(cs, system, c, np, expParams, filters, exclusion, filterFunc, noInactive, vsProps);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (ConceptDefinitionComponent c : def.getConcept()) {
|
|
||||||
addCodeAndDescendents(cs, system, c, null, expParams, filters, exclusion, filterFunc, noInactive);
|
|
||||||
}
|
|
||||||
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, null, expParams, filters, exclusion, filterFunc, noInactive);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, Parameters expParams, List<ValueSet> filters, boolean noInactive) throws ETooCostly, FHIRException {
|
private void addCodes(ValueSetExpansionComponent expand, List<ValueSetExpansionParameterComponent> params, Parameters expParams, List<ValueSet> filters, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps) throws ETooCostly, FHIRException {
|
||||||
if (expand != null) {
|
if (expand != null) {
|
||||||
if (expand.getContains().size() > maxExpansionSize)
|
if (expand.getContains().size() > maxExpansionSize)
|
||||||
throw failCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
throw failCostly("Too many codes to display (>" + Integer.toString(expand.getContains().size()) + ")");
|
||||||
|
@ -348,7 +342,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
params.add(p);
|
params.add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
copyImportContains(expand.getContains(), null, expParams, filters, noInactive);
|
copyImportContains(expand.getContains(), null, expParams, filters, noInactive, vsProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,11 +572,11 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filter, boolean noInactive) throws FHIRException {
|
private void copyImportContains(List<ValueSetExpansionContainsComponent> list, ValueSetExpansionContainsComponent parent, Parameters expParams, List<ValueSet> filter, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps) throws FHIRException {
|
||||||
for (ValueSetExpansionContainsComponent c : list) {
|
for (ValueSetExpansionContainsComponent c : list) {
|
||||||
c.checkNoModifiers("Imported Expansion in Code System", "expanding");
|
c.checkNoModifiers("Imported Expansion in Code System", "expanding");
|
||||||
ValueSetExpansionContainsComponent np = addCode(c.getSystem(), c.getCode(), c.getDisplay(), parent, null, expParams, c.getAbstract(), c.getInactive(), filter, noInactive);
|
ValueSetExpansionContainsComponent np = addCode(c.getSystem(), c.getCode(), c.getDisplay(), parent, null, expParams, c.getAbstract(), c.getInactive(), filter, noInactive, false, vsProps);
|
||||||
copyImportContains(c.getContains(), np, expParams, filter, noInactive);
|
copyImportContains(c.getContains(), np, expParams, filter, noInactive, vsProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,18 +593,18 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
ValueSet base = imports.get(0);
|
ValueSet base = imports.get(0);
|
||||||
imports.remove(0);
|
imports.remove(0);
|
||||||
base.checkNoModifiers("Imported ValueSet", "expanding");
|
base.checkNoModifiers("Imported ValueSet", "expanding");
|
||||||
copyImportContains(base.getExpansion().getContains(), null, expParams, imports, noInactive);
|
copyImportContains(base.getExpansion().getContains(), null, expParams, imports, noInactive, base.getExpansion().getProperty());
|
||||||
} else {
|
} else {
|
||||||
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
|
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
|
||||||
if (isServerSide(inc.getSystem()) || (cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT))) {
|
if (isServerSide(inc.getSystem()) || (cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT))) {
|
||||||
doServerIncludeCodes(inc, heirarchical, exp, imports, expParams, extensions, noInactive);
|
doServerIncludeCodes(inc, heirarchical, exp, imports, expParams, extensions, noInactive, valueSet.getExpansion().getProperty());
|
||||||
} else {
|
} else {
|
||||||
doInternalIncludeCodes(inc, exp, expParams, imports, cs, noInactive);
|
doInternalIncludeCodes(inc, exp, expParams, imports, cs, noInactive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doServerIncludeCodes(ConceptSetComponent inc, boolean heirarchical, ValueSetExpansionComponent exp, List<ValueSet> imports, Parameters expParams, List<Extension> extensions, boolean noInactive) throws FHIRException {
|
private void doServerIncludeCodes(ConceptSetComponent inc, boolean heirarchical, ValueSetExpansionComponent exp, List<ValueSet> imports, Parameters expParams, List<Extension> extensions, boolean noInactive, List<ValueSetExpansionPropertyComponent> vsProps) throws FHIRException {
|
||||||
ValueSetExpansionOutcome vso = context.expandVS(inc, heirarchical, noInactive);
|
ValueSetExpansionOutcome vso = context.expandVS(inc, heirarchical, noInactive);
|
||||||
if (vso.getError() != null) {
|
if (vso.getError() != null) {
|
||||||
throw failTSE("Unable to expand imported value set: " + vso.getError());
|
throw failTSE("Unable to expand imported value set: " + vso.getError());
|
||||||
|
@ -634,7 +628,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ValueSetExpansionContainsComponent cc : vs.getExpansion().getContains()) {
|
for (ValueSetExpansionContainsComponent cc : vs.getExpansion().getContains()) {
|
||||||
addCodeAndDescendents(cc, null, expParams, imports, noInactive);
|
addCodeAndDescendents(cc, null, expParams, imports, noInactive, vsProps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +658,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
if (inc.getConcept().size() == 0 && inc.getFilter().size() == 0) {
|
||||||
// special case - add all the code system
|
// special case - add all the code system
|
||||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(), noInactive);
|
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||||
}
|
}
|
||||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||||
addFragmentWarning(exp, cs);
|
addFragmentWarning(exp, cs);
|
||||||
|
@ -693,7 +687,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
} else {
|
} else {
|
||||||
inactive = CodeSystemUtilities.isInactive(cs, def);
|
inactive = CodeSystemUtilities.isInactive(cs, def);
|
||||||
}
|
}
|
||||||
addCode(inc.getSystem(), c.getCode(), !Utilities.noString(c.getDisplay()) ? c.getDisplay() : def == null ? null : def.getDisplay(), null, convertDesignations(c.getDesignation()), expParams, false, inactive, imports, noInactive);
|
addCode(inc.getSystem(), c.getCode(), !Utilities.noString(c.getDisplay()) ? c.getDisplay() : def == null ? null : def.getDisplay(), null, convertDesignations(c.getDesignation()), expParams, false, inactive, imports, noInactive, false, exp.getProperty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inc.getFilter().size() > 1) {
|
if (inc.getFilter().size() > 1) {
|
||||||
|
@ -710,14 +704,14 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||||
if (def == null)
|
if (def == null)
|
||||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(), noInactive);
|
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISNOTA) {
|
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISNOTA) {
|
||||||
// special: all codes in the target code system that are not under the value
|
// special: all codes in the target code system that are not under the value
|
||||||
ConceptDefinitionComponent defEx = getConceptForCode(cs.getConcept(), fc.getValue());
|
ConceptDefinitionComponent defEx = getConceptForCode(cs.getConcept(), fc.getValue());
|
||||||
if (defEx == null)
|
if (defEx == null)
|
||||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, defEx, new AllConceptsFilter(), noInactive);
|
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, defEx, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||||
}
|
}
|
||||||
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
} else if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.DESCENDENTOF) {
|
||||||
// special: all codes in the target code system under the value
|
// special: all codes in the target code system under the value
|
||||||
|
@ -725,11 +719,11 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
if (def == null)
|
if (def == null)
|
||||||
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
throw failTSE("Code '" + fc.getValue() + "' not found in system '" + inc.getSystem() + "'");
|
||||||
for (ConceptDefinitionComponent c : def.getConcept())
|
for (ConceptDefinitionComponent c : def.getConcept())
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(), noInactive);
|
addCodeAndDescendents(cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||||
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
if (def.hasUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK)) {
|
||||||
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
List<ConceptDefinitionComponent> children = (List<ConceptDefinitionComponent>) def.getUserData(CodeSystemUtilities.USER_DATA_CROSS_LINK);
|
||||||
for (ConceptDefinitionComponent c : children)
|
for (ConceptDefinitionComponent c : children)
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(), noInactive);
|
addCodeAndDescendents(cs, inc.getSystem(), c, null, expParams, imports, null, new AllConceptsFilter(), noInactive, exp.getProperty());
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
|
||||||
|
@ -740,13 +734,13 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
|
||||||
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {
|
||||||
if (def.getDisplay().contains(fc.getValue())) {
|
if (def.getDisplay().contains(fc.getValue())) {
|
||||||
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), null, def.getDesignation(), expParams, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
addCode(inc.getSystem(), def.getCode(), def.getDisplay(), null, def.getDesignation(), expParams, CodeSystemUtilities.isNotSelectable(cs, def), CodeSystemUtilities.isInactive(cs, def),
|
||||||
imports, noInactive);
|
imports, noInactive, false, exp.getProperty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isDefinedProperty(cs, fc.getProperty())) {
|
} else if (isDefinedProperty(cs, fc.getProperty())) {
|
||||||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new PropertyFilter(fc, getPropertyDefinition(cs, fc.getProperty())), noInactive);
|
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null, new PropertyFilter(fc, getPropertyDefinition(cs, fc.getProperty())), noInactive, exp.getProperty());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw fail("Search by property[" + fc.getProperty() + "] and op[" + fc.getOp() + "] is not supported yet");
|
throw fail("Search by property[" + fc.getProperty() + "] and op[" + fc.getOp() + "] is not supported yet");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.hl7.fhir.r5.terminologies;
|
package org.hl7.fhir.r5.terminologies;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2011+, HL7, Inc.
|
Copyright (c) 2011+, HL7, Inc.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
@ -31,16 +33,24 @@ package org.hl7.fhir.r5.terminologies;
|
||||||
|
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
|
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.model.BooleanType;
|
||||||
import org.hl7.fhir.r5.model.CanonicalType;
|
import org.hl7.fhir.r5.model.CanonicalType;
|
||||||
import org.hl7.fhir.r5.model.CodeSystem;
|
import org.hl7.fhir.r5.model.CodeSystem;
|
||||||
|
import org.hl7.fhir.r5.model.DateTimeType;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
|
||||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||||
import org.hl7.fhir.r5.model.Identifier;
|
import org.hl7.fhir.r5.model.Identifier;
|
||||||
import org.hl7.fhir.r5.model.Meta;
|
import org.hl7.fhir.r5.model.Meta;
|
||||||
import org.hl7.fhir.r5.model.UriType;
|
import org.hl7.fhir.r5.model.UriType;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
|
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||||
|
import org.hl7.fhir.r5.model.CodeType;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||||
|
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
|
||||||
|
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.ConceptStatus;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.utilities.StandardsStatus;
|
import org.hl7.fhir.utilities.StandardsStatus;
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
|
@ -234,4 +244,15 @@ public class ValueSetUtilities {
|
||||||
return vs;
|
return vs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setDeprecated(List<ValueSetExpansionPropertyComponent> vsProp, ValueSetExpansionContainsComponent n) {
|
||||||
|
n.addProperty().setCode("status").setValue(new CodeType("deprecated"));
|
||||||
|
for (ValueSetExpansionPropertyComponent o : vsProp) {
|
||||||
|
if ("status".equals(o.getCode())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vsProp.add(new ValueSetExpansionPropertyComponent().setCode("status").setUri("http://hl7.org/fhir/concept-properties#status"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue