Fix logical model rendering to use type characteristics for can-be-target

This commit is contained in:
Grahame Grieve 2024-12-19 13:16:48 +11:00
parent 952edabded
commit ef86cf7652
5 changed files with 59 additions and 17 deletions

View File

@ -51,6 +51,7 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext.OIDDefinition;
import org.hl7.fhir.r5.context.IWorkerContext.OIDDefinitionComparer;
import org.hl7.fhir.r5.context.IWorkerContext.ITerminologyOperationDetails;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.formats.ParserType;
@ -109,6 +110,10 @@ import javax.annotation.Nonnull;
public interface IWorkerContext {
public interface ITerminologyOperationDetails {
public void seeSupplement(CodeSystem supp);
}
/**
@deprecated This interface only exists to provide backward compatibility for the following two projects:
<a href="https://github.com/cqframework/clinical-reasoning">clinical-reasoning</a>
@ -513,7 +518,7 @@ public interface IWorkerContext {
* @return
* @throws FHIRException
*/
ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean hierarchical, boolean noInactive) throws TerminologyServiceException;
ValueSetExpansionOutcome expandVS(ITerminologyOperationDetails opCtxt, ConceptSetComponent inc, boolean hierarchical, boolean noInactive) throws TerminologyServiceException;
/**
* get/set the locale used when creating messages

View File

@ -1580,20 +1580,18 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
if (profile.getKind() == StructureDefinitionKind.LOGICAL) {
Extension lt = ToolingExtensions.getExtension(profile, ToolingExtensions.EXT_LOGICAL_TARGET);
if (lt == null || !lt.hasValueBooleanType()) {
List<Extension> tc = ToolingExtensions.getExtensions(profile, ToolingExtensions.EXT_TYPE_CHARACTERISTICS);
Boolean canBeTarget = checkCanBeTarget(lt, tc);
if (canBeTarget == null) {
// don't say anything
} else if (canBeTarget) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.addPiece(gen.new Piece(null, context.formatPhrase(RenderingContext.STRUC_DEF_NOT_MARK), null).addStyle("font-weight:bold")); ;
} else if (lt.getValue().hasExtension(ToolingExtensions.EXT_DAR)) {
} else if (!lt.getValueBooleanType().hasValue()) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.addPiece(gen.new Piece(null, context.formatPhrase(RenderingContext.STRUC_DEF_CAN_TARGET), null).addStyle("font-weight:bold")); ;
} else if (lt.getValueBooleanType().booleanValue()) {
c.addPiece(gen.new Piece(null, context.formatPhrase(RenderingContext.STRUC_DEF_CAN_TARGET), null).addStyle("font-weight:bold"));
} else {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.addPiece(gen.new Piece(null, context.formatPhrase(RenderingContext.STRUC_DEF_CAN_TARGET), null).addStyle("font-weight:bold"));
} else {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
c.addPiece(gen.new Piece(null, context.formatPhrase(RenderingContext.STRUC_DEF_CAN_TARGET), null).addStyle("font-weight:bold"));
}
c.addPiece(gen.new Piece(null, context.formatPhrase(RenderingContext.STRUC_DEF_NOT_MARK), null).addStyle("font-weight:bold"));
}
String ps = ToolingExtensions.readStringExtension(profile, ToolingExtensions.EXT_PROFILE_STYLE);
if (ps != null) {
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
@ -1765,6 +1763,27 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
return c;
}
private Boolean checkCanBeTarget(Extension lt, List<Extension> tc) {
Boolean res = null;
if (lt == null || !lt.hasValueBooleanType() || lt.getValue().hasExtension(ToolingExtensions.EXT_DAR)) {
} else if (!lt.getValueBooleanType().hasValue()) {
res = null; // GDG Dec-2024: this is true, but changed to null
} else if (lt.getValueBooleanType().booleanValue()) {
res = true;
} else {
res = false; // GDG Dec 2024- this was true, but evidently should be false, so fixed
}
if (res == null && !tc.isEmpty()) {
res = false;
for (Extension t : tc) {
if (t.hasValueCodeType() && "can-be-target".equals(t.getValueCodeType().primitiveValue())) {
res = true;
}
}
}
return res;
}
private boolean isAbstractBaseProfile(String source) {
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, source);
return (sd != null) && sd.getAbstract() && sd.hasUrl() && sd.getUrl().startsWith("http://hl7.org/fhir/StructureDefinition/");

View File

@ -120,6 +120,7 @@ import org.hl7.fhir.r5.terminologies.providers.CodeSystemProvider;
import org.hl7.fhir.r5.terminologies.providers.CodeSystemProviderExtension;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext.TerminologyServiceProtectionException;
import org.hl7.fhir.r5.terminologies.utilities.ValueSetProcessBase.TerminologyOperationDetails;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
import org.hl7.fhir.r5.terminologies.utilities.ValueSetProcessBase;
import org.hl7.fhir.r5.utils.ToolingExtensions;
@ -609,7 +610,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
if (exc.hasSystem()) {
CodeSystem cs = context.fetchSupplementedCodeSystem(exc.getSystem());
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(exc.getSystem(), opContext.getOptions().getFhirVersion())) {
ValueSetExpansionOutcome vse = context.expandVS(exc, false, false);
ValueSetExpansionOutcome vse = context.expandVS(new TerminologyOperationDetails(requiredSupplements), exc, false, false);
ValueSet valueset = vse.getValueset();
if (valueset == null)
throw failTSE("Error Expanding ValueSet: "+vse.getError());
@ -655,7 +656,6 @@ public class ValueSetExpander extends ValueSetProcessBase {
}
public ValueSetExpansionOutcome expand(ValueSet source, Parameters expParams) {
allErrors.clear();
try {
opContext.seeContext(source.getVersionedUrl());
@ -1050,7 +1050,7 @@ public class ValueSetExpander extends ValueSetProcessBase {
return;
}
ValueSetExpansionOutcome vso = context.expandVS(inc, heirarchical, noInactive);
ValueSetExpansionOutcome vso = context.expandVS(new TerminologyOperationDetails(requiredSupplements), inc, heirarchical, noInactive);
if (vso.getError() != null) {
throw failTSE("Unable to expand imported value set: " + vso.getError());
}

View File

@ -5,8 +5,10 @@ import java.util.List;
import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext.ITerminologyOperationDetails;
import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r5.model.OperationOutcome.IssueType;
@ -27,6 +29,22 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
public class ValueSetProcessBase {
public static class TerminologyOperationDetails implements ITerminologyOperationDetails {
private List<String> supplements;
public TerminologyOperationDetails(List<String> supplements) {
super();
this.supplements = supplements;
}
@Override
public void seeSupplement(CodeSystem supp) {
supplements.remove(supp.getUrl());
supplements.remove(supp.getVersionedUrl());
}
}
public enum OpIssueCode {
NotInVS, ThisNotInVS, InvalidCode, Display, DisplayComment, NotFound, CodeRule, VSProcessing, InferFailed, StatusCheck, InvalidData;

View File

@ -1291,7 +1291,7 @@ public class ValueSetValidator extends ValueSetProcessBase {
sys.add(vsi.getSystem());
} else {
// ok, we'll try to expand this one then
ValueSetExpansionOutcome vse = context.expandVS(vsi, false, false);
ValueSetExpansionOutcome vse = context.expandVS(new TerminologyOperationDetails(requiredSupplements), vsi, false, false);
if (vse.isOk()) {
if (!checkSystems(vse.getValueset().getExpansion().getContains(), code, sys, problems)) {
return false;