From d97e2d8534a0f58ca431380ffa6056b3df6ef31b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 29 Aug 2022 12:44:27 +1000 Subject: [PATCH 1/5] FHIR-31356 Add quick links to copy 'coding' from value set and code system enumerations --- .../hl7/fhir/r5/renderers/CodeSystemRenderer.java | 15 ++++++++++++++- .../fhir/r5/renderers/TerminologyRenderer.java | 14 +++++++++++--- .../fhir/r5/renderers/utils/RenderingContext.java | 9 +++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java index bb8d121b2..55151f29d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CodeSystemRenderer.java @@ -183,7 +183,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { hierarchy = hierarchy || csNav.isRestructure(); List langs = new ArrayList<>(); - addMapHeaders(addTableHeaderRowStandard(t, hierarchy, display, definitions, commentS, version, deprecated, properties, null, null, false), maps); + addCopyColumn(addMapHeaders(addTableHeaderRowStandard(t, hierarchy, display, definitions, commentS, version, deprecated, properties, null, null, false), maps)); for (ConceptDefinitionComponent c : csNav.getConcepts(null)) { hasExtensions = addDefineRowToTable(t, c, 0, hierarchy, display, definitions, commentS, version, deprecated, maps, cs.getUrl(), cs, properties, csNav, langs, isSupplement) || hasExtensions; } @@ -202,6 +202,13 @@ public class CodeSystemRenderer extends TerminologyRenderer { return hasExtensions; } + private void addCopyColumn(XhtmlNode tr) { + if (context.isCopyButton()) { + tr.td().b().tx("Copy"); + } + + } + private boolean conceptsHaveDefinition(ConceptDefinitionComponent c) { if (c.hasDefinition()) { return true; @@ -492,6 +499,12 @@ public class CodeSystemRenderer extends TerminologyRenderer { } td = tr.td().colspan(Integer.toString(w)); } + if (context.isCopyButton()) { + td = tr.td(); + clipboard(td, "icon_clipboard_x.png", "XML", "\n"+(cs.getVersionNeeded() ? "\n" : "")+"\n\n"); + td.nbsp(); + clipboard(td, "icon_clipboard_j.png", "JSON", "\"system\" : \""+Utilities.escapeXml(cs.getUrl())+"\",\n"+(cs.getVersionNeeded() ? "\"version\" : \""+Utilities.escapeXml(cs.getVersion())+"\",\n" : "")+"\"code\" : \""+Utilities.escapeXml(c.getCode())+"\",\n\"display\" : \""+Utilities.escapeXml(c.getDisplay())+"\"\n"); + } return hasExtensions; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TerminologyRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TerminologyRenderer.java index d7fe9c06e..ed14cd19b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TerminologyRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TerminologyRenderer.java @@ -111,7 +111,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer { } - protected void addMapHeaders(XhtmlNode tr, List maps) throws FHIRFormatError, DefinitionException, IOException { + protected XhtmlNode addMapHeaders(XhtmlNode tr, List maps) throws FHIRFormatError, DefinitionException, IOException { for (UsedConceptMap m : maps) { XhtmlNode td = tr.td(); XhtmlNode b = td.b(); @@ -120,6 +120,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer { if (m.getDetails().isDoDescription() && m.getMap().hasDescription()) addMarkdown(td, m.getMap().getDescription()); } + return tr; } protected String getHeader() { @@ -311,8 +312,6 @@ public abstract class TerminologyRenderer extends ResourceRenderer { } } - - protected String getDisplayForConcept(String system, String version, String value) { if (value == null || system == null) return null; @@ -320,4 +319,13 @@ public abstract class TerminologyRenderer extends ResourceRenderer { return cl == null ? null : cl.getDisplay(); } + + protected void clipboard(XhtmlNode x, String img, String title, String source) { + XhtmlNode span = x.span("cursor: pointer", "Copy "+title+" Format to clipboard"); + span.attribute("onClick", "navigator.clipboard.writeText('"+Utilities.escapeJson(source)+"');"); + span.img(img).setAttribute("width", "24px").setAttribute("height", "16px"); + } + + + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java index 57bb8c20d..dc854c463 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java @@ -131,6 +131,7 @@ public class RenderingContext { private DateTimeFormatter dateFormat; private DateTimeFormatter dateYearFormat; private DateTimeFormatter dateYearMonthFormat; + private boolean copyButton; /** * @@ -190,6 +191,7 @@ public class RenderingContext { res.targetVersion = targetVersion; res.locale = locale; res.showComments = showComments; + res.copyButton = copyButton; res.terminologyServiceOptions = terminologyServiceOptions.copy(); return res; @@ -596,6 +598,13 @@ public class RenderingContext { this.showComments = showComments; return this; } + public boolean isCopyButton() { + return copyButton; + } + public RenderingContext setCopyButton(boolean copyButton) { + this.copyButton = copyButton; + return this; + } } \ No newline at end of file From 17adc621d34d1069f7115283344bfc8afc2258dc Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 29 Aug 2022 12:45:42 +1000 Subject: [PATCH 2/5] get oid for canonical resource --- .../java/org/hl7/fhir/r5/model/CanonicalResource.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/CanonicalResource.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/CanonicalResource.java index c9275b605..ad40e273c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/CanonicalResource.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/CanonicalResource.java @@ -559,5 +559,14 @@ public abstract class CanonicalResource extends DomainResource { } // end addition + public String oid() { + for (Identifier id : getIdentifier()) { + if (id.getValue().startsWith("urn:oid:")) { + return id.getValue().substring(8); + } + } + return null; + } + } From 4db936752a80792d44eb40e4818c85aea1837297 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 29 Aug 2022 15:53:47 +1000 Subject: [PATCH 3/5] FHIR-24884 Define best practices for narrative for a resource --- .../hl7/fhir/r5/renderers/LiquidRenderer.java | 25 +++++++++++++++- .../hl7/fhir/r5/renderers/ListRenderer.java | 23 ++++++++------- .../r5/renderers/ProfileDrivenRenderer.java | 4 +++ .../fhir/r5/renderers/RendererFactory.java | 9 +++++- .../fhir/r5/renderers/ResourceRenderer.java | 10 +++++++ .../r5/renderers/utils/RenderingContext.java | 2 ++ .../org/hl7/fhir/r5/utils/LiquidEngine.java | 29 ++++++++++++++++++- .../r5/test/NarrativeGenerationTests.java | 4 +++ .../java/org/hl7/fhir/r5/test/VocabTests.java | 6 ++++ .../4.0.1/all-systems.cache | 9 ++++++ 10 files changed, 108 insertions(+), 13 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java index bc8eb4caa..7959109d7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java @@ -6,6 +6,8 @@ import java.io.UnsupportedEncodingException; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.elementmodel.Element; +import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; @@ -13,12 +15,13 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.LiquidEngine; +import org.hl7.fhir.r5.utils.LiquidEngine.ILiquidRenderingSupport; import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; -public class LiquidRenderer extends ResourceRenderer { +public class LiquidRenderer extends ResourceRenderer implements ILiquidRenderingSupport { private String liquidTemplate; @@ -56,6 +59,7 @@ public class LiquidRenderer extends ResourceRenderer { XhtmlNode xn; try { engine.setIncludeResolver(new LiquidRendererIncludeResolver(context)); + engine.setRenderingSupport(this); LiquidDocument doc = engine.parse(liquidTemplate, "template"); String html = engine.evaluate(doc, r, rcontext); xn = new XhtmlParser().parseFragment(html); @@ -102,4 +106,23 @@ public class LiquidRenderer extends ResourceRenderer { return true; } + public RendererType getRendererType() { + return RendererType.LIQUID; + } + + @Override + public String renderForLiquid(Base base) throws FHIRException { + try { + if (base instanceof Element) { + return displayBase(context.getParser().parseType((Element) base)); + } else { + return displayBase(base); + } + } catch (FHIRFormatError e) { + throw new FHIRException(e); + } catch (IOException e) { + throw new FHIRException(e); + } + } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ListRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ListRenderer.java index 8f0d1a1c1..60746987c 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ListRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ListRenderer.java @@ -207,7 +207,6 @@ public class ListRenderer extends ResourceRenderer { } } - private XhtmlNode shortForRef(XhtmlNode x, Base ref) throws UnsupportedEncodingException, IOException { if (ref == null) { x.tx("(null)"); @@ -215,16 +214,20 @@ public class ListRenderer extends ResourceRenderer { String disp = ref.getChildByName("display") != null && ref.getChildByName("display").hasValues() ? ref.getChildByName("display").getValues().get(0).primitiveValue() : null; if (ref.getChildByName("reference").hasValues()) { String url = ref.getChildByName("reference").getValues().get(0).primitiveValue(); - ResourceWithReference r = context.getResolver().resolve(context, url); - if (r == null) { - if (disp == null) { - disp = url; - } - x.tx(disp); - } else if (r.getResource() != null) { - RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, (Reference) ref); + if (url.startsWith("#")) { + x.tx("?ngen-16a?"); } else { - RendererFactory.factory(url, context).renderReference(r.getResource(), x, (Reference) ref); + ResourceWithReference r = context.getResolver().resolve(context, url); + if (r == null) { + if (disp == null) { + disp = url; + } + x.tx(disp); + } else if (r.getResource() != null) { + RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, (Reference) ref); + } else { + x.ah(r.getReference()).tx(url); + } } } else if (disp != null) { x.tx(disp); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java index 62c9d5412..944444d6f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProfileDrivenRenderer.java @@ -1015,4 +1015,8 @@ public class ProfileDrivenRenderer extends ResourceRenderer { return context.getWorker().getResourceNames().contains(resource.fhirType()); } + public RendererType getRendererType() { + return RendererType.PROFILE; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RendererFactory.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RendererFactory.java index 9d974bb21..3f5e006c4 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RendererFactory.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RendererFactory.java @@ -5,6 +5,7 @@ import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.utilities.Utilities; public class RendererFactory { @@ -131,5 +132,11 @@ public class RendererFactory { return factory(rw, lrc, null); } - + public static boolean hasSpecificRenderer(String rt) { + + return Utilities.existsInList(rt, + "CodeSystem", "ValueSet", "ConceptMap", + "CapabilityStatement", "CompartmentDefinition", "ImplementationGuide", "Library", "NamingSystem", "OperationDefinition", "Questionnaire", "SearchParameter", "StructureDefinition"); + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java index 1dc024895..79798edcb 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java @@ -26,6 +26,7 @@ import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.DirectWrappers.ResourceWrapperDirect; import org.hl7.fhir.r5.renderers.utils.ElementWrappers.ResourceWrapperMetaElement; +import org.hl7.fhir.r5.renderers.ResourceRenderer.RendererType; 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.ResourceWithReference; @@ -39,6 +40,11 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public abstract class ResourceRenderer extends DataRenderer { + public enum RendererType { + NATIVE, PROFILE, LIQUID + + } + protected ResourceContext rcontext; protected XVerExtensionManager xverManager; protected boolean forResource; @@ -507,4 +513,8 @@ public abstract class ResourceRenderer extends DataRenderer { } } + + public RendererType getRendererType() { + return RendererType.NATIVE; + } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java index dc854c463..370e4a2ad 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/RenderingContext.java @@ -15,6 +15,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider; import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.Enumerations.FHIRVersion; @@ -38,6 +39,7 @@ public class RenderingContext { // parses xml to an XML instance. Whatever codes provides this needs to provide something that parses the right version public interface ITypeParser { Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException ; + Base parseType(Element base) throws FHIRFormatError, IOException, FHIRException ; } /** diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java index 043ede0cc..7521c4107 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java @@ -1,5 +1,6 @@ package org.hl7.fhir.r5.utils; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -37,22 +38,31 @@ import java.util.Map; */ import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.PathEngineException; import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.ExpressionNode; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Tuple; import org.hl7.fhir.r5.model.TypeDetails; import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; +import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.utils.FHIRPathEngine.ExpressionNodeWithOffset; import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext; +import org.hl7.fhir.r5.utils.LiquidEngine.ILiquidRenderingSupport; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class LiquidEngine implements IEvaluationContext { + public interface ILiquidRenderingSupport { + String renderForLiquid(Base i) throws FHIRException; + } + public interface ILiquidEngineIncludeResolver { public String fetchInclude(LiquidEngine engine, String name); } @@ -60,6 +70,7 @@ public class LiquidEngine implements IEvaluationContext { private IEvaluationContext externalHostServices; private FHIRPathEngine engine; private ILiquidEngineIncludeResolver includeResolver; + private ILiquidRenderingSupport renderingSupport; private class LiquidEngineContext { private Object externalContext; @@ -92,6 +103,14 @@ public class LiquidEngine implements IEvaluationContext { this.includeResolver = includeResolver; } + public ILiquidRenderingSupport getRenderingSupport() { + return renderingSupport; + } + + public void setRenderingSupport(ILiquidRenderingSupport renderingSupport) { + this.renderingSupport = renderingSupport; + } + public LiquidDocument parse(String source, String sourceName) throws FHIRException { return new LiquidParser(source).parse(sourceName); } @@ -104,6 +123,7 @@ public class LiquidEngine implements IEvaluationContext { } return b.toString(); } + private abstract class LiquidNode { protected void closeUp() { @@ -130,6 +150,7 @@ public class LiquidEngine implements IEvaluationContext { public void evaluate(StringBuilder b, Base resource, LiquidEngineContext ctxt) { b.append(constant); } + } private class LiquidStatement extends LiquidNode { @@ -140,7 +161,13 @@ public class LiquidEngine implements IEvaluationContext { public void evaluate(StringBuilder b, Base resource, LiquidEngineContext ctxt) throws FHIRException { if (compiled == null) compiled = engine.parse(statement); - b.append(engine.evaluateToString(ctxt, resource, resource, resource, compiled)); + List items = engine.evaluate(ctxt, resource, resource, resource, compiled); + boolean first = true; + for (Base i : items) { + if (first) first = false; else b.append(", "); + String s = renderingSupport != null ? renderingSupport.renderForLiquid(i) : null; + b.append(s != null ? s : engine.convertToString(i)); + } } } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java index 483041201..42cb884eb 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java @@ -111,6 +111,10 @@ public class NarrativeGenerationTests { public Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException { return new org.hl7.fhir.r5.formats.XmlParser().parseType(xml, type); } + @Override + public Base parseType(org.hl7.fhir.r5.elementmodel.Element e) throws FHIRFormatError, IOException, FHIRException { + throw new NotImplementedException(); + } } public static final String WINDOWS = "WINDOWS"; diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java index 18e5d428c..5e74e075e 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/VocabTests.java @@ -9,6 +9,7 @@ import java.util.stream.Stream; import javax.xml.parsers.ParserConfigurationException; +import org.apache.commons.lang3.NotImplementedException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.context.IWorkerContext; @@ -50,6 +51,11 @@ public class VocabTests { public Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException { return new org.hl7.fhir.r5.formats.XmlParser().parseType(xml, type); } + + @Override + public Base parseType(org.hl7.fhir.r5.elementmodel.Element e) throws FHIRFormatError, IOException, FHIRException { + throw new NotImplementedException(); + } } private static IWorkerContext context; diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/all-systems.cache b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/all-systems.cache index 14c90b885..795bf7576 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/all-systems.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/all-systems.cache @@ -1542,3 +1542,12 @@ v: { "system" : "urn:iso:std:iso:3166" } ------------------------------------------------------------------------------------- +{"code" : { + "code" : "en-AU" +}, "url": "http://hl7.org/fhir/ValueSet/languages", "version": "4.0.1", "lang":"en-AU", "useServer":"true", "useClient":"true", "guessSystem":"true", "valueSetMode":"ALL_CHECKS", "versionFlexible":"false"}#### +v: { + "display" : "English (Australia)", + "code" : "en-AU", + "system" : "urn:ietf:bcp:47" +} +------------------------------------------------------------------------------------- From 3b4260d955779b46b1ed73628ca10c90dba0ea8b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 29 Aug 2022 16:17:21 +1000 Subject: [PATCH 4/5] FHIR-24884 Define best practices for narrative for a resource --- .../org/hl7/fhir/r5/renderers/LiquidRenderer.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java index 7959109d7..76cee540e 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java @@ -8,6 +8,7 @@ import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; @@ -18,6 +19,7 @@ import org.hl7.fhir.r5.utils.LiquidEngine; import org.hl7.fhir.r5.utils.LiquidEngine.ILiquidRenderingSupport; import org.hl7.fhir.r5.utils.LiquidEngine.LiquidDocument; import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlComposer; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; @@ -94,6 +96,7 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering XhtmlNode xn; try { LiquidDocument doc = engine.parse(liquidTemplate, "template"); + engine.setRenderingSupport(this); String html = engine.evaluate(doc, r.getBase(), rcontext); xn = new XhtmlParser().parseFragment(html); if (!x.getName().equals("div")) @@ -114,10 +117,16 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering public String renderForLiquid(Base base) throws FHIRException { try { if (base instanceof Element) { - return displayBase(context.getParser().parseType((Element) base)); - } else { - return displayBase(base); + base = context.getParser().parseType((Element) base); } + XhtmlNode x = new XhtmlNode(NodeType.Element); + if (base instanceof DataType) { + render(x, (DataType) base); + } else { + x.tx(base.toString()); + } + String res = new XhtmlComposer(true).compose(x).substring(5); + return res.substring(0, res.length()-6); } catch (FHIRFormatError e) { throw new FHIRException(e); } catch (IOException e) { From 832da9fc6bf15d79ffcf15c0dbfee8421a031bde Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Mon, 29 Aug 2022 17:52:39 +1000 Subject: [PATCH 5/5] fix up rendering --- .../hl7/fhir/r5/renderers/LiquidRenderer.java | 28 ++++++++++++++++--- .../org/hl7/fhir/r5/utils/LiquidEngine.java | 4 +-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java index 76cee540e..938f32bdc 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LiquidRenderer.java @@ -10,8 +10,10 @@ import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.DomainResource; +import org.hl7.fhir.r5.model.Reference; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; +import org.hl7.fhir.r5.renderers.LiquidRenderer.LiquidRendererContxt; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r5.utils.EOperationOutcome; @@ -25,6 +27,22 @@ import org.hl7.fhir.utilities.xhtml.XhtmlParser; public class LiquidRenderer extends ResourceRenderer implements ILiquidRenderingSupport { + public class LiquidRendererContxt { + + private ResourceContext rcontext; + private ResourceWrapper resource; + + public LiquidRendererContxt(ResourceContext rcontext, ResourceWrapper r) { + this.rcontext = rcontext; + this.resource = r; + } + + public ResourceWrapper getResource() { + return resource; + } + + } + private String liquidTemplate; public LiquidRenderer(RenderingContext context, String liquidTemplate) { @@ -97,7 +115,7 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering try { LiquidDocument doc = engine.parse(liquidTemplate, "template"); engine.setRenderingSupport(this); - String html = engine.evaluate(doc, r.getBase(), rcontext); + String html = engine.evaluate(doc, r.getBase(), new LiquidRendererContxt(rcontext, r)); xn = new XhtmlParser().parseFragment(html); if (!x.getName().equals("div")) throw new FHIRException("Error in template: Root element is not 'div'"); @@ -114,13 +132,15 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering } @Override - public String renderForLiquid(Base base) throws FHIRException { + public String renderForLiquid(Object appContext, Base base) throws FHIRException { try { if (base instanceof Element) { base = context.getParser().parseType((Element) base); } - XhtmlNode x = new XhtmlNode(NodeType.Element); - if (base instanceof DataType) { + XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); + if (base instanceof Reference) { + renderReference(((LiquidRendererContxt) appContext).getResource(), x, (Reference) base); + } else if (base instanceof DataType) { render(x, (DataType) base); } else { x.tx(base.toString()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java index 7521c4107..f502dccba 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/LiquidEngine.java @@ -60,7 +60,7 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class LiquidEngine implements IEvaluationContext { public interface ILiquidRenderingSupport { - String renderForLiquid(Base i) throws FHIRException; + String renderForLiquid(Object appContext, Base i) throws FHIRException; } public interface ILiquidEngineIncludeResolver { @@ -165,7 +165,7 @@ public class LiquidEngine implements IEvaluationContext { boolean first = true; for (Base i : items) { if (first) first = false; else b.append(", "); - String s = renderingSupport != null ? renderingSupport.renderForLiquid(i) : null; + String s = renderingSupport != null ? renderingSupport.renderForLiquid(ctxt.externalContext, i) : null; b.append(s != null ? s : engine.convertToString(i)); } }