From 0fa757b426a51699d308a276318213e7977ce01e Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Sat, 12 Feb 2022 07:53:23 +1100 Subject: [PATCH] Fix markdown relative link issues + start working on additional bindings extension --- .../loaders/loaderR5/BaseLoaderR5.java | 5 ++ .../loaderR5/ILoaderKnowledgeProviderR5.java | 2 + .../NullLoaderKnowledgeProviderR5.java | 5 ++ .../fhir/r5/conformance/ProfileUtilities.java | 47 ++++++++++++++++--- .../hl7/fhir/r5/utils/ToolingExtensions.java | 1 + .../src/test/resources/txCache/loinc.cache | 45 ++++++++++++++++++ .../resources/txCache/4.0.1/all-systems.cache | 8 ++++ 7 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 org.hl7.fhir.r5/src/test/resources/txCache/loinc.cache diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/BaseLoaderR5.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/BaseLoaderR5.java index 63a799d32..58e5b2ff0 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/BaseLoaderR5.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/BaseLoaderR5.java @@ -38,6 +38,11 @@ public abstract class BaseLoaderR5 implements IContextResourceLoader { public void setPath(Resource r) { String path = lkp.getResourcePath(r); + if (lkp.getWebRoot() != null) { + r.setUserData("webroot", lkp.getWebRoot()); + } else { + r.setUserData("webroot", ""); + } if (path != null) { r.setUserData("path", path); } diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/ILoaderKnowledgeProviderR5.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/ILoaderKnowledgeProviderR5.java index 9ed940ea0..3a8c1ca3b 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/ILoaderKnowledgeProviderR5.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/ILoaderKnowledgeProviderR5.java @@ -16,4 +16,6 @@ public interface ILoaderKnowledgeProviderR5 { String getResourcePath(Resource resource); ILoaderKnowledgeProviderR5 forNewPackage(NpmPackage npm) throws JsonSyntaxException, IOException; + + String getWebRoot(); } diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/NullLoaderKnowledgeProviderR5.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/NullLoaderKnowledgeProviderR5.java index 15986d5bb..6af390878 100644 --- a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/NullLoaderKnowledgeProviderR5.java +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/NullLoaderKnowledgeProviderR5.java @@ -13,4 +13,9 @@ public class NullLoaderKnowledgeProviderR5 implements ILoaderKnowledgeProviderR5 public ILoaderKnowledgeProviderR5 forNewPackage(NpmPackage npm) { return this; } + + @Override + public String getWebRoot() { + return null; + } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 59de6012d..8123817b5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -104,6 +104,7 @@ import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingCompo import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionSnapshotComponent; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.model.UriType; +import org.hl7.fhir.r5.model.UsageContext; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; @@ -2480,19 +2481,19 @@ public class ProfileUtilities extends TranslatingUtilities { if (webUrl != null) { // also, must touch up the markdown if (element.hasDefinition()) - element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames)); + element.setDefinition(processRelativeUrls(element.getDefinition(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true)); if (element.hasComment()) - element.setComment(processRelativeUrls(element.getComment(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames)); + element.setComment(processRelativeUrls(element.getComment(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true)); if (element.hasRequirements()) - element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames)); + element.setRequirements(processRelativeUrls(element.getRequirements(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true)); if (element.hasMeaningWhenMissing()) - element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames)); + element.setMeaningWhenMissing(processRelativeUrls(element.getMeaningWhenMissing(), webUrl, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true)); } } return element; } - public static String processRelativeUrls(String markdown, String webUrl, String basePath, List resourceNames, Set filenames) { + public static String processRelativeUrls(String markdown, String webUrl, String basePath, List resourceNames, Set filenames, boolean processRelatives) { StringBuilder b = new StringBuilder(); int i = 0; while (i < markdown.length()) { @@ -2520,7 +2521,13 @@ public class ProfileUtilities extends TranslatingUtilities { } else { b.append("]("); // disabled 7-Dec 2021 GDG - we don't want to fool with relative URLs at all? - // b.append(webUrl); + // re-enabled 11-Feb 2022 GDG - we do want to do this. At least, $assemble in davinci-dtr, where the markdown comes from the SDC IG, and an SDC local reference must be changed to point to SDC. in this case, it's called when generating snapshots + // added processRelatives parameter to deal with this (well, to try) + if (processRelatives) { + b.append(webUrl); + } else { + System.out.println("Not making "+url+" relative to '"+webUrl+"'"); + } i = i + 1; } } else @@ -2778,7 +2785,9 @@ public class ProfileUtilities extends TranslatingUtilities { profile = source.getType().size() == 1 && source.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, source.getTypeFirstRep().getProfile().get(0).getValue()) : null; if (profile != null) { ElementDefinition e = profile.getSnapshot().getElement().get(0); - base.setDefinition(e.getDefinition()); + String webroot = profile.getUserString("webroot"); + + base.setDefinition(processRelativeUrls(e.getDefinition(), webroot, baseSpecUrl(), context.getResourceNames(), masterSourceFileNames, true)); base.setShort(e.getShort()); if (e.hasCommentElement()) base.setCommentElement(e.getCommentElement()); @@ -4688,6 +4697,13 @@ public class ProfileUtilities extends TranslatingUtilities { c.getPieces().add(gen.new Piece(null, ": ", null)); c.addMarkdownNoPara(PublicationHacker.fixBindingDescriptions(context, binding.getDescriptionElement()).asStringValue(), checkForNoChange(PublicationHacker.fixBindingDescriptions(context, binding.getDescriptionElement()))); } + if (binding.hasExtension(ToolingExtensions.EXT_BINDING_ADDITIONAL)) { + c.addPiece(gen.new Piece("br")); + c.getPieces().add(checkForNoChange(binding, gen.new Piece(null, translate("sd.table", "Additional Bindings")+": ", null).addStyle("font-weight:bold"))); + for (Extension ext : binding.getExtensionsByUrl(ToolingExtensions.EXT_BINDING_ADDITIONAL)) { + renderAdditionalBinding(gen, c, ext); + } + } } for (ElementDefinitionConstraintComponent inv : definition.getConstraint()) { if (!inv.hasSource() || profile == null || inv.getSource().equals(profile.getUrl()) || allInvariants) { @@ -4767,6 +4783,23 @@ public class ProfileUtilities extends TranslatingUtilities { return c; } + private void renderAdditionalBinding(HierarchicalTableGenerator gen, Cell c, Extension ext) { + // 2 purpose value-set-link ([context]) {documentation} +// String purpose = ext.getExtensionString("purpose"); +// String valueSet = ext.getExtensionString("valueSet"); +// String doco = ext.getExtensionString("documentation"); +// UsageContext usage = (ext.hasExtension("usage")) ? ext.getExtensionByUrl("usage").getValueUsageContext() : null; +// +// purpose: code - defines how the binding is used +// usage : UsageContext - defines the contexts in which this binding is used for it's purpose +// valueSet : canonical(ValueSet) +// documentation : markdown +// !! +// c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, inv.getKey()+": ", null).addStyle("font-weight:bold"))); +// c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, gt(inv.getHumanElement()), null))); + + } + private BindingResolution makeNullBr(ElementDefinitionBindingComponent binding) { BindingResolution br = new BindingResolution(); br.url = "http://none.none/none"; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java index 1815f56cf..6ef84e898 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java @@ -200,6 +200,7 @@ public class ToolingExtensions { public static final String EXT_VALUESET_SYSTEM = "http://hl7.org/fhir/StructureDefinition/valueset-system"; public static final String EXT_EXPAND_RULES = "http://hl7.org/fhir/StructureDefinition/valueset-expand-rules"; public static final String EXT_EXPAND_GROUP = "http://hl7.org/fhir/StructureDefinition/valueset-expand-group"; + public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding"; // specific extension helpers diff --git a/org.hl7.fhir.r5/src/test/resources/txCache/loinc.cache b/org.hl7.fhir.r5/src/test/resources/txCache/loinc.cache new file mode 100644 index 000000000..8e1e3c41a --- /dev/null +++ b/org.hl7.fhir.r5/src/test/resources/txCache/loinc.cache @@ -0,0 +1,45 @@ +------------------------------------------------------------------------------------- +{"hierarchical" : false, "valueSet" :{ + "resourceType" : "ValueSet", + "compose" : { + "include" : [{ + "system" : "http://loinc.org", + "concept" : [{ + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/valueset-label", + "valueString" : "A." + }], + "code" : "LA20752-4", + "display" : "Within 24 hours" + }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/valueset-label", + "valueString" : "B." + }], + "code" : "LA20753-2", + "display" : "After 24 hours but before 3 days" + }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/valueset-label", + "valueString" : "C." + }], + "code" : "LA20754-0", + "display" : "Three days or later" + }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/valueset-label", + "valueString" : "D." + }], + "code" : "LA4489-6", + "display" : "Unknown" + }] + }] + } +}}#### +e: { + "error" : "Cannot invoke \"org.hl7.fhir.r5.terminologies.TerminologyClient.expandValueset(org.hl7.fhir.r5.model.ValueSet, org.hl7.fhir.r5.model.Parameters, java.util.Map)\" because \"this.txClient\" is null" +} +------------------------------------------------------------------------------------- diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/all-systems.cache b/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/all-systems.cache index d61c0a93c..733b04079 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/all-systems.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/4.0.1/all-systems.cache @@ -1591,3 +1591,11 @@ v: { "error" : "Unable to find code 10821000202101 in http://snomed.info/sct (version http://snomed.info/sct/900000000000207008/version/20210731); The code \"10821000202101\" is not valid in the system http://snomed.info/sct; The code provided (http://snomed.info/sct#10821000202101) is not valid in the value set 'no-colonoscopy-sedation-level' (from http://tx.fhir.org/r4)" } ------------------------------------------------------------------------------------- +{"code" : { + "code" : "pdf" +}, "url": "http://hl7.org/fhir/ValueSet/mimetypes", "version": "4.0.1", "lang":"null", "useServer":"true", "useClient":"true", "guessSystem":"true", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}#### +v: { + "severity" : "error", + "error" : "The code \"pdf\" is not valid in the system urn:ietf:bcp:13; The code provided (urn:ietf:bcp:13#pdf) is not valid in the value set 'Mime Types' (from http://tx.fhir.org/r4)" +} +-------------------------------------------------------------------------------------