Allow expansions on code system fragments, with warnings when appropriate
This commit is contained in:
parent
979bad6af1
commit
82d80caec5
|
@ -569,7 +569,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
|
||||
|
||||
private boolean hasTooCostlyExpansion(ValueSet valueset) {
|
||||
return valueset != null && valueset.hasExpansion() && ToolingExtensions.hasExtension(valueset.getExpansion(), "http://hl7.org/fhir/StructureDefinition/valueset-toocostly");
|
||||
return valueset != null && valueset.hasExpansion() && ToolingExtensions.hasExtension(valueset.getExpansion(), ToolingExtensions.EXT_EXP_TOOCOSTLY);
|
||||
}
|
||||
// --- validate code -------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -289,7 +289,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;
|
||||
|
|
|
@ -349,19 +349,6 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
return res;
|
||||
}
|
||||
|
||||
private void addToHeirarchy(List<ValueSetExpansionContainsComponent> target, List<ValueSetExpansionContainsComponent> source) {
|
||||
for (ValueSetExpansionContainsComponent s : source) {
|
||||
target.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
|
||||
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
|
||||
if (def == null)
|
||||
throw new TerminologyServiceException("Unable to find code '" + code + "' in code system " + cs.getUrl());
|
||||
return def.getDisplay();
|
||||
}
|
||||
|
||||
private ConceptDefinitionComponent getConceptForCode(List<ConceptDefinitionComponent> clist, String code) {
|
||||
for (ConceptDefinitionComponent c : clist) {
|
||||
if (code.equals(c.getCode()))
|
||||
|
@ -404,9 +391,9 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
if (!existsInParams(exp.getParameter(), "version", new UriType(vs.getUrl() + "|" + vs.getVersion())))
|
||||
exp.getParameter().add(new ValueSetExpansionParameterComponent().setName("version").setValue(new UriType(vs.getUrl() + "|" + vs.getVersion())));
|
||||
for (Extension ex : vso.getValueset().getExpansion().getExtension()) {
|
||||
if (ex.getUrl().equals("http://hl7.org/fhir/StructureDefinition/valueset-toocostly")) {
|
||||
if (ex.getUrl().equals(ToolingExtensions.EXT_EXP_TOOCOSTLY)) {
|
||||
if (ex.getValue() instanceof BooleanType) {
|
||||
exp.getExtension().add(new Extension("http://hl7.org/fhir/StructureDefinition/valueset-toocostly").setValue(new UriType(value)));
|
||||
exp.getExtension().add(new Extension(ToolingExtensions.EXT_EXP_TOOCOSTLY).setValue(new UriType(value)));
|
||||
} else {
|
||||
exp.getExtension().add(ex);
|
||||
}
|
||||
|
@ -444,7 +431,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
copyImportContains(base.getExpansion().getContains(), null, expParams, imports);
|
||||
} else {
|
||||
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
|
||||
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE)) {
|
||||
if ((cs == null || (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT))) {
|
||||
doServerIncludeCodes(inc, heirarchical, exp, imports, expParams, extensions);
|
||||
} else {
|
||||
doInternalIncludeCodes(inc, exp, expParams, imports, cs);
|
||||
|
@ -469,7 +456,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
}
|
||||
}
|
||||
for (Extension ex : vs.getExpansion().getExtension()) {
|
||||
if (Utilities.existsInList(ex.getUrl(), "http://hl7.org/fhir/StructureDefinition/valueset-toocostly", "http://hl7.org/fhir/StructureDefinition/valueset-unclosed")) {
|
||||
if (Utilities.existsInList(ex.getUrl(), ToolingExtensions.EXT_EXP_TOOCOSTLY, "http://hl7.org/fhir/StructureDefinition/valueset-unclosed")) {
|
||||
if (!hasExtension(extensions, ex.getUrl())) {
|
||||
extensions.add(ex);
|
||||
}
|
||||
|
@ -489,16 +476,15 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void doInternalIncludeCodes(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, List<ValueSet> imports,
|
||||
CodeSystem cs) throws NoTerminologyServiceException, TerminologyServiceException, FHIRException {
|
||||
public void doInternalIncludeCodes(ConceptSetComponent inc, ValueSetExpansionComponent exp, Parameters expParams, List<ValueSet> imports, CodeSystem cs) throws NoTerminologyServiceException, TerminologyServiceException, FHIRException {
|
||||
if (cs == null) {
|
||||
if (context.isNoTerminologyServer())
|
||||
throw new NoTerminologyServiceException("unable to find code system " + inc.getSystem().toString());
|
||||
throw new NoTerminologyServiceException("Unable to find code system " + inc.getSystem().toString());
|
||||
else
|
||||
throw new TerminologyServiceException("unable to find code system " + inc.getSystem().toString());
|
||||
throw new TerminologyServiceException("Unable to find code system " + inc.getSystem().toString());
|
||||
}
|
||||
cs.checkNoModifiers("Code System", "expanding");
|
||||
if (cs.getContent() != CodeSystemContentMode.COMPLETE)
|
||||
if (cs.getContent() != CodeSystemContentMode.COMPLETE && cs.getContent() != CodeSystemContentMode.FRAGMENT)
|
||||
throw new TerminologyServiceException("Code system " + inc.getSystem().toString() + " is incomplete");
|
||||
if (cs.hasVersion())
|
||||
if (!existsInParams(exp.getParameter(), "version", new UriType(cs.getUrl() + "|" + cs.getVersion())))
|
||||
|
@ -509,14 +495,27 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
for (ConceptDefinitionComponent def : cs.getConcept()) {
|
||||
addCodeAndDescendents(cs, inc.getSystem(), def, null, expParams, imports, null);
|
||||
}
|
||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||
addFragmentWarning(exp, cs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!inc.getConcept().isEmpty()) {
|
||||
canBeHeirarchy = false;
|
||||
for (ConceptReferenceComponent c : inc.getConcept()) {
|
||||
c.checkNoModifiers("Code in Code System", "expanding");
|
||||
addCode(inc.getSystem(), c.getCode(), Utilities.noString(c.getDisplay()) ? getCodeDisplay(cs, c.getCode()) : c.getDisplay(), null, convertDesignations(c.getDesignation()), expParams, false,
|
||||
CodeSystemUtilities.isInactive(cs, c.getCode()), imports);
|
||||
ConceptDefinitionComponent def = CodeSystemUtilities.findCode(cs.getConcept(), c.getCode());
|
||||
Boolean inactive = false; // default is true if we're a fragment and
|
||||
if (def == null) {
|
||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||
addFragmentWarning(exp, cs);
|
||||
} else {
|
||||
throw new TerminologyServiceException("Unable to find code '" + c.getCode() + "' in code system " + cs.getUrl());
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (inc.getFilter().size() > 1) {
|
||||
|
@ -524,6 +523,9 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
throw new TerminologyServiceException("Multiple filters not handled yet"); // need to and them, and this isn't done yet. But this shouldn't arise in non loinc and snomed value sets
|
||||
}
|
||||
if (inc.getFilter().size() == 1) {
|
||||
if (cs.getContent() == CodeSystemContentMode.FRAGMENT) {
|
||||
addFragmentWarning(exp, cs);
|
||||
}
|
||||
ConceptSetFilterComponent fc = inc.getFilter().get(0);
|
||||
if ("concept".equals(fc.getProperty()) && fc.getOp() == FilterOperator.ISA) {
|
||||
// special: all codes in the target code system under the value
|
||||
|
@ -563,6 +565,15 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
|
|||
}
|
||||
}
|
||||
|
||||
private void addFragmentWarning(ValueSetExpansionComponent exp, CodeSystem cs) {
|
||||
for (Extension ex : cs.getExtensionsByUrl(ToolingExtensions.EXT_EXP_FRAGMENT)) {
|
||||
if (ex.getValue().primitiveValue().equals(cs.getUrl())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
exp.addExtension(new Extension(ToolingExtensions.EXT_EXP_FRAGMENT).setValue(new UriType(cs.getUrl())));
|
||||
}
|
||||
|
||||
private List<ConceptDefinitionDesignationComponent> convertDesignations(List<ConceptReferenceDesignationComponent> list) {
|
||||
List<ConceptDefinitionDesignationComponent> res = new ArrayList<CodeSystem.ConceptDefinitionDesignationComponent>();
|
||||
for (ConceptReferenceDesignationComponent t : list) {
|
||||
|
|
|
@ -3276,8 +3276,8 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
if (vs.hasCopyright())
|
||||
generateCopyright(x, vs);
|
||||
}
|
||||
if (ToolingExtensions.hasExtension(vs.getExpansion(), "http://hl7.org/fhir/StructureDefinition/valueset-toocostly")) {
|
||||
List<Extension> exl = vs.getExpansion().getExtensionsByUrl("http://hl7.org/fhir/StructureDefinition/valueset-toocostly");
|
||||
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) {
|
||||
|
@ -3294,6 +3294,22 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
else
|
||||
x.para().tx("This value set contains "+count.toString()+" concepts");
|
||||
}
|
||||
if (ToolingExtensions.hasExtension(vs.getExpansion(), ToolingExtensions.EXT_EXP_FRAGMENT)) {
|
||||
XhtmlNode div = x.div().style("border: maroon 1px solid; background-color: #FFCCCC; padding: 8px");
|
||||
List<Extension> exl = vs.getExpansion().getExtensionsByUrl(ToolingExtensions.EXT_EXP_FRAGMENT);
|
||||
if (exl.size() > 1) {
|
||||
div.para().addText("Warning: this expansion is generated from fragments of the following code systems, and may be missing codes, or include codes that are not valid:");
|
||||
XhtmlNode ul = div.ul();
|
||||
for (Extension ex : exl) {
|
||||
addCSRef(ul.li(), ex.getValue().primitiveValue());
|
||||
}
|
||||
} else {
|
||||
XhtmlNode p = div.para();
|
||||
p.addText("Warning: this expansion is generated from a fragment of the code system ");
|
||||
addCSRef(p, exl.get(0).getValue().primitiveValue());
|
||||
p.addText(" and may be missing codes, or include codes that are not valid");
|
||||
}
|
||||
}
|
||||
|
||||
generateVersionNotice(x, vs.getExpansion());
|
||||
|
||||
|
@ -3355,6 +3371,18 @@ public class NarrativeGenerator implements INarrativeGenerator {
|
|||
return hasExtensions;
|
||||
}
|
||||
|
||||
private void addCSRef(XhtmlNode x, String url) {
|
||||
CodeSystem cs = context.fetchCodeSystem(url);
|
||||
if (cs == null) {
|
||||
x.code(url);
|
||||
} else if (cs.hasUserData("path")) {
|
||||
x.ah(cs.getUserString("path")).tx(cs.present());
|
||||
} else {
|
||||
x.code(url);
|
||||
x.tx(" ("+cs.present()+")");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion) {
|
||||
Map<String, String> versions = new HashMap<String, String>();
|
||||
|
|
|
@ -166,6 +166,8 @@ public class ToolingExtensions {
|
|||
public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type";
|
||||
public static final String EXT_RENDERED_VALUE = "http://hl7.org/fhir/StructureDefinition/rendered-value";
|
||||
public static final String EXT_OLD_CONCEPTMAP_EQUIVALENCE = "http://hl7.org/fhir/1.0/StructureDefinition/extension-ConceptMap.element.target.equivalence";
|
||||
public static final String EXT_EXP_FRAGMENT = "http://hl7.org/fhir/tools/StructureDefinition/expansion-codesystem-fragment";
|
||||
public static final String EXT_EXP_TOOCOSTLY = "http://hl7.org/fhir/StructureDefinition/valueset-toocostly";
|
||||
|
||||
// specific extension helpers
|
||||
|
||||
|
|
Loading…
Reference in New Issue