Improved rendering of codes in include when rendering valuesets

This commit is contained in:
Grahame Grieve 2023-09-20 11:12:50 +10:00
parent e0af2b7916
commit eecc6633d3
3 changed files with 35 additions and 73 deletions

View File

@ -15,8 +15,10 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation; import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation;
import org.hl7.fhir.r5.context.TerminologyCache;
import org.hl7.fhir.r5.context.IWorkerContext.CodingValidationRequest; import org.hl7.fhir.r5.context.IWorkerContext.CodingValidationRequest;
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r5.context.TerminologyCache.CacheToken;
import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.BooleanType; import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
@ -26,8 +28,10 @@ import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ConceptMap; import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.DataType;
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.Extension; import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.ExtensionHelper; import org.hl7.fhir.r5.model.ExtensionHelper;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.PrimitiveType; 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.StringType; import org.hl7.fhir.r5.model.StringType;
@ -38,6 +42,7 @@ 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;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetFilterComponent;
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;
@ -48,9 +53,11 @@ import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.ValueSetUtilities; import org.hl7.fhir.r5.terminologies.ValueSetUtilities;
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.LoincLinker; import org.hl7.fhir.utilities.LoincLinker;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
@ -1142,7 +1149,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
} }
} }
private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index, Resource vsRes) throws FHIRException, IOException { private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index, ValueSet vsRes) throws FHIRException, IOException {
boolean hasExtensions = false; boolean hasExtensions = false;
XhtmlNode li; XhtmlNode li;
li = ul.li(); li = ul.li();
@ -1165,7 +1172,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
} }
// for performance reasons, we do all the fetching in one batch // for performance reasons, we do all the fetching in one batch
definitions = getConceptsForCodes(e, inc); definitions = getConceptsForCodes(e, inc, vsRes, index);
XhtmlNode t = li.table("none"); XhtmlNode t = li.table("none");
@ -1361,7 +1368,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
} }
private Map<String, ConceptDefinitionComponent> getConceptsForCodes(CodeSystem e, ConceptSetComponent inc) { private Map<String, ConceptDefinitionComponent> getConceptsForCodes(CodeSystem e, ConceptSetComponent inc, ValueSet source, int index) {
if (e == null) { if (e == null) {
e = getContext().getWorker().fetchCodeSystem(inc.getSystem()); e = getContext().getWorker().fetchCodeSystem(inc.getSystem());
} }
@ -1369,13 +1376,21 @@ public class ValueSetRenderer extends TerminologyRenderer {
ValueSetExpansionComponent vse = null; ValueSetExpansionComponent vse = null;
if (!context.isNoSlowLookup()) { // && !getContext().getWorker().hasCache()) { removed GG 20220107 like what is this trying to do? if (!context.isNoSlowLookup()) { // && !getContext().getWorker().hasCache()) { removed GG 20220107 like what is this trying to do?
try { try {
ValueSetExpansionOutcome vso = getContext().getWorker().expandVS(inc, false, false);
ValueSet vs = new ValueSet();
vs.setUrl(source.getUrl()+"-inc-"+index);
vs.setStatus(PublicationStatus.ACTIVE);
vs.setCompose(new ValueSetComposeComponent());
vs.getCompose().setInactive(false);
vs.getCompose().getInclude().add(inc);
ValueSetExpansionOutcome vso = getContext().getWorker().expandVS(vs, true, false);
ValueSet valueset = vso.getValueset(); ValueSet valueset = vso.getValueset();
if (valueset == null) if (valueset == null)
throw new TerminologyServiceException("Error Expanding ValueSet: "+vso.getError()); throw new TerminologyServiceException("Error Expanding ValueSet: "+vso.getError());
vse = valueset.getExpansion(); vse = valueset.getExpansion();
} catch (TerminologyServiceException e1) { } catch (Exception e1) {
return null; return null;
} }
} }

View File

@ -138,6 +138,15 @@ public class CommaSeparatedStringBuilder {
return self.toString(); return self.toString();
} }
public static String buildObjects(List<? extends Object> list) {
CommaSeparatedStringBuilder self = new CommaSeparatedStringBuilder();
for (Object s : list) {
self.append(s.toString());
}
return self.toString();
}
public static Set<String> toSet(String source) { public static Set<String> toSet(String source) {
if (source == null) { if (source == null) {
return null; return null;

View File

@ -173,6 +173,8 @@ import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPo
import org.hl7.fhir.r5.utils.validation.constants.IdStatus; import org.hl7.fhir.r5.utils.validation.constants.IdStatus;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.HL7WorkGroups;
import org.hl7.fhir.utilities.HL7WorkGroups.HL7WorkGroup;
import org.hl7.fhir.utilities.MarkDownProcessor; import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.SIDUtilities; import org.hl7.fhir.utilities.SIDUtilities;
import org.hl7.fhir.utilities.StandardsStatus; import org.hl7.fhir.utilities.StandardsStatus;
@ -5403,84 +5405,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wg != null, I18nConstants.VALIDATION_HL7_WG_NEEDED, ToolingExtensions.EXT_WORKGROUP)) { if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wg != null, I18nConstants.VALIDATION_HL7_WG_NEEDED, ToolingExtensions.EXT_WORKGROUP)) {
String name = nameForWG(wg); HL7WorkGroup wgd = HL7WorkGroups.find(wg);
String url = urlForWG(wg); if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), wgd != null, I18nConstants.VALIDATION_HL7_WG_UNKNOWN, wg)) {
if (rule(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), name != null, I18nConstants.VALIDATION_HL7_WG_UNKNOWN, wg)) { String rpub = "HL7 International / "+wgd.getName();
String rpub = "HL7 International / "+name;
if (warning(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), pub != null, I18nConstants.VALIDATION_HL7_PUBLISHER_MISSING, wg, rpub)) { if (warning(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), pub != null, I18nConstants.VALIDATION_HL7_PUBLISHER_MISSING, wg, rpub)) {
warningOrError(pub.contains("/"), errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), rpub.equals(pub), I18nConstants.VALIDATION_HL7_PUBLISHER_MISMATCH, wg, rpub, pub); warningOrError(pub.contains("/"), errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), rpub.equals(pub), I18nConstants.VALIDATION_HL7_PUBLISHER_MISMATCH, wg, rpub, pub);
} }
warning(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), warning(errors, "2023-09-15", IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(),
Utilities.startsWithInList(url, urls), I18nConstants.VALIDATION_HL7_WG_URL, wg, url); Utilities.startsWithInList( wgd.getLink(), urls), I18nConstants.VALIDATION_HL7_WG_URL, wg, wgd.getLink());
return true; return true;
} }
} }
return false; return false;
} }
private String urlForWG(String wg) {
switch (wg) {
case "cbcc": return "http://www.hl7.org/Special/committees/homehealth";
case "cds": return "http://www.hl7.org/Special/committees/dss";
case "cqi": return "http://www.hl7.org/Special/committees/cqi";
case "cg": return "http://www.hl7.org/Special/committees/clingenomics";
case "dev": return "http://www.hl7.org/Special/committees/healthcaredevices";
case "ehr": return "http://www.hl7.org/special/committees/ehr";
case "fhir": return "http://www.hl7.org/Special/committees/fiwg";
case "fm": return "http://www.hl7.org/Special/committees/fm";
case "hsi": return "http://www.hl7.org/Special/committees/hsi";
case "ii": return "http://www.hl7.org/Special/committees/imagemgt";
case "inm": return "http://www.hl7.org/special/committees/inm";
case "mnm": return "http://www.hl7.org/special/committees/mnm";
case "its": return "http://www.hl7.org/special/committees/xml";
case "oo": return "http://www.hl7.org/Special/committees/orders";
case "pa": return "http://www.hl7.org/Special/committees/pafm";
case "pc": return "http://www.hl7.org/Special/committees/patientcare";
case "pe": return "http://www.hl7.org/Special/committees/patientempowerment";
case "pher": return "http://www.hl7.org/Special/committees/pher";
case "phx": return "http://www.hl7.org/Special/committees/medication";
case "brr": return "http://www.hl7.org/Special/committees/rcrim";
case "sd": return "http://www.hl7.org/Special/committees/structure";
case "sec": return "http://www.hl7.org/Special/committees/secure";
case "us": return "http://www.hl7.org/Special/Committees/usrealm";
case "vocab": return "http://www.hl7.org/Special/committees/Vocab";
case "aid": return "http://www.hl7.org/Special/committees/java";
}
return null;
}
private String nameForWG(String wg) {
switch (wg) {
case "cbcc": return "Community Based Collaborative Care";
case "cds": return "Clinical Decision Support";
case "cqi": return "Clinical Quality Information";
case "cg": return "Clinical Genomics";
case "dev": return "Health Care Devices";
case "ehr": return "Electronic Health Records";
case "fhir": return "FHIR Infrastructure";
case "fm": return "Financial Management";
case "hsi": return "Health Standards Integration";
case "ii": return "Imaging Integration";
case "inm": return "Infrastructure And Messaging";
case "mnm": return "Modeling and Methodology";
case "its": return "Implementable Technology Specifications";
case "oo": return "Orders and Observations";
case "pa": return "Patient Administration";
case "pc": return "Patient Care";
case "pe": return "Patient Empowerment";
case "pher": return "Public Health and Emergency Response";
case "phx": return "Pharmacy";
case "brr": return "Biomedical Research and Regulation";
case "sd": return "Structured Documents";
case "sec": return "Security";
case "us": return "US Realm Taskforce";
case "vocab": return "Terminology Infrastructure";
case "aid": return "Application Implementation and Design";
}
return null;
}
private boolean statusCodesConsistent(String status, String standardsStatus) { private boolean statusCodesConsistent(String status, String standardsStatus) {
switch (standardsStatus) { switch (standardsStatus) {
case "draft": return Utilities.existsInList(status, "draft"); case "draft": return Utilities.existsInList(status, "draft");