diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/wrapper/ResourceWrapperR4.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/wrapper/ResourceWrapperR4.java new file mode 100644 index 000000000..573f66119 --- /dev/null +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/wrapper/ResourceWrapperR4.java @@ -0,0 +1,239 @@ +package org.hl7.fhir.convertors.wrapper; + +import java.util.Collection; +import java.util.Locale; + +import org.hl7.fhir.r4.model.Base; +import org.hl7.fhir.r4.model.DomainResource; +import org.hl7.fhir.r4.model.ElementDefinition; +import org.hl7.fhir.r4.model.Enumeration; +import org.hl7.fhir.r4.model.Narrative; +import org.hl7.fhir.r4.model.Property; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.utilities.DebugUtilities; +import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; + +/** + * This class is used to walk through the resources when rendering, whether + * the resource is a native resource or loaded by the element model + */ +public class ResourceWrapperR4 extends ResourceWrapper { + + protected Base element; + + ResourceWrapperR4() { + super(); + } + + private ResourceWrapper makeChild(String name, int index, ElementKind kind, Base element) { + ResourceWrapperR4 self = new ResourceWrapperR4(); + self.contextUtils = this.contextUtils; + self.parent = this; + self.name = name; + self.index = index; + self.kind = kind; + self.element = element; + return self; + } + + public String fhirVersion() { + return "4.0.1"; + } + + public String fhirType() { + if (kind == ElementKind.BackboneElement) { + return basePath(); + } else { + return element.fhirType(); + } + } + + public boolean isPrimitive() { + return element.isPrimitive(); + } + + public boolean hasPrimitiveValue() { + return element.hasPrimitiveValue(); + } + + public String primitiveValue() { + return element.primitiveValue(); + } + + protected void loadTheChildren() { + for (Property p : element.children()) { + String name = p.getName(); + int i = 0; + for (Base v : p.getValues()) { + loadElementChild(p, name, i, v); + i++; + } + } + } + + private void loadElementChild(Property p, String name, int i, Base v) { + ElementKind kind = determineModelKind(p, v); + int index = p.isList() ? i : -1; + ElementDefinition ed = null; + children.add(makeChild(name, index, kind, v)); + } + + private ElementKind determineModelKind(Property p, Base v) { + if ("DataRequirement".equals(v.fhirType())) { + DebugUtilities.breakpoint(); + } + if (v.isPrimitive()) { + return ElementKind.PrimitiveType; + } else if (contextUtils.isDatatype(v.fhirType())) { + return ElementKind.DataType; + } else if (!v.isResource()) { + return ElementKind.BackboneElement; + } else if (parent == null) { + return ElementKind.IndependentResource; + } else if ("Bundle.entry".equals(fhirType()) && "resource".equals(p.getName())) { + return ElementKind.BundleEntry; + } else if ("Bundle".equals(fhirType()) && "outcome".equals(p.getName())) { + return ElementKind.InlineResource; + } else if ("Bundle".equals(fhirType()) && "issues".equals(p.getName())) { + return ElementKind.InlineResource; + } else if (isResource() && "contained".equals(p.getName())) { + return ElementKind.ContainedResource; + } else { + return ElementKind.InlineResource; + } + } + + public boolean isResource() { + return element.isResource(); + } + + public boolean canHaveNarrative() { + if (!isResource()) { + return false; + } + return element instanceof DomainResource; + } + + public XhtmlNode getNarrative() { + if (!canHaveNarrative()) { + return null; + } + ResourceWrapper text = child("text"); + if (text == null) { + return null; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return null; + } + return ((ResourceWrapperR4) div).element.getXhtml(); + } + + public boolean hasNarrative() { + if (!canHaveNarrative()) { + return false; + } + ResourceWrapper text = child("text"); + if (text == null) { + return false; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return false; + } + return ((ResourceWrapperR4) div).element.getXhtml() != null; + } + + public void setNarrative(XhtmlNode x, String status, boolean multiLangMode, Locale locale, boolean isPretty) { + if (element instanceof DomainResource) { + DomainResource r = (DomainResource) element; + r.getText().setUserData("renderer.generated", true); + if (!r.hasText() || !r.getText().hasDiv()) { + r.setText(new Narrative()); + r.getText().setStatusAsString(status); + } + if (multiLangMode) { + if (!r.getText().hasDiv()) { + XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); + div.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + r.getText().setDiv(div); + } else { + r.getText().getDiv().getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang")); + } + markLanguage(x, locale); + r.getText().getDiv().getChildNodes().add(x); + } else { + if (!x.hasAttribute("xmlns")) + x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + if (r.hasLanguage()) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", r.getLanguage()); + x.setAttribute("xml:lang", r.getLanguage()); + } + r.getText().setDiv(x); + } + } else { + throw new Error("Cannot call setNarrative on a "+element.fhirType()); + } + } + + public void markLanguage(XhtmlNode x, Locale locale) { + x.setAttribute("lang", locale.toString()); + x.setAttribute("xml:lang", locale.toString()); + x.addTag(0, "hr"); + x.addTag(0, "p").b().tx(locale.getDisplayName()); + x.addTag(0, "hr"); + } + + + public String getId() { + return element.getIdBase(); + } + + @Override + public String toString() { + return name + (index == -1 ? "" : "["+index+"]")+": "+fhirType()+" ("+kind+"/"+path()+"): native = "+element.fhirType()+" -> "+element.toString(); + } + + public org.hl7.fhir.r5.model.Resource getResourceNative() { + return null; + } + + public boolean hasFormatComment() { + return element.hasFormatComment(); + } + + public Collection getFormatCommentsPre() { + return element.getFormatCommentsPre(); + } + + public XhtmlNode getXhtml() { + return element.getXhtml(); + } + + public org.hl7.fhir.r5.model.Base getBase() { + return null; + } + + public boolean isDirect() { + return true; + } + + public String getWebPath() { + if (isResource()) { + return ((Resource) element).getUserString("path"); + } else { + return null; + } + } + + public String getCodeSystemUri() { + if (element instanceof Enumeration) { + return ((Enumeration) element).getSystem(); + } + return null; + } + +} \ No newline at end of file diff --git a/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/wrapper/ResourceWrapperR4B.java b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/wrapper/ResourceWrapperR4B.java new file mode 100644 index 000000000..a6f474f4c --- /dev/null +++ b/org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/wrapper/ResourceWrapperR4B.java @@ -0,0 +1,235 @@ +package org.hl7.fhir.convertors.wrapper; + +import java.util.Collection; +import java.util.Locale; + +import org.hl7.fhir.r4b.model.Base; +import org.hl7.fhir.r4b.model.DomainResource; +import org.hl7.fhir.r4b.model.ElementDefinition; +import org.hl7.fhir.r4b.model.Enumeration; +import org.hl7.fhir.r4b.model.Narrative; +import org.hl7.fhir.r4b.model.Property; +import org.hl7.fhir.r4b.model.Resource; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; + +/** + * This class is used to walk through the resources when rendering, whether + * the resource is a native resource or loaded by the element model + */ +public class ResourceWrapperR4B extends ResourceWrapper { + + protected Base element; + + ResourceWrapperR4B() { + super(); + } + + private ResourceWrapper makeChild(String name, int index, ElementKind kind, Base element) { + ResourceWrapperR4B self = new ResourceWrapperR4B(); + self.contextUtils = this.contextUtils; + self.parent = this; + self.name = name; + self.index = index; + self.kind = kind; + self.element = element; + return self; + } + + public String fhirVersion() { + return "4.0.1"; + } + + public String fhirType() { + if (kind == ElementKind.BackboneElement) { + return basePath(); + } else { + return element.fhirType(); + } + } + + public boolean isPrimitive() { + return element.isPrimitive(); + } + + public boolean hasPrimitiveValue() { + return element.hasPrimitiveValue(); + } + + public String primitiveValue() { + return element.primitiveValue(); + } + + protected void loadTheChildren() { + for (Property p : element.children()) { + String name = p.getName(); + int i = 0; + for (Base v : p.getValues()) { + loadElementChild(p, name, i, v); + i++; + } + } + } + + private void loadElementChild(Property p, String name, int i, Base v) { + ElementKind kind = determineModelKind(p, v); + int index = p.isList() ? i : -1; + ElementDefinition ed = null; + children.add(makeChild(name, index, kind, v)); + } + + private ElementKind determineModelKind(Property p, Base v) { + if (v.isPrimitive()) { + return ElementKind.PrimitiveType; + } else if (contextUtils.isDatatype(v.fhirType())) { + return ElementKind.DataType; + } else if (!v.isResource()) { + return ElementKind.BackboneElement; + } else if (parent == null) { + return ElementKind.IndependentResource; + } else if ("Bundle.entry".equals(fhirType()) && "resource".equals(p.getName())) { + return ElementKind.BundleEntry; + } else if ("Bundle".equals(fhirType()) && "outcome".equals(p.getName())) { + return ElementKind.InlineResource; + } else if ("Bundle".equals(fhirType()) && "issues".equals(p.getName())) { + return ElementKind.InlineResource; + } else if (isResource() && "contained".equals(p.getName())) { + return ElementKind.ContainedResource; + } else { + return ElementKind.InlineResource; + } + } + + public boolean isResource() { + return element.isResource(); + } + + public boolean canHaveNarrative() { + if (!isResource()) { + return false; + } + return element instanceof DomainResource; + } + + public XhtmlNode getNarrative() { + if (!canHaveNarrative()) { + return null; + } + ResourceWrapper text = child("text"); + if (text == null) { + return null; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return null; + } + return ((ResourceWrapperR4B) div).element.getXhtml(); + } + + public boolean hasNarrative() { + if (!canHaveNarrative()) { + return false; + } + ResourceWrapper text = child("text"); + if (text == null) { + return false; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return false; + } + return ((ResourceWrapperR4B) div).element.getXhtml() != null; + } + + public void setNarrative(XhtmlNode x, String status, boolean multiLangMode, Locale locale, boolean isPretty) { + if (element instanceof DomainResource) { + DomainResource r = (DomainResource) element; + r.getText().setUserData("renderer.generated", true); + if (!r.hasText() || !r.getText().hasDiv()) { + r.setText(new Narrative()); + r.getText().setStatusAsString(status); + } + if (multiLangMode) { + if (!r.getText().hasDiv()) { + XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); + div.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + r.getText().setDiv(div); + } else { + r.getText().getDiv().getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang")); + } + markLanguage(x, locale); + r.getText().getDiv().getChildNodes().add(x); + } else { + if (!x.hasAttribute("xmlns")) + x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + if (r.hasLanguage()) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", r.getLanguage()); + x.setAttribute("xml:lang", r.getLanguage()); + } + r.getText().setDiv(x); + } + } else { + throw new Error("Cannot call setNarrative on a "+element.fhirType()); + } + } + + public void markLanguage(XhtmlNode x, Locale locale) { + x.setAttribute("lang", locale.toString()); + x.setAttribute("xml:lang", locale.toString()); + x.addTag(0, "hr"); + x.addTag(0, "p").b().tx(locale.getDisplayName()); + x.addTag(0, "hr"); + } + + + public String getId() { + return element.getIdBase(); + } + + @Override + public String toString() { + return name + (index == -1 ? "" : "["+index+"]")+": "+fhirType()+" ("+kind+"/"+path()+"): native = "+element.fhirType()+" -> "+element.toString(); + } + + public org.hl7.fhir.r5.model.Resource getResourceNative() { + return null; + } + + public boolean hasFormatComment() { + return element.hasFormatComment(); + } + + public Collection getFormatCommentsPre() { + return element.getFormatCommentsPre(); + } + + public XhtmlNode getXhtml() { + return element.getXhtml(); + } + + public org.hl7.fhir.r5.model.Base getBase() { + return null; + } + + public boolean isDirect() { + return true; + } + + public String getWebPath() { + if (isResource()) { + return ((Resource) element).getUserString("path"); + } else { + return null; + } + } + + public String getCodeSystemUri() { + if (element instanceof Enumeration) { + return ((Enumeration) element).getSystem(); + } + return null; + } + +} \ No newline at end of file diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BinaryRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BinaryRenderer.java index 4552c0773..c570a09d7 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BinaryRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BinaryRenderer.java @@ -13,6 +13,13 @@ import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlComposer; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class BinaryRenderer { private String folder; diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BundleRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BundleRenderer.java index 83785c367..187d3aae6 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BundleRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/BundleRenderer.java @@ -30,6 +30,13 @@ import org.hl7.fhir.r4b.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class BundleRenderer extends ResourceRenderer { public BundleRenderer(RenderingContext context, ResourceContext rcontext) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CapabilityStatementRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CapabilityStatementRenderer.java index 629119880..068930527 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CapabilityStatementRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CapabilityStatementRenderer.java @@ -21,6 +21,13 @@ import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class CapabilityStatementRenderer extends ResourceRenderer { public CapabilityStatementRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CodeSystemRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CodeSystemRenderer.java index f4ddeb415..5559c2fe5 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CodeSystemRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CodeSystemRenderer.java @@ -29,6 +29,13 @@ import org.hl7.fhir.utilities.LoincLinker; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class CodeSystemRenderer extends TerminologyRenderer { public CodeSystemRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CompartmentDefinitionRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CompartmentDefinitionRenderer.java index be23c2963..bc9e468ae 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CompartmentDefinitionRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/CompartmentDefinitionRenderer.java @@ -17,6 +17,13 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class CompartmentDefinitionRenderer extends ResourceRenderer { public CompartmentDefinitionRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ConceptMapRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ConceptMapRenderer.java index 1f4274afb..bbce8ec69 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ConceptMapRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ConceptMapRenderer.java @@ -25,6 +25,13 @@ import org.hl7.fhir.r4b.utils.ToolingExtensions; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ConceptMapRenderer extends TerminologyRenderer { public ConceptMapRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DataRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DataRenderer.java index 0f90dace7..f6687d733 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DataRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DataRenderer.java @@ -96,6 +96,13 @@ import ca.uhn.fhir.model.api.TemporalPrecisionEnum; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class DataRenderer extends Renderer { // -- 1. context -------------------------------------------------------------- diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DiagnosticReportRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DiagnosticReportRenderer.java index 2b9120bd6..0ee658364 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DiagnosticReportRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/DiagnosticReportRenderer.java @@ -24,6 +24,13 @@ import org.hl7.fhir.r4b.utils.EOperationOutcome; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class DiagnosticReportRenderer extends ResourceRenderer { public class ObservationNode { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/EncounterRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/EncounterRenderer.java index 1e5b1bb1a..159b155f9 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/EncounterRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/EncounterRenderer.java @@ -9,6 +9,13 @@ import org.hl7.fhir.r4b.renderers.utils.RenderingContext; import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class EncounterRenderer extends ResourceRenderer { public EncounterRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ImplementationGuideRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ImplementationGuideRenderer.java index ba24504fe..5a6481f7d 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ImplementationGuideRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ImplementationGuideRenderer.java @@ -13,6 +13,13 @@ import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ImplementationGuideRenderer extends ResourceRenderer { public ImplementationGuideRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LibraryRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LibraryRenderer.java index 0a871b5d1..c881a4b49 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LibraryRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LibraryRenderer.java @@ -31,6 +31,13 @@ import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceWithReference; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class LibraryRenderer extends ResourceRenderer { private static final int DATA_IMG_SIZE_CUTOFF = 4000; diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LiquidRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LiquidRenderer.java index 75b4cfc93..33de62fe6 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LiquidRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/LiquidRenderer.java @@ -18,6 +18,13 @@ import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class LiquidRenderer extends ResourceRenderer { private String liquidTemplate; diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ListRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ListRenderer.java index 5f9ec1d6c..3ba4884ea 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ListRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ListRenderer.java @@ -19,6 +19,13 @@ import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceWithReference; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ListRenderer extends ResourceRenderer { public ListRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/NamingSystemRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/NamingSystemRenderer.java index aea6d638b..8f78b364b 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/NamingSystemRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/NamingSystemRenderer.java @@ -19,6 +19,13 @@ import org.hl7.fhir.r4b.utils.ToolingExtensions; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class NamingSystemRenderer extends ResourceRenderer { public NamingSystemRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationDefinitionRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationDefinitionRenderer.java index d17b89208..c08e5b0a8 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationDefinitionRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationDefinitionRenderer.java @@ -20,6 +20,13 @@ import org.hl7.fhir.r4b.utils.ToolingExtensions; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class OperationDefinitionRenderer extends TerminologyRenderer { public OperationDefinitionRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationOutcomeRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationOutcomeRenderer.java index 3e19bb360..1c8f574f9 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationOutcomeRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/OperationOutcomeRenderer.java @@ -20,6 +20,13 @@ import org.hl7.fhir.r4b.utils.ToolingExtensions; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class OperationOutcomeRenderer extends ResourceRenderer { public OperationOutcomeRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ParametersRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ParametersRenderer.java index 90a113069..e4a6287f0 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ParametersRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ParametersRenderer.java @@ -29,6 +29,13 @@ import org.hl7.fhir.r4b.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ParametersRenderer extends ResourceRenderer { public ParametersRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/PatientRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/PatientRenderer.java index d3c7c17d1..cf72137ff 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/PatientRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/PatientRenderer.java @@ -19,6 +19,13 @@ import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.PropertyWrapper; import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class PatientRenderer extends ResourceRenderer { public PatientRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProfileDrivenRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProfileDrivenRenderer.java index bdab8d151..d749667cd 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProfileDrivenRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProfileDrivenRenderer.java @@ -83,6 +83,13 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xml.XMLUtil; import org.w3c.dom.Element; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ProfileDrivenRenderer extends ResourceRenderer { private Set containedIds = new HashSet<>(); diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProvenanceRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProvenanceRenderer.java index edf2b9e2b..22c716eed 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProvenanceRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ProvenanceRenderer.java @@ -14,6 +14,13 @@ import org.hl7.fhir.r4b.renderers.utils.RenderingContext; import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ProvenanceRenderer extends ResourceRenderer { public ProvenanceRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireRenderer.java index b5a0488cd..3c06716ea 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireRenderer.java @@ -40,6 +40,13 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; import javax.annotation.Nonnull; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class QuestionnaireRenderer extends TerminologyRenderer { public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = "http://hl7.org/fhir/4.0/StructureDefinition/extension-Questionnaire.item.type"; diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireResponseRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireResponseRenderer.java index c20e65358..ac4998af2 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireResponseRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/QuestionnaireResponseRenderer.java @@ -39,6 +39,13 @@ import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class QuestionnaireResponseRenderer extends ResourceRenderer { public QuestionnaireResponseRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/Renderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/Renderer.java index 94b477c5c..ca7a5b8dd 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/Renderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/Renderer.java @@ -10,28 +10,10 @@ import org.hl7.fhir.utilities.validation.ValidationOptions; /** * Rendering framework: * - * * boolean render(DomainResource) : produce an HTML representation suitable - * for runtime / documentation, and insert it into the resource. Return true of - * any extensions encountered * boolean render(XhtmlNode, Resource: produce an - * HTML representation, and fill out the provided node with it. Return true of - * any extensions encountered * XhtmlNode build(DomainResource): same as - * render(DomainResource) but also return the XHtmlNode + * See R5 rendering framework to render R4B resources * - * * String display(Base) : produce a plan text concise representation that - * serves to describe the resource * void display(XhtmlNode, Base) : produce a - * plan text concise representation that serves to describe the resource - * - * * void describe(XhtmlNode, Resource) : produce a short summary of the - * resource with key details presented (potentially more verbose than display, - * but still suitable for a single line) - * - * if not specific code for rendering a resource has been provided, and there's - * no liquid script to guide it, a generic rendering based onthe profile will be - * performed - * - * @author graha - * */ +@Deprecated public class Renderer { protected RenderingContext context; diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/RendererFactory.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/RendererFactory.java index b9a5edaa1..0a2d42586 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/RendererFactory.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/RendererFactory.java @@ -6,6 +6,13 @@ import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r4b.renderers.utils.RenderingContext; import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceContext; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class RendererFactory { public static ResourceRenderer factory(String resourceName, RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ResourceRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ResourceRenderer.java index af255e217..21ca12d19 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ResourceRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ResourceRenderer.java @@ -36,6 +36,13 @@ import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public abstract class ResourceRenderer extends DataRenderer { protected ResourceContext rcontext; diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/SearchParameterRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/SearchParameterRenderer.java index b645a6642..eddc6364d 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/SearchParameterRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/SearchParameterRenderer.java @@ -26,6 +26,13 @@ import org.hl7.fhir.r4b.utils.ToolingExtensions; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class SearchParameterRenderer extends TerminologyRenderer { public SearchParameterRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/StructureDefinitionRenderer.java index d64112584..5487e26ec 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/StructureDefinitionRenderer.java @@ -13,6 +13,13 @@ import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r4b.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class StructureDefinitionRenderer extends ResourceRenderer { public StructureDefinitionRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/TerminologyRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/TerminologyRenderer.java index 1ef2d1448..28be20a9e 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/TerminologyRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/TerminologyRenderer.java @@ -32,6 +32,13 @@ import org.hl7.fhir.utilities.CanonicalPair; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public abstract class TerminologyRenderer extends ResourceRenderer { public TerminologyRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ValueSetRenderer.java b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ValueSetRenderer.java index e3ed01452..f35d90bae 100644 --- a/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.r4b/src/main/java/org/hl7/fhir/r4b/renderers/ValueSetRenderer.java @@ -54,6 +54,13 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +/** + * Rendering framework: + * + * See R5 rendering framework to render R4B resources + * + */ +@Deprecated public class ValueSetRenderer extends TerminologyRenderer { public ValueSetRenderer(RenderingContext context) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/StructureDefinitionComparer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/StructureDefinitionComparer.java index 1356ffae7..494be7d56 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/StructureDefinitionComparer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/comparison/StructureDefinitionComparer.java @@ -35,6 +35,7 @@ import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus; import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; @@ -1259,13 +1260,13 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple public XhtmlNode renderUnion(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException { StructureDefinitionRenderer sdr = new StructureDefinitionRenderer(new RenderingContext(utilsLeft.getContext(), null, utilsLeft.getTerminologyServiceOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER).setPkp(this)); - return sdr.generateTable(corePath, comp.union, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "u"); + return sdr.generateTable(new RenderingStatus(), corePath, comp.union, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "u", null); } public XhtmlNode renderIntersection(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException { StructureDefinitionRenderer sdr = new StructureDefinitionRenderer(new RenderingContext(utilsLeft.getContext(), null, utilsLeft.getTerminologyServiceOptions(), corePath, prefix, null, ResourceRendererMode.TECHNICAL, GenerationRules.IG_PUBLISHER).setPkp(this)); - return sdr.generateTable(corePath, comp.intersection, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "i"); + return sdr.generateTable(new RenderingStatus(), corePath, comp.intersection, false, prefix, false, id, true, corePath, prefix, false, true, null, false, sdr.getContext(), "i", null); } private void genElementComp(String defPath, String anchorPrefix, HierarchicalTableGenerator gen, List rows, StructuralMatch combined, String corePath, String prefix, Row slicingRow, boolean root) throws IOException { @@ -1334,12 +1335,12 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple nc = sdrRight.genElementNameCell(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, false, ext, used , ref, sName, null); } if (combined.hasLeft()) { - frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList()), leftColor); + frame(sdrLeft.genElementCells(new RenderingStatus(), gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList(), null), leftColor); } else { frame(spacers(row, 4, gen), leftColor); } if (combined.hasRight()) { - frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList()), rightColor); + frame(sdrRight.genElementCells(new RenderingStatus(), gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0, defPath, anchorPrefix, new ArrayList(), null), rightColor); } else { frame(spacers(row, 4, gen), rightColor); } @@ -1478,6 +1479,12 @@ public boolean prependLinks() { public String getLinkForUrl(String corePath, String s) { return null; } + +@Override +public String getCanonicalForDefaultContext() { + // TODO Auto-generated method stub + return null; +} } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileKnowledgeProvider.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileKnowledgeProvider.java index c8f59bcd6..b578764bd 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileKnowledgeProvider.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/profile/ProfileKnowledgeProvider.java @@ -16,4 +16,5 @@ public interface ProfileKnowledgeProvider { String getLinkForProfile(StructureDefinition profile, String url); boolean prependLinks(); String getLinkForUrl(String corePath, String s); + String getCanonicalForDefaultContext(); } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index 26fecdae6..ac2dfbee0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -383,7 +383,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte String url = r.getUrl(); if (!allowLoadingDuplicates && hasResourceVersion(r.getType(), url, r.getVersion()) && !packageInfo.isHTO()) { - // spcial workaround for known problems with existing packages + // special workaround for known problems with existing packages if (Utilities.existsInList(url, "http://hl7.org/fhir/SearchParameter/example")) { return; } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java index 4efb7c718..02890a037 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/ContextUtilities.java @@ -464,5 +464,15 @@ public class ContextUtilities implements ProfileKnowledgeProvider { return false; } + public IWorkerContext getWorker() { + return context; + } + + @Override + public String getCanonicalForDefaultContext() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java index 7fda6798c..e4e07a849 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/JsonParser.java @@ -63,6 +63,7 @@ import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.DebugUtilities; import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; @@ -87,6 +88,7 @@ public class JsonParser extends ParserBase { private boolean allowComments; private Element baseElement; + private boolean markedXhtml; public JsonParser(IWorkerContext context, ProfileUtilities utilities) { super(context, utilities); @@ -766,6 +768,7 @@ public class JsonParser extends ParserBase { e.populatePaths(null); } + markedXhtml = false; OutputStreamWriter osw = new OutputStreamWriter(stream, "UTF-8"); if (style == OutputStyle.CANONICAL) { json = new JsonCreatorCanonical(osw); @@ -779,7 +782,7 @@ public class JsonParser extends ParserBase { prop("resourceType", e.getType(), null); Set done = new HashSet(); for (Element child : e.getChildren()) { - compose(e.getName(), e, done, child, ""); + compose(e.getName(), e, done, child); } json.endObject(); json.finish(); @@ -804,28 +807,28 @@ public class JsonParser extends ParserBase { prop("resourceType", e.getType(), linkResolver == null ? null : linkResolver.resolveProperty(e.getProperty())); Set done = new HashSet(); for (Element child : e.getChildren()) { - compose(e.getName(), e, done, child, ""); + compose(e.getName(), e, done, child); } json.endObject(); json.finish(); } - private void compose(String path, Element e, Set done, Element child, String tgtPath) throws IOException { + private void compose(String path, Element e, Set done, Element child) throws IOException { checkComposeComments(child); if (wantCompose(path, child)) { boolean isList = child.hasElementProperty() ? child.getElementProperty().isList() : child.getProperty().isList(); if (!isList) {// for specials, ignore the cardinality of the stated type - compose(path, child, tgtPath); + compose(path, child); } else if (!done.contains(child.getName())) { done.add(child.getName()); List list = e.getChildrenByName(child.getName()); - composeList(path, list, tgtPath); + composeList(path, list); } } } - private void composeList(String path, List list, String tgtPath) throws IOException { + private void composeList(String path, List list) throws IOException { // there will be at least one element String name = list.get(0).getName(); boolean complex = true; @@ -873,15 +876,7 @@ public class JsonParser extends ParserBase { } Set done = new HashSet(); for (Element child : item.getChildren()) { - String tp = tgtPath; - if (child.getSpecial() == SpecialElement.BUNDLE_ENTRY) { - if (Utilities.noString(tp)) { - tp = "Bnd."+i+"."; - } else { - tp = tgtPath+i+"."; - } - } - compose(path+"."+name+"[]", item, done, child, tp); + compose(path+"."+name+"[]", item, done, child); } close(); } else { @@ -914,14 +909,15 @@ public class JsonParser extends ParserBase { json.value(item.getValue()); } - private void compose(String path, Element element, String tgtPath) throws IOException { + private void compose(String path, Element element) throws IOException { String name = element.getName(); if (element.isPrimitive() || isPrimitive(element.getType())) { if (element.hasValue()) primitiveValue(name, element); name = "_"+name; - if (element.getType().equals("xhtml")) - json.anchor(tgtPath+"end-xhtml"); + if (!markedXhtml && element.getType().equals("xhtml")) + json.anchor("end-xhtml"); + markedXhtml = true; } if (element.hasChildren()) { open(name, linkResolver == null ? null : linkResolver.resolveProperty(element.getProperty())); @@ -936,7 +932,7 @@ public class JsonParser extends ParserBase { } Set done = new HashSet(); for (Element child : element.getChildren()) { - compose(path+"."+element.getName(), element, done, child, tgtPath); + compose(path+"."+element.getName(), element, done, child); } close(); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java index f55e6d51d..410c225d6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/XmlParser.java @@ -100,7 +100,7 @@ public class XmlParser extends ParserBase { } private String schemaPath; - private int bundleEntryCounter = 0; + private boolean markedXhtml; public String getSchemaPath() { return schemaPath; @@ -724,6 +724,7 @@ public class XmlParser extends ParserBase { @Override public void compose(Element e, OutputStream stream, OutputStyle style, String base) throws IOException, FHIRException { + markedXhtml = false; XMLWriter xml = new XMLWriter(stream, "UTF-8"); xml.setSortAttributes(false); xml.setPretty(style == OutputStyle.PRETTY); @@ -738,7 +739,7 @@ public class XmlParser extends ParserBase { if (hasTypeAttr(e)) xml.namespace("http://www.w3.org/2001/XMLSchema-instance", "xsi"); addNamespaces(xml, e); - composeElement(xml, e, e.getType(), true, ""); + composeElement(xml, e, e.getType(), true); xml.end(); } @@ -791,16 +792,17 @@ public class XmlParser extends ParserBase { if (e.getPath() == null) { e.populatePaths(null); } + markedXhtml = false; xml.start(); xml.setDefaultNamespace(e.getProperty().getXmlNamespace()); if (schemaPath != null) { xml.setSchemaLocation(FormatUtilities.FHIR_NS, Utilities.pathURL(schemaPath, e.fhirType()+".xsd")); } - composeElement(xml, e, e.getType(), true, ""); + composeElement(xml, e, e.getType(), true); xml.end(); } - private void composeElement(IXMLWriter xml, Element element, String elementName, boolean root, String tgtPath) throws IOException, FHIRException { + private void composeElement(IXMLWriter xml, Element element, String elementName, boolean root) throws IOException, FHIRException { if (showDecorations) { @SuppressWarnings("unchecked") List decorations = (List) element.getUserData("fhir.decorations"); @@ -834,7 +836,10 @@ public class XmlParser extends ParserBase { new CDANarrativeFormat().convert(xml, new XhtmlParser().parseFragment(rawXhtml)); } else { xml.escapedText(rawXhtml); - xml.anchor(tgtPath+"end-xhtml"); + if (!markedXhtml) { + xml.anchor("end-xhtml"); + markedXhtml = true; + } } } else if (isText(element.getProperty())) { if (linkResolver != null) @@ -858,7 +863,7 @@ public class XmlParser extends ParserBase { } } for (Element child : element.getChildren()) - composeElement(xml, child, child.getName(), false, tgtPath); + composeElement(xml, child, child.getName(), false); xml.exit(element.getProperty().getXmlNamespace(),elementName); } else xml.element(elementName); @@ -910,16 +915,7 @@ public class XmlParser extends ParserBase { xml.link(linkResolver.resolveProperty(element.getProperty())); xml.text(child.getValue()); } else if (!isAttr(child.getProperty())) { - String tp = tgtPath; - if (child.getSpecial() == SpecialElement.BUNDLE_ENTRY) { - bundleEntryCounter ++; - if (Utilities.noString(tp)) { - tp = "Bnd."+bundleEntryCounter+"."; - } else { - tp = tgtPath+bundleEntryCounter+"."; - } - } - composeElement(xml, child, child.getName(), false, tp); + composeElement(xml, child, child.getName(), false); } } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Extension.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Extension.java index 7359ecb68..636265931 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Extension.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/model/Extension.java @@ -70,7 +70,7 @@ public class Extension extends BaseExtension implements IBaseExtension entries = b.children("entry"); - if ("document".equals(b.get("type").primitiveValue())) { - if (entries.isEmpty() || (entries.get(0).has("resource") && !"Composition".equals(entries.get(0).get("resource").fhirType()))) - throw new FHIRException(context.formatPhrase(RenderingContext.BUND_REND_INVALID_DOC, b.getId(), entries.get(0).get("resource").fhirType()+"')")); - return renderDocument(x, b, entries); - } else if ("collection".equals(b.get("type").primitiveValue()) && allEntriesAreHistoryProvenance(entries)) { + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper b) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if ("ex-fhir-document-bundle".equals(b.getId())) { + DebugUtilities.breakpoint(); + } + List entries = b.children("entry"); + if ("collection".equals(b.primitiveValue("type")) && allEntriesAreHistoryProvenance(entries)) { // nothing } else { - XhtmlNode root = new XhtmlNode(NodeType.Element, "div"); - root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.get("type").primitiveValue())); - int i = 0; - for (BaseWrapper be : entries) { - i++; - if (be.has("fullUrl")) { - root.an(makeInternalBundleLink(be.get("fullUrl").primitiveValue())); - } - if (be.has("resource")) { - if (be.getChildByName("resource").getValues().get(0).has("id")) { - root.an(be.get("resource").fhirType() + "_" + be.getChildByName("resource").getValues().get(0).get("id").primitiveValue()); - root.an("hc"+be.get("resource").fhirType() + "_" + be.getChildByName("resource").getValues().get(0).get("id").primitiveValue()); - } else { - String id = makeIdFromBundleEntry(be.get("fullUrl").primitiveValue()); - root.an(be.get("resource").fhirType() + "_" + id); - root.an("hc"+be.get("resource").fhirType() + "_" + id); - } + int start = 0; + XhtmlNode root = x; + if ("document".equals(b.primitiveValue("type"))) { + if (entries.isEmpty() || (entries.get(0).has("resource") && !"Composition".equals(entries.get(0).child("resource").fhirType()))) + throw new FHIRException(context.formatPhrase(RenderingContext.BUND_REND_INVALID_DOC, b.getId(), entries.get(0).child("resource").fhirType()+"')")); + renderDocument(status, root, b, entries); + if (!context.isTechnicalMode()) { + return; } + start = 1; root.hr(); - if (be.has("fullUrl")) { - root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.get("fullUrl").primitiveValue())); - } else { - root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i))); - } -// if (be.hasRequest()) -// renderRequest(root, be.getRequest()); -// if (be.hasSearch()) -// renderSearch(root, be.getSearch()); -// if (be.hasResponse()) -// renderResponse(root, be.getResponse()); - if (be.has("resource")) { - root.para().addText(formatPhrase(RenderingContext.BUNDLE_RESOURCE, be.get("resource").fhirType())); - ResourceWrapper rw = be.getChildByName("resource").getAsResource(); - XhtmlNode xn = rw.getNarrative(); - if (xn == null || xn.isEmpty()) { - ResourceRenderer rr = RendererFactory.factory(rw, context); - try { - rr.setRcontext(new ResourceContext(rcontext, rw)); - xn = rr.render(rw); - } catch (Exception e) { - xn = new XhtmlNode(); - xn.para().b().tx(context.formatPhrase(RenderingContext.BUNDLE_REV_EXCP, e.getMessage()) + " "); + root.h2().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOCUMENT_CONTENTS)); + } else { + renderResourceTechDetails(b, x); + root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.primitiveValue("type"))); + } + int i = 0; + for (ResourceWrapper be : entries) { + i++; + if (i >= start) { + if (be.has("fullUrl")) { + root.an(context.prefixAnchor(makeInternalBundleLink(be.primitiveValue("fullUrl")))); + } + if (be.has("resource")) { + if (be.child("resource").has("id")) { + root.an(context.prefixAnchor(be.child("resource").fhirType() + "_" + be.child("resource").primitiveValue("id"))); + root.an(context.prefixAnchor("hc"+be.child("resource").fhirType() + "_" + be.child("resource").primitiveValue("id"))); + } else { + String id = makeIdFromBundleEntry(be.primitiveValue("fullUrl")); + root.an(context.prefixAnchor(be.child("resource").fhirType() + "_" + id)); + root.an(context.prefixAnchor("hc"+be.child("resource").fhirType() + "_" + id)); } } - root.blockquote().para().addChildren(xn); + root.hr(); + if (be.has("fullUrl")) { + root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.primitiveValue("fullUrl"))); + } else { + root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i))); + } + if (be.has("search")) { + renderSearch(x, be.child("search")); + } + // if (be.hasRequest()) + // renderRequest(root, be.getRequest()); + // if (be.hasSearch()) + // renderSearch(root, be.getSearch()); + // if (be.hasResponse()) + // renderResponse(root, be.getResponse()); + if (be.has("resource")) { + ResourceWrapper r = be.child("resource"); + root.para().addText(formatPhrase(RenderingContext.BUNDLE_RESOURCE, r.fhirType())); + XhtmlNode xn = r.getNarrative(); + if (xn == null || xn.isEmpty()) { + ResourceRenderer rr = RendererFactory.factory(r, context); + try { + xn = new XhtmlNode(NodeType.Element, "div"); + rr.buildNarrative(new RenderingStatus(), xn, r); + } catch (Exception e) { + xn = new XhtmlNode(); + xn.para().b().tx(context.formatPhrase(RenderingContext.BUNDLE_REV_EXCP, e.getMessage()) + " "); + } + } + root.blockquote().para().addChildren(xn); + } + if (be.has("request")) { + renderRequest(x, be.child("request")); + } + if (be.has("response")) { + renderResponse(x, be.child("response")); + } } } } - return false; } - - private boolean renderDocument(XhtmlNode x, ResourceWrapper b, List entries) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome { + private void renderDocument(RenderingStatus status, XhtmlNode x, ResourceWrapper b, List entries) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome { // from the spec: // // When the document is presented for human consumption, applications SHOULD present the collated narrative portions in order: // * The subject resource Narrative // * The Composition resource Narrative // * The section.text Narratives - ResourceWrapper comp = (ResourceWrapper) entries.get(0).getChildByName("resource").getAsResource(); - ResourceWrapper subject = resolveReference(entries, comp.get("subject")); + + ResourceWrapper comp = (ResourceWrapper) entries.get(0).child("resource"); + + XhtmlNode sum = renderResourceTechDetails(b, docSection(x, "Document Details"), comp.primitiveValueMN("title", "name")); + if (sum != null) { + XhtmlNode p = sum.para(); + p.startScript("doc"); + renderDataType(status, p.param("status"), comp.child("status")); + renderDataType(status, p.param("date"), comp.child("date")); + renderDataType(status, p.param("author"), comp.child("author")); + renderDataType(status, p.param("subject"), comp.child("subject")); + if (comp.has("encounter")) { + renderDataType(status, p.param("encounter"), comp.child("encounter")); + p.paramValue("has-encounter", "true"); + } else { + p.paramValue("has-encounter", "false"); + } + p.execScript(context.formatMessage(RenderingContext.DOCUMENT_SUMMARY)); + p.closeScript(); + + // status, type, category, subject, encounter, date, author, + x.hr(); + } + + ResourceWrapper subject = resolveReference(entries, comp.child("subject")); + XhtmlNode sec = docSection(x, "Document Subject"); if (subject != null) { if (subject.hasNarrative()) { - x.addChildren(subject.getNarrative()); + sec.addChildren(subject.getNarrative()); } else { - RendererFactory.factory(subject, context, new ResourceContext(rcontext, subject)).render(x, subject); + RendererFactory.factory(subject, context).buildNarrative(status, sec, subject); } } x.hr(); + sec = docSection(x, "Document Content"); if (comp.hasNarrative()) { - x.addChildren(comp.getNarrative()); - x.hr(); + sec.addChildren(comp.getNarrative()); + sec.hr(); } - List sections = comp.children("section"); - for (BaseWrapper section : sections) { - addSection(x, section, 2, false); + List sections = comp.children("section"); + for (ResourceWrapper section : sections) { + addSection(status, sec, section, 2, false); } - return false; } - private void addSection(XhtmlNode x, BaseWrapper section, int level, boolean nested) throws UnsupportedEncodingException, FHIRException, IOException { + private XhtmlNode docSection(XhtmlNode x, String name) { + XhtmlNode div = x.div(); + div.style("border: 1px solid maroon; padding: 10px; background-color: #f2faf9; min-height: 160px;"); + div.para().b().tx(name); + return div; + } + + private void addSection(RenderingStatus status, XhtmlNode x, ResourceWrapper section, int level, boolean nested) throws UnsupportedEncodingException, FHIRException, IOException { if (section.has("title") || section.has("code") || section.has("text") || section.has("section")) { XhtmlNode div = x.div(); if (section.has("title")) { - div.h(level).tx(section.get("title").primitiveValue()); + div.h(level).tx(section.primitiveValue("title")); } else if (section.has("code")) { - renderBase(div.h(level), section.get("code")); + renderDataType(status, div.h(level), section.child("code")); } if (section.has("text")) { - Base narrative = section.get("text"); + ResourceWrapper narrative = section.child("text"); x.addChildren(narrative.getXhtml()); } if (section.has("section")) { - List sections = section.children("section"); - for (BaseWrapper child : sections) { + List sections = section.children("section"); + for (ResourceWrapper child : sections) { if (nested) { - addSection(x.blockquote().para(), child, level+1, true); + addSection(status, x.blockquote().para(), child, level+1, true); } else { - addSection(x, child, level+1, true); + addSection(status, x, child, level+1, true); } } } @@ -179,194 +203,27 @@ public class BundleRenderer extends ResourceRenderer { // children } - private ResourceWrapper resolveReference(List entries, Base base) throws UnsupportedEncodingException, FHIRException, IOException { + private ResourceWrapper resolveReference(List entries, ResourceWrapper base) throws UnsupportedEncodingException, FHIRException, IOException { if (base == null) { return null; } - Property prop = base.getChildByName("reference"); - if (prop.hasValues()) { - String ref = prop.getValues().get(0).primitiveValue(); - if (ref != null) { - for (BaseWrapper entry : entries) { - if (entry.has("fullUrl")) { - String fu = entry.get("fullUrl").primitiveValue(); - if (ref.equals(fu)) { - return (ResourceWrapper) entry.getChildByName("resource").getAsResource(); - } + ResourceWrapper prop = base.child("reference"); + if (prop != null && prop.hasPrimitiveValue()) { + for (ResourceWrapper entry : entries) { + if (entry.has("fullUrl")) { + String fu = entry.primitiveValue("fullUrl"); + if (prop.primitiveValue().equals(fu)) { + return entry.child("resource"); } } } } return null; } - - private boolean renderDocument(XhtmlNode x, Bundle b) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome { - // from the spec: - // - // When the document is presented for human consumption, applications SHOULD present the collated narrative portions in order: - // * The subject resource Narrative - // * The Composition resource Narrative - // * The section.text Narratives - Composition comp = (Composition) b.getEntry().get(0).getResource(); - Resource subject = resolveReference(b, comp.getSubjectFirstRep()); - if (subject != null) { - XhtmlNode nx = (subject instanceof DomainResource) ? ((DomainResource) subject).getText().getDiv() : null; - if (nx != null && !nx.isEmpty()) { - x.addChildren(nx); - } else { - RendererFactory.factory(subject, context).setRcontext(new ResourceContext(rcontext, subject)).render(x, subject); - } - } - x.hr(); - if (!comp.getText().hasDiv()) { - ResourceRenderer rr = RendererFactory.factory(comp, getContext()); - rr.setRcontext(new ResourceContext(rcontext, comp)); - rr.render(comp); - } - if (comp.getText().hasDiv()) { - x.addChildren(comp.getText().getDiv()); - x.hr(); - } - for (SectionComponent section : comp.getSection()) { - addSection(x, section, 2, false, comp); - } - return false; - } - - private Resource resolveReference(Bundle bnd, Reference reference) { - String ref = reference.getReference(); - if (ref == null) { - return null; - } - for (BundleEntryComponent be : bnd.getEntry()) { - if (ref.equals(be.getFullUrl())) { - return be.getResource(); - } - } - return null; - } - - - private void addSection(XhtmlNode x, SectionComponent section, int level, boolean nested, Composition c) throws UnsupportedEncodingException, FHIRException, IOException { - if (section.hasTitle() || section.hasCode() || section.hasText() || section.hasSection()) { - XhtmlNode div = x.div(); - if (section.hasTitle()) { - div.h(level).tx(section.getTitle()); - } else if (section.hasCode()) { - renderBase(div.h(level), section.getCode()); - } - if (section.hasText()) { - x.addChildren(section.getText().getDiv()); - } - if (section.hasEntry()) { - XhtmlNode ul = x.ul(); - for (Reference r : section.getEntry()) { - renderReference(c, ul.li(), r); - } - } - if (section.hasSection()) { - List sections = section.getSection(); - for (SectionComponent child : sections) { - if (nested) { - addSection(x.blockquote().para(), child, level+1, true, c); - } else { - addSection(x, child, level+1, true, c); - } - } - } - } - // children - } - - public XhtmlNode render(Bundle b) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - if ((b.getType() == BundleType.COLLECTION && allEntresAreHistoryProvenance(b))) { - return null; - } else { - int start = 0; - boolean docMode = false; - XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - if (b.getType() == BundleType.DOCUMENT) { - if (!b.hasEntry() || !(b.getEntryFirstRep().hasResource() && b.getEntryFirstRep().getResource() instanceof Composition)) { - throw new FHIRException(context.formatPhrase(RenderingContext.BUNDLE_REV_INV_DOC)); - } - renderDocument(x, b); - start = 1; - docMode = true; - x.hr(); - x.h2().addText(formatPhrase(RenderingContext.BUNDLE_DOCUMENT_CONTENT, b.getId(), b.getType().toCode())); - } else { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.getType().toCode())); - } - int i = 0; - for (BundleEntryComponent be : b.getEntry()) { - i++; - if (i > start) { - if (be.hasFullUrl()) - x.an(makeInternalBundleLink(be.getFullUrl())); - if (be.hasResource()) { - if (be.getResource().hasId()) { - x.an(be.getResource().getResourceType().name() + "_" + be.getResource().getId()); - x.an("hc"+be.getResource().getResourceType().name() + "_" + be.getResource().getId()); - } else { - String id = makeIdFromBundleEntry(be.getFullUrl()); - x.an(be.getResource().getResourceType().name() + "_" + id); - x.an("hc"+be.getResource().getResourceType().name() + "_" + id); - } - } - x.hr(); - if (docMode) { - if (be.hasFullUrl() && be.hasResource()) { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_URD, Integer.toString(i), be.getFullUrl(), be.getResource().fhirType(), be.getResource().getIdBase())); - } else if (be.hasFullUrl()) { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_U, Integer.toString(i), be.getFullUrl())); - } else if (be.hasResource()) { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_RD, Integer.toString(i), be.getResource().fhirType(), be.getResource().getIdBase())); - } - } else { - if (be.hasFullUrl()) { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.getFullUrl())); - } else { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i))); - } - if (be.hasRequest()) - renderRequest(x, be.getRequest()); - if (be.hasSearch()) - renderSearch(x, be.getSearch()); - if (be.hasResponse()) - renderResponse(x, be.getResponse()); - } - if (be.hasResource()) { - if (!docMode) { - x.para().addText(formatPhrase(RenderingContext.BUNDLE_RESOURCE, be.getResource().fhirType())); - } - if (be.hasResource()) { - XhtmlNode xn = null; - if (be.getResource() instanceof DomainResource) { - DomainResource dr = (DomainResource) be.getResource(); - xn = dr.getText().getDiv(); - } - if (xn == null || xn.isEmpty()) { - ResourceRenderer rr = RendererFactory.factory(be.getResource(), context); - try { - rr.setRcontext(new ResourceContext(rcontext, be.getResource())); - xn = rr.build(be.getResource()); - } catch (Exception e) { - xn = makeExceptionXhtml(e, context.formatPhrase(RenderingContext.BUND_REND_GEN_NARR)); - } - } - x.blockquote().para().getChildNodes().addAll(checkInternalLinks(b, xn.getChildNodes())); - } - } - } - } - return x; - } - } - - public static boolean allEntriesAreHistoryProvenance(List entries) throws UnsupportedEncodingException, FHIRException, IOException { - for (BaseWrapper be : entries) { - if (!"Provenance".equals(be.get("resource").fhirType())) { + public static boolean allEntriesAreHistoryProvenance(List entries) throws UnsupportedEncodingException, FHIRException, IOException { + for (ResourceWrapper be : entries) { + if (!"Provenance".equals(be.child("resource").fhirType())) { return false; } } @@ -409,52 +266,48 @@ public class BundleRenderer extends ResourceRenderer { } } - private void renderSearch(XhtmlNode root, BundleEntrySearchComponent search) { + private void renderSearch(XhtmlNode root, ResourceWrapper search) { StringBuilder b = new StringBuilder(); b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH)); - if (search.hasMode()) - b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH_MODE, search.getMode().toCode())); - if (search.hasScore()) { - if (search.hasMode()) + if (search.has("mode")) + b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH_MODE, search.primitiveValue("mode"))); + if (search.has("score")) { + if (search.has("mode")) { b.append(","); - b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH_SCORE, search.getScore())); + } + b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH_SCORE, search.primitiveValue("score"))); } root.para().addText(b.toString()); } - private void renderResponse(XhtmlNode root, BundleEntryResponseComponent response) { + private void renderResponse(XhtmlNode root, ResourceWrapper response) { root.para().addText(formatPhrase(RenderingContext.BUNDLE_RESPONSE)); StringBuilder b = new StringBuilder(); - b.append(response.getStatus()+"\r\n"); - if (response.hasLocation()) - b.append(formatPhrase(RenderingContext.BUNDLE_LOCATION, response.getLocation())+"\r\n"); - if (response.hasEtag()) - b.append(formatPhrase(RenderingContext.BUNDLE_ETAG, response.getEtag())+"\r\n"); - if (response.hasLastModified()) - b.append(formatPhrase(RenderingContext.BUNDLE_LAST_MOD, response.getEtag())+"\r\n"); + b.append(response.primitiveValue("status")+"\r\n"); + if (response.has("location")) + b.append(formatPhrase(RenderingContext.BUNDLE_LOCATION, response.primitiveValue("location"))+"\r\n"); + if (response.has("etag")) + b.append(formatPhrase(RenderingContext.BUNDLE_ETAG, response.primitiveValue("etag"))+"\r\n"); + if (response.has("lastModified")) + b.append(formatPhrase(RenderingContext.BUNDLE_LAST_MOD, response.primitiveValue("lastModified"))+"\r\n"); root.pre().addText(b.toString()); } - private void renderRequest(XhtmlNode root, BundleEntryRequestComponent request) { + private void renderRequest(XhtmlNode root, ResourceWrapper request) { root.para().addText(formatPhrase(RenderingContext.BUNDLE_REQUEST)); StringBuilder b = new StringBuilder(); - b.append(request.getMethod()+" "+request.getUrl()+"\r\n"); - if (request.hasIfNoneMatch()) - b.append(formatPhrase(RenderingContext.BUNDLE_IF_NON_MATCH, request.getIfNoneMatch())+"\r\n"); - if (request.hasIfModifiedSince()) - b.append(formatPhrase(RenderingContext.BUNDLE_IF_MOD, request.getIfModifiedSince())+"\r\n"); - if (request.hasIfMatch()) - b.append(formatPhrase(RenderingContext.BUNDLE_IF_MATCH, request.getIfMatch())+"\r\n"); - if (request.hasIfNoneExist()) - b.append(formatPhrase(RenderingContext.BUNDLE_IF_NONE, request.getIfNoneExist())+"\r\n"); + b.append(request.primitiveValue("method")+" "+request.primitiveValue("url")+"\r\n"); + if (request.has("ifNoneMatch")) + b.append(formatPhrase(RenderingContext.BUNDLE_IF_NON_MATCH, request.primitiveValue("ifNoneMatch"))+"\r\n"); + if (request.has("ifModifiedSince")) + b.append(formatPhrase(RenderingContext.BUNDLE_IF_MOD, request.primitiveValue("ifModifiedSince"))+"\r\n"); + if (request.has("ifMatch")) + b.append(formatPhrase(RenderingContext.BUNDLE_IF_MATCH, request.primitiveValue("ifMatch"))+"\r\n"); + if (request.has("ifNoneExist")) + b.append(formatPhrase(RenderingContext.BUNDLE_IF_NONE, request.primitiveValue("ifNoneExist"))+"\r\n"); root.pre().addText(b.toString()); } - - public String display(Bundle bundle) throws UnsupportedEncodingException, IOException { - return "??"; - } - public boolean canRender(Bundle b) { for (BundleEntryComponent be : b.getEntry()) { if (be.hasResource()) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CapabilityStatementRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CapabilityStatementRenderer.java index 3a1b8c645..5ad279112 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CapabilityStatementRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CapabilityStatementRenderer.java @@ -2,7 +2,6 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; import java.io.UnsupportedEncodingException; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -11,9 +10,8 @@ import java.util.Map; import javax.annotation.Nullable; import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CapabilityStatement; import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent; @@ -31,23 +29,39 @@ import org.hl7.fhir.r5.model.Element; import org.hl7.fhir.r5.model.Enumeration; import org.hl7.fhir.r5.model.Enumerations.FHIRVersion; import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.OperationDefinition; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class CapabilityStatementRenderer extends ResourceRenderer { + + public CapabilityStatementRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + render(status, x, (CapabilityStatement) r.getBase(), r); + } else { + throw new Error("CapabilityStatementRenderer only renders native resources directly"); + } + } + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + private static final String EXPECTATION = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation"; private static final String COMBINED = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-search-parameter-combination"; private static final String SP_BASE = "http://hl7.org/fhir/searchparameter/"; @@ -266,20 +280,8 @@ public class CapabilityStatementRenderer extends ResourceRenderer { } - //Constructors - public CapabilityStatementRenderer(RenderingContext context) { - super(context); - } - - public CapabilityStatementRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (CapabilityStatement) dr); - } - - public boolean render(XhtmlNode x, CapabilityStatement conf) throws FHIRFormatError, DefinitionException, IOException { + public void render(RenderingStatus status, XhtmlNode x, CapabilityStatement conf, ResourceWrapper res) throws FHIRFormatError, DefinitionException, IOException { + status.setExtensions(true); boolean igRenderingMode = (context.getRules() == GenerationRules.IG_PUBLISHER); FHIRVersion currentVersion = conf.getFhirVersion(); String versionPathComponent = getVersionPathComponent(currentVersion.getDefinition()); @@ -298,7 +300,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer { uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_FHIR_VER, currentVersion.toCode()) + " "); addSupportedFormats(uList, conf); - uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_PUB_ON, displayDateTime(conf.getDateElement()) + " ")); + uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_PUB_ON, displayDateTime(wrapWC(res, conf.getDateElement())) + " ")); uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_PUB_BY, conf.getPublisherElement().asStringValue()) + " "); @@ -307,7 +309,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer { block.addTag("p").addText(context.formatPhrase(RenderingContext.CAPABILTY_ALLOW_CAP)); - addSupportedCSs(x, conf); + addSupportedCSs(status, x, conf, res); addSupportedIGs(x, conf); int restNum = conf.getRest().size(); @@ -338,7 +340,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer { x.h(nextLevel,"resourcesCap" + Integer.toString(count)).addText(context.formatPhrase(RenderingContext.CAPABILITY_RES_PRO)); x.h(nextLevel+1,"resourcesSummary" + Integer.toString(count)).addText(context.formatPhrase(RenderingContext.GENERAL_SUMM)); addSummaryIntro(x); - addSummaryTable(x, rest, hasVRead, hasPatch, hasDelete, hasHistory, hasUpdates, count); + addSummaryTable(status, res, x, rest, hasVRead, hasPatch, hasDelete, hasHistory, hasUpdates, count); x.addTag("hr"); //Third time for individual resources int resCount = 1; @@ -355,7 +357,6 @@ public class CapabilityStatementRenderer extends ResourceRenderer { addWarningPanel(x,"⹋⹋ - this mark indicates that there are more than one expectation extensions present"); } - return true; } private String getVersionPathComponent(String definition) { @@ -374,12 +375,6 @@ public class CapabilityStatementRenderer extends ResourceRenderer { return cs.present(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((CapabilityStatement) r).present(); - } - - private boolean hasOp(CapabilityStatementRestResourceComponent r, TypeRestfulInteraction on) { for (ResourceInteractionComponent op : r.getInteraction()) { if (op.getCode() == on) @@ -424,19 +419,14 @@ public class CapabilityStatementRenderer extends ResourceRenderer { return null; } - private void addSupportedCSs(XhtmlNode x, CapabilityStatement cap) { + private void addSupportedCSs(RenderingStatus status, XhtmlNode x, CapabilityStatement cap, ResourceWrapper res) throws UnsupportedEncodingException, IOException { if (cap.hasInstantiates()) { XhtmlNode p = x.para(); p.tx(cap.getInstantiates().size() > 1 ? "This CapabilityStatement instantiates these CapabilityStatements" : "This CapabilityStatement instantiates the CapabilityStatement"); boolean first = true; for (CanonicalType ct : cap.getInstantiates()) { - CapabilityStatement cs = context.getContext().fetchResource(CapabilityStatement.class, ct.getValue(), cap); if (first) {first = false;} else {p.tx(", ");}; - if (cs == null) { - p.code().tx(ct.getValue()); - } else { - p.ah(cs.getWebPath()).tx(cs.present()); - } + renderCanonical(status, res, p, CapabilityStatement.class, ct); } } if (cap.hasImports()) { @@ -444,13 +434,8 @@ public class CapabilityStatementRenderer extends ResourceRenderer { p.tx(cap.getImports().size() > 1 ? "This CapabilityStatement imports these CapabilityStatements" : "This CapabilityStatement imports the CapabilityStatement"); boolean first = true; for (CanonicalType ct : cap.getImports()) { - CapabilityStatement cs = context.getContext().fetchResource(CapabilityStatement.class, ct.getValue(), cap); if (first) {first = false;} else {p.tx(", ");}; - if (cs == null) { - p.code().tx(ct.getValue()); - } else { - p.ah(cs.getWebPath()).tx(cs.present()); - } + renderCanonical(status, res, p, CapabilityStatement.class, ct); } } } @@ -737,7 +722,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer { uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_RES_OPER)); } - private void addSummaryTable(XhtmlNode x, CapabilityStatement.CapabilityStatementRestComponent rest, boolean hasVRead, boolean hasPatch, boolean hasDelete, boolean hasHistory, boolean hasUpdates, int count) throws IOException { + private void addSummaryTable(RenderingStatus status, ResourceWrapper res, XhtmlNode x, CapabilityStatement.CapabilityStatementRestComponent rest, boolean hasVRead, boolean hasPatch, boolean hasDelete, boolean hasHistory, boolean hasUpdates, int count) throws IOException { XhtmlNode t = x.div().attribute("class","table-responsive").table("table table-condensed table-hover"); XhtmlNode tr = t.addTag("thead").tr(); tr.th().b().tx(context.formatPhrase(RenderingContext.CAPABILITY_RES_TYP)); @@ -785,12 +770,12 @@ public class CapabilityStatementRenderer extends ResourceRenderer { if (hasSupProf) { profCell.br(); profCell.addTag("em").addText(context.formatPhrase(RenderingContext.CAPABILITY_ADD_SUPP_PROF)); - renderSupportedProfiles(profCell, r); + renderSupportedProfiles(status, res, profCell, r); } } else { //Case of only supported profiles profCell.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP_PROFS)); - renderSupportedProfiles(profCell, r); + renderSupportedProfiles(status, res, profCell, r); } //Show capabilities tr.td().addText(showOp(r, TypeRestfulInteraction.READ)); @@ -836,16 +821,11 @@ public class CapabilityStatementRenderer extends ResourceRenderer { return paramNames; } - private void renderSupportedProfiles(XhtmlNode profCell, CapabilityStatementRestResourceComponent r) throws IOException { + private void renderSupportedProfiles(RenderingStatus status, ResourceWrapper res, XhtmlNode profCell, CapabilityStatementRestResourceComponent r) throws IOException { for (CanonicalType sp: r.getSupportedProfile()) { profCell.br(); profCell.nbsp().nbsp(); - StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, sp.getValue()); - if (sd != null) { - profCell.ah(sd.getWebPath()).addText(sd.present()); - } else { - profCell.ah(sp.getValue()).addText(sp.getValue()); - } + renderCanonical(status, res, profCell, StructureDefinition.class, sp); } if (r.hasExtension(ToolingExtensions.EXT_PROFILE_MAPPING)) { profCell.br(); @@ -1451,16 +1431,6 @@ public class CapabilityStatementRenderer extends ResourceRenderer { node.addTag("span").attribute("class", "lead").addText(text); } - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } - private void addResourceLink(XhtmlNode node, String name, String canonicalUri) { addResourceLink(node, name, canonicalUri, false, ""); } 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 7d6cb9ed2..e8b53738c 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 @@ -1,10 +1,10 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; @@ -13,7 +13,6 @@ import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation; 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.Enumerations.CodeSystemContentMode; import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent; import org.hl7.fhir.r5.model.CodeSystem.CodeSystemHierarchyMeaning; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; @@ -22,26 +21,48 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent; import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Enumeration; +import org.hl7.fhir.r5.model.Enumerations.CodeSystemContentMode; import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; -import org.hl7.fhir.r5.renderers.CodeSystemRenderer.Translateable; +import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.renderers.utils.RenderingContext.MultiLanguagePolicy; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.LoincLinker; import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.i18n.I18nConstants; -import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class CodeSystemRenderer extends TerminologyRenderer { + + public CodeSystemRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (CodeSystem) r.getBase()); + render(status, x, (CodeSystem) r.getBase(), r); + } else { + throw new Error("CodeSystemRenderer only renders native resources directly"); + } + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + + public class Translateable { private String lang; @@ -62,39 +83,22 @@ public class CodeSystemRenderer extends TerminologyRenderer { } - - private Boolean doMarkdown = null; - - public CodeSystemRenderer(RenderingContext context) { - super(context); - } - - public CodeSystemRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } + private Boolean doMarkdown = null; - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (CodeSystem) dr); - } - - public boolean render(XhtmlNode x, CodeSystem cs) throws FHIRFormatError, DefinitionException, IOException { - boolean hasExtensions = false; - - if (context.isHeader()) { + public void render(RenderingStatus status, XhtmlNode x, CodeSystem cs, ResourceWrapper res) throws FHIRFormatError, DefinitionException, IOException { + + if (context.isShowSummaryTable()) { XhtmlNode h = x.h2(); h.addText(cs.hasTitle() ? cs.getTitle() : cs.getName()); addMarkdown(x, cs.getDescription()); if (cs.hasCopyright()) - generateCopyright(x, cs ); + generateCopyright(x, res); } boolean props = generateProperties(x, cs); generateFilters(x, cs); List maps = new ArrayList(); - hasExtensions = generateCodeSystemContent(x, cs, hasExtensions, maps, props); - - return hasExtensions; + generateCodeSystemContent(status, x, cs, maps, props); } public void describe(XhtmlNode x, CodeSystem cs) { @@ -200,19 +204,22 @@ public class CodeSystemRenderer extends TerminologyRenderer { } } - private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List maps, boolean props) throws FHIRFormatError, DefinitionException, IOException { + private void generateCodeSystemContent(RenderingStatus status, XhtmlNode x, CodeSystem cs, List maps, boolean props) throws FHIRFormatError, DefinitionException, IOException { if (props) { x.para().b().tx(formatPhrase(RenderingContext.CODESYSTEM_CONCEPTS)); } XhtmlNode p = x.para(); + + p.startScript("csc"); renderStatus(cs.getUrlElement(), p.param("cs")).code().tx(cs.getUrl()); makeCasedParam(p.param("cased"), cs, cs.getCaseSensitiveElement()); makeHierarchyParam(p.param("h"), cs, cs.getHierarchyMeaningElement()); - p.paramValue("code-count", CodeSystemUtilities.countCodes(cs)); - p.sentenceForParams(sentenceForContent(cs.getContent(), cs)); + p.execScript(sentenceForContent(cs.getContent(), cs)); + p.closeScript(); + if (cs.getContent() == CodeSystemContentMode.NOTPRESENT) { - return false; + return; } XhtmlNode t = x.table( "codes"); @@ -258,7 +265,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { 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.size() < 2 ? langs : null, isSupplement) || hasExtensions; + addDefineRowToTable(status, t, c, 0, hierarchy, display, definitions, commentS, version, deprecated, maps, cs.getUrl(), cs, properties, csNav, langs.size() < 2 ? langs : null, isSupplement); } if (langs.size() >= 2) { Collections.sort(langs); @@ -272,7 +279,6 @@ public class CodeSystemRenderer extends TerminologyRenderer { addLanguageRow(c, t, langs); } } - return hasExtensions; } private void makeHierarchyParam(XhtmlNode x, CodeSystem cs, Enumeration hm) { @@ -421,7 +427,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { - private boolean addDefineRowToTable(XhtmlNode t, ConceptDefinitionComponent c, int level, boolean hasHierarchy, boolean hasDisplay, boolean hasDefinitions, boolean comment, boolean version, boolean deprecated, List maps, String system, CodeSystem cs, List properties, CodeSystemNavigator csNav, List langs, boolean isSupplement) throws FHIRFormatError, DefinitionException, IOException { + private void addDefineRowToTable(RenderingStatus status, XhtmlNode t, ConceptDefinitionComponent c, int level, boolean hasHierarchy, boolean hasDisplay, boolean hasDefinitions, boolean comment, boolean version, boolean deprecated, List maps, String system, CodeSystem cs, List properties, CodeSystemNavigator csNav, List langs, boolean isSupplement) throws FHIRFormatError, DefinitionException, IOException { boolean hasExtensions = false; XhtmlNode tr = t.tr(); boolean notCurrent = CodeSystemUtilities.isNotCurrent(cs, c); @@ -438,13 +444,13 @@ public class CodeSystemRenderer extends TerminologyRenderer { } String link = isSupplement ? getLinkForCode(cs.getSupplements(), null, c.getCode()) : null; if (link != null) { - td.ah(link).style( "white-space:nowrap").addText(c.getCode()); + td.ah(context.prefixLocalHref(link)).style( "white-space:nowrap").addText(c.getCode()); } else { td.style("white-space:nowrap").addText(c.getCode()); } XhtmlNode a; if (c.hasCodeElement()) { - td.an(cs.getId()+"-" + Utilities.nmtokenize(c.getCode())); + td.an(context.prefixAnchor(cs.getId()+"-" + Utilities.nmtokenize(c.getCode()))); } if (hasDisplay) { @@ -512,7 +518,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { td.tx(" "+ context.formatPhrase(RenderingContext.CODE_SYS_REPLACED_BY) + " "); String url = getCodingReference(cc, system); if (url != null) { - td.ah(url).addText(cc.getCode()); + td.ah(context.prefixLocalHref(url)).addText(cc.getCode()); td.tx(": "+cc.getDisplay()+")"); } else td.addText(cc.getCode()+" '"+cc.getDisplay()+"' in "+cc.getSystem()+")"); @@ -576,14 +582,14 @@ public class CodeSystemRenderer extends TerminologyRenderer { } else if (pcv.hasValueStringType() && Utilities.isAbsoluteUrl(pcv.getValue().primitiveValue())) { CanonicalResource cr = (CanonicalResource) context.getContext().fetchResource(Resource.class, pcv.getValue().primitiveValue()); if (cr != null) { - td.ah(cr.getWebPath(), cr.getVersionedUrl()).tx(cr.present()); + td.ah(context.prefixLocalHref(cr.getWebPath()), cr.getVersionedUrl()).tx(cr.present()); } else if (Utilities.isAbsoluteUrlLinkable(pcv.getValue().primitiveValue())) { - td.ah(pcv.getValue().primitiveValue()).tx(pcv.getValue().primitiveValue()); + td.ah(context.prefixLocalHref(pcv.getValue().primitiveValue())).tx(pcv.getValue().primitiveValue()); } else { td.code(pcv.getValue().primitiveValue()); } } else if ("parent".equals(pcv.getCode())) { - td.ah("#"+cs.getId()+"-"+Utilities.nmtokenize(pcv.getValue().primitiveValue())).addText(pcv.getValue().primitiveValue()); + td.ah(context.prefixLocalHref("#"+cs.getId()+"-"+Utilities.nmtokenize(pcv.getValue().primitiveValue()))).addText(pcv.getValue().primitiveValue()); } else { td.addText(pcv.getValue().primitiveValue()); } @@ -607,7 +613,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { first = false; XhtmlNode span = td.span(null, mapping.comp.hasRelationship() ? mapping.comp.getRelationship().toCode() : ""); span.addText(getCharForRelationship(mapping.comp)); - a = td.ah(getContext().getLink(KnownLinkType.SPEC)+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode())); + a = td.ah(context.prefixLocalHref(getContext().getLink(KnownLinkType.SPEC)+m.getLink()+"#"+makeAnchor(mapping.group.getTarget(), mapping.comp.getCode()))); a.addText(mapping.comp.getCode()); if (!Utilities.noString(mapping.comp.getComment())) td.i().tx("("+mapping.comp.getComment()+")"); @@ -615,7 +621,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { } List ocl = csNav.getOtherChildren(c); for (ConceptDefinitionComponent cc : csNav.getConcepts(c)) { - hasExtensions = addDefineRowToTable(t, cc, level+1, hasHierarchy, hasDisplay, hasDefinitions, comment, version, deprecated, maps, system, cs, properties, csNav, langs, isSupplement) || hasExtensions; + addDefineRowToTable(status, t, cc, level+1, hasHierarchy, hasDisplay, hasDefinitions, comment, version, deprecated, maps, system, cs, properties, csNav, langs, isSupplement); } for (ConceptDefinitionComponent cc : ocl) { tr = t.tr(); @@ -625,7 +631,7 @@ public class CodeSystemRenderer extends TerminologyRenderer { String s = Utilities.padLeft("", '\u00A0', (level+1)*2); td.addText(s); td.style("white-space:nowrap"); - a = td.ah("#"+cs.getId()+"-" + Utilities.nmtokenize(cc.getCode())); + a = td.ah(context.prefixLocalHref("#"+cs.getId()+"-" + Utilities.nmtokenize(cc.getCode()))); a.addText(cc.getCode()); if (hasDisplay) { td = tr.td(); @@ -643,7 +649,6 @@ public class CodeSystemRenderer extends TerminologyRenderer { 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; } private String getDisplay(String lang, ConceptDefinitionComponent c) { @@ -738,4 +743,58 @@ public class CodeSystemRenderer extends TerminologyRenderer { } } + + @Override + protected void genSummaryTableContent(RenderingStatus status, XhtmlNode tbl, CanonicalResource cr) throws IOException { + super.genSummaryTableContent(status, tbl, cr); + + CodeSystem cs = (CodeSystem) cr; + XhtmlNode tr; + if (cs.hasContent()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_CONTENT)+":"); + XhtmlNode td = tr.td(); + td.tx((cs.getContent().getDisplay())+": "+describeContent(cs.getContent(), cs)); + if (cs.getContent() == CodeSystemContentMode.SUPPLEMENT) { + td.tx(" "); + CodeSystem tgt = context.getContext().fetchCodeSystem(cs.getSupplements()); + if (tgt != null) { + td.ah(tgt.getWebPath()).tx(tgt.present()); + } else { + td.code().tx(cs.getSupplements()); + } + } + } + + if (CodeSystemUtilities.hasOID(cs)) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_OID)+":"); + tr.td().tx(context.formatPhrase(RenderingContext.CODE_SYS_FOR_OID, CodeSystemUtilities.getOID(cs))); + } + + if (cs.hasValueSet()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_VALUESET)+":"); + ValueSet vs = context.getContext().findTxResource(ValueSet.class, cs.getValueSet()); + if (vs == null) { + tr.td().tx(context.formatPhrase(RenderingContext.CODE_SYS_THE_VALUE_SET, cs.getValueSet())+")"); + } else { + tr.td().ah(vs.getWebPath()).tx(context.formatPhrase(RenderingContext.CODE_SYS_THE_VALUE_SET, cs.getValueSet())+")"); + } + } + } + + private String describeContent(CodeSystemContentMode content, CodeSystem cs) { + switch (content) { + case COMPLETE: return (context.formatPhrase(RenderingContext.CODE_SYS_COMPLETE)); + case NOTPRESENT: return (context.formatPhrase(RenderingContext.CODE_SYS_NOTPRESENT)); + case EXAMPLE: return (context.formatPhrase(RenderingContext.CODE_SYS_EXAMPLE)); + case FRAGMENT: return (context.formatPhrase(RenderingContext.CODE_SYS_FRAGMENT)); + case SUPPLEMENT: return (context.formatPhrase(RenderingContext.CODE_SYS_SUPPLEMENT)); + default: + return "?? illegal content status value "+(content == null ? "(null)" : content.toCode()); + } + } + + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CompartmentDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CompartmentDefinitionRenderer.java index cb46cc7c8..fa0da2152 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CompartmentDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/CompartmentDefinitionRenderer.java @@ -4,33 +4,41 @@ import java.io.IOException; 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.model.CompartmentDefinition; import org.hl7.fhir.r5.model.CompartmentDefinition.CompartmentDefinitionResourceComponent; -import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; -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.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; public class CompartmentDefinitionRenderer extends ResourceRenderer { - public CompartmentDefinitionRenderer(RenderingContext context) { - super(context); + public CompartmentDefinitionRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (CompartmentDefinition) r.getBase()); + render(status, x, (CompartmentDefinition) r.getBase()); + } else { + throw new Error("CompartmentDefinitionRenderer only renders native resources directly"); + } } - public CompartmentDefinitionRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (CompartmentDefinition) dr); + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public boolean render(XhtmlNode x, CompartmentDefinition cpd) throws FHIRFormatError, DefinitionException, IOException { + public void render(RenderingStatus status, XhtmlNode x, CompartmentDefinition cpd) throws FHIRFormatError, DefinitionException, IOException { StringBuilder in = new StringBuilder(); StringBuilder out = new StringBuilder(); for (CompartmentDefinitionResourceComponent cc: cpd.getResource()) { @@ -56,7 +64,6 @@ public class CompartmentDefinitionRenderer extends ResourceRenderer { out.toString()+ "\r\n"); x.getChildNodes().addAll(xn.getChildNodes()); - return true; } public void describe(XhtmlNode x, CompartmentDefinition cd) { @@ -67,19 +74,4 @@ public class CompartmentDefinitionRenderer extends ResourceRenderer { return cd.present(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((CompartmentDefinition) r).present(); - } - - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } - } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ConceptMapRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ConceptMapRenderer.java index 8697dff3a..627a16232 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ConceptMapRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ConceptMapRenderer.java @@ -1,6 +1,7 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -10,6 +11,7 @@ import java.util.List; import java.util.Map; import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.Coding; @@ -24,9 +26,9 @@ import org.hl7.fhir.r5.model.ContactDetail; import org.hl7.fhir.r5.model.ContactPoint; import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.ConceptMapRenderer.CollateralDefinition; import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.Utilities; @@ -35,6 +37,29 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class ConceptMapRenderer extends TerminologyRenderer { + + public ConceptMapRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (ConceptMap) r.getBase()); + render(status, r, x, (ConceptMap) r.getBase(), false); + } else { + throw new Error("ConceptMapRenderer only renders native resources directly"); + } + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + + + public static class CollateralDefinition { private Resource resource; private String label; @@ -296,19 +321,9 @@ public class ConceptMapRenderer extends TerminologyRenderer { } } - public ConceptMapRenderer(RenderingContext context) { - super(context); - } - - public ConceptMapRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (ConceptMap) dr, false); - } - public boolean render(XhtmlNode x, ConceptMap cm, boolean header) throws FHIRFormatError, DefinitionException, IOException { + public void render(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ConceptMap cm, boolean header) throws FHIRFormatError, DefinitionException, IOException { if (header) { x.h2().addText(cm.getName()+" ("+cm.getUrl()+")"); } @@ -330,7 +345,7 @@ public class ConceptMapRenderer extends TerminologyRenderer { p.addText(Utilities.capitalize(cm.getStatus().toString())+" "+ (context.formatPhrase(RenderingContext.CONC_MAP_NO_PROD_USE) + " ")); else p.addText(Utilities.capitalize(cm.getStatus().toString())+". "); - p.tx(context.formatPhrase(RenderingContext.CONC_MAP_PUB_ON, (cm.hasDate() ? display(cm.getDateElement()) : "?ngen-10?")+" by "+cm.getPublisher()) + " "); + p.tx(context.formatPhrase(RenderingContext.CONC_MAP_PUB_ON, (cm.hasDate() ? displayDataType(cm.getDateElement()) : "?ngen-10?")+" by "+cm.getPublisher()) + " "); if (!cm.getContact().isEmpty()) { p.tx(" ("); boolean firsti = true; @@ -347,7 +362,7 @@ public class ConceptMapRenderer extends TerminologyRenderer { first = false; else p.tx(", "); - addTelecom(p, c); + addTelecom(p, wrapWC(res, c)); } } p.tx(")"); @@ -403,13 +418,13 @@ public class ConceptMapRenderer extends TerminologyRenderer { pp.b().tx(context.formatPhrase(RenderingContext.CONC_MAP_GRP, gc) + " "); pp.tx(context.formatPhrase(RenderingContext.CONC_MAP_FROM) + " "); if (grp.hasSource()) { - renderCanonical(cm, pp, grp.getSource()); + renderCanonical(status, res, pp, CodeSystem.class, grp.getSourceElement()); } else { pp.code(context.formatPhrase(RenderingContext.CONC_MAP_CODE_SYS_UNSPEC)); } pp.tx(" to "); if (grp.hasTarget()) { - renderCanonical(cm, pp, grp.getTarget()); + renderCanonical(status, res, pp, CodeSystem.class, grp.getTargetElement()); } else { pp.code(context.formatPhrase(RenderingContext.CONC_MAP_CODE_SYS_UNSPEC)); } @@ -440,9 +455,9 @@ public class ConceptMapRenderer extends TerminologyRenderer { else { if (ccm.hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) { String code = ToolingExtensions.readStringExtension(ccm, ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE); - tr.td().ah(eqpath+"#"+code, code).tx(presentEquivalenceCode(code)); + tr.td().ah(context.prefixLocalHref(eqpath+"#"+code), code).tx(presentEquivalenceCode(code)); } else { - tr.td().ah(eqpath+"#"+ccm.getRelationship().toCode(), ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode())); + tr.td().ah(context.prefixLocalHref(eqpath+"#"+ccm.getRelationship().toCode()), ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode())); } } td = tr.td(); @@ -592,9 +607,9 @@ public class ConceptMapRenderer extends TerminologyRenderer { else { if (ccm.getRelationshipElement().hasExtension(ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE)) { String code = ToolingExtensions.readStringExtension(ccm.getRelationshipElement(), ToolingExtensions.EXT_OLD_CONCEPTMAP_EQUIVALENCE); - tr.td().ah(eqpath+"#"+code, code).tx(presentEquivalenceCode(code)); + tr.td().ah(context.prefixLocalHref(eqpath+"#"+code), code).tx(presentEquivalenceCode(code)); } else { - tr.td().ah(eqpath+"#"+ccm.getRelationship().toCode(), ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode())); + tr.td().ah(context.prefixLocalHref(eqpath+"#"+ccm.getRelationship().toCode()), ccm.getRelationship().toCode()).tx(presentRelationshipCode(ccm.getRelationship().toCode())); } } } @@ -630,7 +645,6 @@ public class ConceptMapRenderer extends TerminologyRenderer { } } } - return true; } public void describe(XhtmlNode x, ConceptMap cm) { @@ -703,7 +717,7 @@ public class ConceptMapRenderer extends TerminologyRenderer { if (cs == null) td.tx(url); else - td.ah(context.fixReference(cs.getWebPath())).attribute("title", url).tx(cs.present()); + td.ah(context.prefixLocalHref(context.fixReference(cs.getWebPath()))).attribute("title", url).tx(cs.present()); } private void addUnmapped(XhtmlNode tbl, ConceptMapGroupComponent grp) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java index 991574d57..3bc5ea1ee 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java @@ -1,115 +1,79 @@ package org.hl7.fhir.r5.renderers; - -import static java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static java.time.temporal.ChronoField.YEAR; - -import java.io.IOException; -import java.math.BigDecimal; -import java.text.NumberFormat; -import java.time.LocalDate; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.FormatStyle; -import java.time.format.SignStyle; -import java.util.Currency; -import java.util.List; - -import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.context.ContextUtilities; -import org.hl7.fhir.r5.context.IWorkerContext; -import org.hl7.fhir.r5.elementmodel.Element; -import org.hl7.fhir.r5.model.Address; -import org.hl7.fhir.r5.model.Annotation; -import org.hl7.fhir.r5.model.BackboneType; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.Base64BinaryType; -import org.hl7.fhir.r5.model.BaseDateTimeType; -import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.CanonicalType; -import org.hl7.fhir.r5.model.CodeSystem; -import org.hl7.fhir.r5.model.CodeType; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.CodeableReference; -import org.hl7.fhir.r5.model.Coding; -import org.hl7.fhir.r5.model.ContactDetail; -import org.hl7.fhir.r5.model.ContactPoint; -import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem; -import org.hl7.fhir.r5.model.DataRequirement; -import org.hl7.fhir.r5.model.DataRequirement.DataRequirementCodeFilterComponent; -import org.hl7.fhir.r5.model.DataRequirement.DataRequirementDateFilterComponent; -import org.hl7.fhir.r5.model.DataRequirement.DataRequirementSortComponent; -import org.hl7.fhir.r5.model.DataRequirement.SortDirection; -import org.hl7.fhir.r5.model.DataType; -import org.hl7.fhir.r5.model.DateTimeType; -import org.hl7.fhir.r5.model.DateType; -import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.Enumeration; -import org.hl7.fhir.r5.model.Expression; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.ExtensionHelper; -import org.hl7.fhir.r5.model.HumanName; -import org.hl7.fhir.r5.model.HumanName.NameUse; -import org.hl7.fhir.r5.model.IdType; -import org.hl7.fhir.r5.model.Identifier; -import org.hl7.fhir.r5.model.MarkdownType; -import org.hl7.fhir.r5.model.Money; -import org.hl7.fhir.r5.model.NamingSystem; -import org.hl7.fhir.r5.model.Period; -import org.hl7.fhir.r5.model.PrimitiveType; -import org.hl7.fhir.r5.model.Quantity; -import org.hl7.fhir.r5.model.Range; -import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.SampledData; -import org.hl7.fhir.r5.model.StringType; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.Timing; -import org.hl7.fhir.r5.model.Timing.EventTiming; -import org.hl7.fhir.r5.model.Timing.TimingRepeatComponent; -import org.hl7.fhir.r5.model.Timing.UnitsOfTime; -import org.hl7.fhir.r5.model.TriggerDefinition; -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.ConceptReferenceComponent; -import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -import org.hl7.fhir.r5.renderers.CodeResolver.CodeResolution; -import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; -import org.hl7.fhir.r5.terminologies.JurisdictionUtilities; -import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; -import org.hl7.fhir.r5.utils.ToolingExtensions; -import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.VersionUtilities; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; -import org.hl7.fhir.utilities.xhtml.NodeType; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; -import org.hl7.fhir.utilities.xhtml.XhtmlParser; - + +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.YEAR; + +import java.io.IOException; +import java.math.BigDecimal; +import java.text.NumberFormat; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.FormatStyle; +import java.time.format.SignStyle; +import java.util.Currency; +import java.util.List; + +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.model.BackboneType; +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.BaseDateTimeType; +import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.model.CodeableConcept; +import org.hl7.fhir.r5.model.Coding; +import org.hl7.fhir.r5.model.ContactPoint; +import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r5.model.DataType; +import org.hl7.fhir.r5.model.DateTimeType; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.Extension; +import org.hl7.fhir.r5.model.NamingSystem; +import org.hl7.fhir.r5.model.PrimitiveType; +import org.hl7.fhir.r5.model.Quantity; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent; +import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.terminologies.JurisdictionUtilities; +import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; +import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.DebugUtilities; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.VersionUtilities; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; +import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; +import org.hl7.fhir.utilities.xhtml.XhtmlParser; + import ca.uhn.fhir.model.api.TemporalPrecisionEnum; - + public class DataRenderer extends Renderer implements CodeResolver { - + // -- 1. context -------------------------------------------------------------- - + public DataRenderer(RenderingContext context) { super(context); } - + public DataRenderer(IWorkerContext worker) { super(worker); } - + // -- 2. Markdown support ------------------------------------------------------- - + public static String processRelativeUrls(String markdown, String path) { if (markdown == null) { return ""; @@ -129,8 +93,8 @@ public class DataRenderer extends Renderer implements CodeResolver { String url = markdown.substring(i+2, j); if (!Utilities.isAbsoluteUrl(url) && !url.startsWith("..")) { // it's relative - so it's relative to the base URL - b.append("]("); - b.append(basePath); + b.append("]("); + b.append(basePath); } else { b.append("]("); } @@ -144,11 +108,11 @@ public class DataRenderer extends Renderer implements CodeResolver { } return b.toString(); } - + protected void addMarkdown(XhtmlNode x, String text, String path) throws FHIRFormatError, IOException, DefinitionException { addMarkdown(x, processRelativeUrls(text, path)); } - + protected void addMarkdown(XhtmlNode x, String text) throws FHIRFormatError, IOException, DefinitionException { if (text != null) { // 1. custom FHIR extensions @@ -188,10 +152,10 @@ public class DataRenderer extends Renderer implements CodeResolver { } else { throw new DefinitionException(context.formatPhrase(RenderingContext.DATA_REND_MKDWN_LNK, link) + " "); } - + text = left+"["+link+"]("+url+(path == null ? "" : "#"+path)+")"+right; } - + // 2. markdown String s = getContext().getMarkdown().process(text, "narrative generator"); XhtmlParser p = new XhtmlParser(); @@ -204,11 +168,11 @@ public class DataRenderer extends Renderer implements CodeResolver { x.getChildNodes().addAll(m.getChildNodes()); } } - + protected void smartAddText(XhtmlNode p, String text) { if (text == null) return; - + String[] lines = text.split("\\r\\n"); for (int i = 0; i < lines.length; i++) { if (i > 0) @@ -216,9 +180,9 @@ public class DataRenderer extends Renderer implements CodeResolver { p.addText(lines[i]); } } - + // -- 3. General Purpose Terminology Support ----------------------------------------- - + private static String snMonth(String m) { switch (m) { case "1" : return "Jan"; @@ -236,13 +200,13 @@ public class DataRenderer extends Renderer implements CodeResolver { default: return null; } } - + public static String describeVersion(String version) { if (version.startsWith("http://snomed.info/sct")) { String[] p = version.split("\\/"); String ed = null; String dt = ""; - + if (p[p.length-2].equals("version")) { ed = p[p.length-3]; String y = p[p.length-3].substring(4, 8); @@ -268,30 +232,30 @@ public class DataRenderer extends Renderer implements CodeResolver { return version; } } - + public String displaySystem(String system) { if (system == null) - return (context.formatPhrase(RenderingContext.DATA_REND_NOT_STAT)); + return (context.formatPhrase(RenderingContext.DATA_REND_NOT_STAT)); if (system.equals("http://loinc.org")) - return (context.formatPhrase(RenderingContext.DATA_REND_LOINC)); + return (context.formatPhrase(RenderingContext.DATA_REND_LOINC)); if (system.startsWith("http://snomed.info")) - return (context.formatPhrase(RenderingContext.DATA_REND_SNOMED)); + return (context.formatPhrase(RenderingContext.DATA_REND_SNOMED)); if (system.equals("http://www.nlm.nih.gov/research/umls/rxnorm")) - return (context.formatPhrase(RenderingContext.DATA_REND_RXNORM)); + return (context.formatPhrase(RenderingContext.DATA_REND_RXNORM)); if (system.equals("http://hl7.org/fhir/sid/icd-9")) - return (context.formatPhrase(RenderingContext.DATA_REND_ICD)); + return (context.formatPhrase(RenderingContext.DATA_REND_ICD)); if (system.equals("http://dicom.nema.org/resources/ontology/DCM")) - return (context.formatPhrase(RenderingContext.DATA_REND_DICOM)); + return (context.formatPhrase(RenderingContext.DATA_REND_DICOM)); if (system.equals("http://unitsofmeasure.org")) - return (context.formatPhrase(RenderingContext.GENERAL_UCUM)); - + return (context.formatPhrase(RenderingContext.GENERAL_UCUM)); + CodeSystem cs = context.getContext().fetchCodeSystem(system); if (cs != null) { return crPresent(cs); } return tails(system); } - + private String crPresent(CanonicalResource cr) { if (cr.hasUserData("presentation")) { return cr.getUserString("presentation"); @@ -302,7 +266,7 @@ public class DataRenderer extends Renderer implements CodeResolver { return context.getTranslated(cr.getNameElement()); return cr.toString(); } - + private String tails(String system) { if (system.contains("/")) { return system.substring(system.lastIndexOf("/")+1); @@ -310,7 +274,7 @@ public class DataRenderer extends Renderer implements CodeResolver { return (context.formatPhrase(RenderingContext.DATA_REND_UNKNWN)); } } - + protected String makeAnchor(String codeSystem, String code) { String s = codeSystem+'-'+code; StringBuilder b = new StringBuilder(); @@ -322,19 +286,19 @@ public class DataRenderer extends Renderer implements CodeResolver { } return b.toString(); } - + private String lookupCode(String system, String version, String code) { if (JurisdictionUtilities.isJurisdiction(system)) { return JurisdictionUtilities.displayJurisdiction(system+"#"+code); } ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().withLanguage(context.getLocale().toString().replace("_", "-")).withVersionFlexible(true), system, version, code, null); - + if (t != null && t.getDisplay() != null) return t.getDisplay(); else return code; } - + protected String describeLang(String lang) { // special cases: if ("fr-CA".equals(lang)) { @@ -383,7 +347,7 @@ public class DataRenderer extends Renderer implements CodeResolver { } return lang; } - + private boolean isCanonical(String path) { if (!path.endsWith(".url")) return false; @@ -402,15 +366,19 @@ public class DataRenderer extends Renderer implements CodeResolver { return true; return false; } - + // -- 4. Language support ------------------------------------------------------ - + public String gt(@SuppressWarnings("rawtypes") PrimitiveType value) { return context.getTranslated(value); } - + + public String gt(ResourceWrapper value) { + return context.getTranslated(value); + } + // -- 6. General purpose extension rendering ---------------------------------------------- - + public boolean hasRenderableExtensions(DataType element) { for (Extension ext : element.getExtension()) { if (canRender(ext)) { @@ -419,7 +387,7 @@ public class DataRenderer extends Renderer implements CodeResolver { } return false; } - + public boolean hasRenderableExtensions(BackboneType element) { for (Extension ext : element.getExtension()) { if (canRender(ext)) { @@ -428,7 +396,16 @@ public class DataRenderer extends Renderer implements CodeResolver { } return element.hasModifierExtension(); } - + + public boolean hasRenderableExtensions(ResourceWrapper element) { + for (ResourceWrapper ext : element.extensions()) { + if (canRender(ext)) { + return true; + } + } + return false; + } + private String getExtensionLabel(Extension ext) { StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.getUrl()); if (sd != null && ext.hasValue() && ext.getValue().isPrimitive() && sd.hasSnapshot()) { @@ -440,52 +417,77 @@ public class DataRenderer extends Renderer implements CodeResolver { } return null; } - + + private String getExtensionLabel(ResourceWrapper ext) { + StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.primitiveValue("url")); + if (sd != null && ext.has("value") && ext.child("value").isPrimitive() && sd.hasSnapshot()) { + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + if (Utilities.existsInList(ed.getPath(), "Extension", "Extension.value[x]") && ed.hasLabel()) { + return context.getTranslated(ed.getLabelElement()); + } + } + } + return null; + } + private boolean canRender(Extension ext) { return getExtensionLabel(ext) != null; } - - public void renderExtensionsInList(XhtmlNode ul, DataType element) throws FHIRFormatError, DefinitionException, IOException { - for (Extension ext : element.getExtension()) { + + + private boolean canRender(ResourceWrapper ext) { + StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.primitiveValue("url")); + if (sd != null && ext.has("value") && ext.isPrimitive("value") && sd.hasSnapshot()) { + for (ElementDefinition ed : sd.getSnapshot().getElement()) { + if (Utilities.existsInList(ed.getPath(), "Extension", "Extension.value[x]") && ed.hasLabel()) { + return true; + } + } + } + return false; + } + + public void renderExtensionsInList(RenderingStatus status, XhtmlNode ul, ResourceWrapper element) throws FHIRFormatError, DefinitionException, IOException { + for (ResourceWrapper ext : element.extensions()) { if (canRender(ext)) { String lbl = getExtensionLabel(ext); XhtmlNode li = ul.li(); li.tx(lbl); li.tx(": "); - render(li, ext.getValue()); + renderDataType(status, li, ext.child("value")); } } } - - public void renderExtensionsInList(XhtmlNode ul, BackboneType element) throws FHIRFormatError, DefinitionException, IOException { - for (Extension ext : element.getModifierExtension()) { - if (canRender(ext)) { - String lbl = getExtensionLabel(ext); - XhtmlNode li = ul.li(); - li = li.b(); - li.tx(lbl); - li.tx(": "); - render(li, ext.getValue()); - } else { - // somehow have to do better than this - XhtmlNode li = ul.li(); - li.b().tx(context.formatPhrase(RenderingContext.DATA_REND_UNRD_EX)); - } - } - for (Extension ext : element.getExtension()) { - if (canRender(ext)) { - String lbl = getExtensionLabel(ext); - XhtmlNode li = ul.li(); - li.tx(lbl); - li.tx(": "); - render(li, ext.getValue()); - } - } - } - - public void renderExtensionsInText(XhtmlNode div, DataType element, String sep) throws FHIRFormatError, DefinitionException, IOException { + + // public void renderExtensionsInList(XhtmlNode ul, BackboneType element) throws FHIRFormatError, DefinitionException, IOException { + // for (Extension ext : element.getModifierExtension()) { + // if (canRender(ext)) { + // String lbl = getExtensionLabel(ext); + // XhtmlNode li = ul.li(); + // li = li.b(); + // li.tx(lbl); + // li.tx(": "); + // render(li, ext.getValue()); + // } else { + // // somehow have to do better than this + // XhtmlNode li = ul.li(); + // li.b().tx(context.formatPhrase(RenderingContext.DATA_REND_UNRD_EX)); + // } + // } + // for (Extension ext : element.getExtension()) { + // if (canRender(ext)) { + // String lbl = getExtensionLabel(ext); + // XhtmlNode li = ul.li(); + // li.tx(lbl); + // li.tx(": "); + // render(li, ext.getValue()); + // } + // } + // } + // + public void renderExtensionsInText(RenderingStatus status, XhtmlNode div, ResourceWrapper element, String sep) throws FHIRFormatError, DefinitionException, IOException { boolean first = true; - for (Extension ext : element.getExtension()) { + for (ResourceWrapper ext : element.extensions()) { if (canRender(ext)) { if (first) { first = false; @@ -493,110 +495,146 @@ public class DataRenderer extends Renderer implements CodeResolver { div.tx(sep); div.tx(" "); } - + String lbl = getExtensionLabel(ext); div.tx(lbl); div.tx(": "); - render(div, ext.getValue()); + renderDataType(status, div, ext.child("value")); } } } - - public void renderExtensionsInList(XhtmlNode div, BackboneType element, String sep) throws FHIRFormatError, DefinitionException, IOException { - boolean first = true; - for (Extension ext : element.getModifierExtension()) { - if (first) { - first = false; - } else { - div.tx(sep); - div.tx(" "); - } - if (canRender(ext)) { - String lbl = getExtensionLabel(ext); - XhtmlNode b = div.b(); - b.tx(lbl); - b.tx(": "); - render(div, ext.getValue()); - } else { - // somehow have to do better than this - div.b().tx(context.formatPhrase(RenderingContext.DATA_REND_UNRD_EX)); - } - } - for (Extension ext : element.getExtension()) { - if (canRender(ext)) { - if (first) { - first = false; - } else { - div.tx(sep); - div.tx(" "); - } - - String lbl = getExtensionLabel(ext); - div.tx(lbl); - div.tx(": "); - render(div, ext.getValue()); - } - } - - } - + + // public void renderExtensionsInList(XhtmlNode div, BackboneType element, String sep) throws FHIRFormatError, DefinitionException, IOException { + // boolean first = true; + // for (Extension ext : element.getModifierExtension()) { + // if (first) { + // first = false; + // } else { + // div.tx(sep); + // div.tx(" "); + // } + // if (canRender(ext)) { + // String lbl = getExtensionLabel(ext); + // XhtmlNode b = div.b(); + // b.tx(lbl); + // b.tx(": "); + // render(div, ext.getValue()); + // } else { + // // somehow have to do better than this + // div.b().tx(context.formatPhrase(RenderingContext.DATA_REND_UNRD_EX)); + // } + // } + // for (Extension ext : element.getExtension()) { + // if (canRender(ext)) { + // if (first) { + // first = false; + // } else { + // div.tx(sep); + // div.tx(" "); + // } + // + // String lbl = getExtensionLabel(ext); + // div.tx(lbl); + // div.tx(": "); + // render(div, ext.getValue()); + // } + // } + // + // } + // -- 6. Data type Rendering ---------------------------------------------- - + public static String display(IWorkerContext context, DataType type) { - return new DataRenderer(new RenderingContext(context, null, null, "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE)).display(type); + return new DataRenderer(new RenderingContext(context, null, null, "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE)).displayDataType(type); } - + public String displayBase(Base b) { if (b instanceof DataType) { - return display((DataType) b); + return displayDataType((DataType) b); } else { return (context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, b.fhirType()) + " "); } } - - public String display(DataType type) { + + public String displayDataType(DataType type) { + if (type == null) { + return ""; + } + return displayDataType(wrapNC(type)); + } + + public String displayDataType(ResourceWrapper type) { if (type == null || type.isEmpty()) { return ""; } - - if (type instanceof Coding) { - return displayCoding((Coding) type); - } else if (type instanceof CodeableConcept) { - return displayCodeableConcept((CodeableConcept) type); - } else if (type instanceof Identifier) { - return displayIdentifier((Identifier) type); - } else if (type instanceof HumanName) { - return displayHumanName((HumanName) type); - } else if (type instanceof Address) { - return displayAddress((Address) type); - } else if (type instanceof ContactPoint) { - return displayContactPoint((ContactPoint) type); - } else if (type instanceof Quantity) { - return displayQuantity((Quantity) type); - } else if (type instanceof Range) { - return displayRange((Range) type); - } else if (type instanceof Period) { - return displayPeriod((Period) type); - } else if (type instanceof Timing) { - return displayTiming((Timing) type); - } else if (type instanceof SampledData) { - return displaySampledData((SampledData) type); - } else if (type instanceof ContactDetail) { - return displayContactDetail((ContactDetail) type); - } else if (type.isDateTime()) { - return displayDateTime((BaseDateTimeType) type); - } else if (type.isPrimitive()) { - return context.getTranslated((PrimitiveType) type); - } else { - return (context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, type.fhirType()) + " "); - } + + switch (type.fhirType()) { + case "Coding": return displayCoding(type); + case "CodeableConcept": return displayCodeableConcept(type); + case "CodeableReference": return displayCodeableReference(type); + case "Identifier": return displayIdentifier(type); + case "HumanName": return displayHumanName(type); + case "Address": return displayAddress(type); + case "ContactPoint": return displayContactPoint(type); + case "Quantity": return displayQuantity(type); + case "Range": return displayRange(type); + case "Period": return displayPeriod(type); + case "Timing": return displayTiming(type); + case "SampledData": return displaySampledData(type); + case "ContactDetail": return displayContactDetail(type); + case "Annotation": return displayAnnotation(type); + case "Ratio": return displayRatio(type); + case "Reference" : return displayReference(type); + case "dateTime": + case "date" : + case "instant" : + return displayDateTime(type); + default: + if (type.isPrimitive()) { + return context.getTranslated(type); + } else if (Utilities.existsInList(type.fhirType(), "Meta", "Dosage", "Signature", "UsageContext", "RelatedArtifact", "ElementDefinition", "Base64BinaryType", "Attachment")) { + return ""; + } else { + return (context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, type.fhirType()) + " "); + } + } } - - protected String displayDateTime(BaseDateTimeType type) { + + private String displayAnnotation(ResourceWrapper type) { + return type.primitiveValue("text"); + } + + private String displayCodeableReference(ResourceWrapper type) { + if (type.has("reference")) { + return displayReference(type.child("reference")); + } else { + return displayCodeableConcept(type.child("concept")); + } + } + + + protected String displayReference(ResourceWrapper type) { + if (type.has("display")) { + return type.primitiveValue("display"); + } else if (type.has("reference")) { + // ResourceWithReference tr = resolveReference(res, r.getReference()); + // x.addText(tr == null ? r.getReference() : "?ngen-3"); // getDisplayForReference(tr.getReference())); + return "?ngen-3"; + } else { + return "?ngen-4?"; + } + } + + private String displayRatio(ResourceWrapper type) { + return displayQuantity(type.child("numerator"))+" / "+displayQuantity(type.child("denominator")); + } + + protected String displayDateTime(ResourceWrapper type) { if (!type.hasPrimitiveValue()) { return ""; } - + + BaseDateTimeType t = new DateTimeType(type.primitiveValue()); // relevant inputs in rendering context: // timeZone, dateTimeFormat, locale, mode // timezone - application specified timezone to use. @@ -605,13 +643,13 @@ public class DataRenderer extends Renderer implements CodeResolver { // null = default to ... depends on mode // mode - if rendering mode is technical, format defaults to XML format // locale - otherwise, format defaults to SHORT for the Locale (which defaults to default Locale) - if (isOnlyDate(type.getPrecision())) { - - DateTimeFormatter fmt = getDateFormatForPrecision(type); - LocalDate date = LocalDate.of(type.getYear(), type.getMonth()+1, type.getDay()); + if (isOnlyDate(t.getPrecision())) { + + DateTimeFormatter fmt = getDateFormatForPrecision(t); + LocalDate date = LocalDate.of(t.getYear(), t.getMonth()+1, t.getDay()); return fmt.format(date); } - + DateTimeFormatter fmt = context.getDateTimeFormat(); if (fmt == null) { if (context.isTechnicalMode()) { @@ -620,14 +658,14 @@ public class DataRenderer extends Renderer implements CodeResolver { fmt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(context.getLocale()); } } - ZonedDateTime zdt = ZonedDateTime.parse(type.primitiveValue()); + ZonedDateTime zdt = ZonedDateTime.parse(t.primitiveValue()); ZoneId zone = context.getTimeZoneId(); if (zone != null) { zdt = zdt.withZoneSameInstant(zone); } return fmt.format(zdt); } - + private DateTimeFormatter getDateFormatForPrecision(BaseDateTimeType type) { DateTimeFormatter fmt = getContextDateFormat(type); if (fmt != null) { @@ -653,7 +691,7 @@ public class DataRenderer extends Renderer implements CodeResolver { } } } - + private DateTimeFormatter getContextDateFormat(BaseDateTimeType type) { switch (type.getPrecision()) { case YEAR: @@ -664,240 +702,379 @@ public class DataRenderer extends Renderer implements CodeResolver { return context.getDateFormat(); } } - + private boolean isOnlyDate(TemporalPrecisionEnum temporalPrecisionEnum) { return temporalPrecisionEnum == TemporalPrecisionEnum.YEAR || temporalPrecisionEnum == TemporalPrecisionEnum.MONTH || temporalPrecisionEnum == TemporalPrecisionEnum.DAY; } - - public String display(BaseWrapper type) { - return (context.formatPhrase(RenderingContext.DATA_REND_TO_DO)); - } - - public void render(XhtmlNode x, BaseWrapper type) throws FHIRFormatError, DefinitionException, IOException { - Base base = null; - try { - base = type.getBase(); - } catch (FHIRException | IOException e) { - x.tx(context.formatPhrase(RenderingContext.DATA_REND_ERROR, e.getMessage()) + " "); // this shouldn't happen - it's an error in the library itself - return; - } - if (base instanceof DataType) { - render(x, (DataType) base); - } else { - x.tx(context.formatPhrase(RenderingContext.DATA_REND_TO_DO, base.fhirType())); - } - } - - public void renderBase(XhtmlNode x, Base b) throws FHIRFormatError, DefinitionException, IOException { + + + // public void renderDataType(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + //// Base base = null; + //// try { + //// base = type.getBase(); + //// } catch (FHIRException | IOException e) { + //// x.tx(context.formatPhrase(RenderingContext.DATA_REND_ERROR, e.getMessage()) + " "); // this shouldn't happen - it's an error in the library itself + //// return; + //// } + //// if (base instanceof DataType) { + //// render(x, (DataType) base); + //// } else { + //// x.tx(context.formatPhrase(RenderingContext.DATA_REND_TO_DO, base.fhirType())); + //// } + // } + + public void renderBase(RenderingStatus status, XhtmlNode x, Base b) throws FHIRFormatError, DefinitionException, IOException { if (b instanceof DataType) { - render(x, (DataType) b); + renderDataType(status, x, wrapNC((DataType) b)); } else { x.tx(context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, b.fhirType()) + " "); } } - - public void render(XhtmlNode x, DataType type) throws FHIRFormatError, DefinitionException, IOException { - if (type instanceof BaseDateTimeType) { - x.tx(displayDateTime((BaseDateTimeType) type)); - } else if (type instanceof UriType) { - renderUri(x, (UriType) type); - } else if (type instanceof Annotation) { - renderAnnotation(x, (Annotation) type); - } else if (type instanceof Coding) { - renderCodingWithDetails(x, (Coding) type); - } else if (type instanceof CodeableConcept) { - renderCodeableConcept(x, (CodeableConcept) type); - } else if (type instanceof Identifier) { - renderIdentifier(x, (Identifier) type); - } else if (type instanceof HumanName) { - renderHumanName(x, (HumanName) type); - } else if (type instanceof Address) { - renderAddress(x, (Address) type); - } else if (type instanceof Expression) { - renderExpression(x, (Expression) type); - } else if (type instanceof Money) { - renderMoney(x, (Money) type); - } else if (type instanceof ContactPoint) { - renderContactPoint(x, (ContactPoint) type); - } else if (type instanceof Quantity) { - renderQuantity(x, (Quantity) type); - } else if (type instanceof Range) { - renderRange(x, (Range) type); - } else if (type instanceof Period) { - renderPeriod(x, (Period) type); - } else if (type instanceof Timing) { - renderTiming(x, (Timing) type); - } else if (type instanceof SampledData) { - renderSampledData(x, (SampledData) type); - } else if (type instanceof Reference) { - renderReference(x, (Reference) type); - } else if (type instanceof UsageContext) { - renderUsageContext(x, (UsageContext) type); - } else if (type instanceof CodeableReference) { - CodeableReference cr = (CodeableReference) type; - if (cr.hasConcept()) { - renderCodeableConcept(x, cr.getConcept()); + + public boolean renderDataType(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + return renderDataType(status, null, x, type); + } + public boolean renderDataType(RenderingStatus status, XhtmlNode parent, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + switch (type.fhirType()) { + case "dateTime": + case "date" : + case "instant" : + renderDateTime(status, x, type); + break; + case "uri" : + case "url" : + renderUri(status, x, type); + break; + case "canonical" : + renderCanonical(status, x, type); + break; + case "Annotation": + renderAnnotation(status, x, type); + break; + case "Coding": + renderCodingWithDetails(status, x, type); + break; + case "CodeableConcept": + renderCodeableConcept(status, x, type); + break; + case "Identifier": + renderIdentifier(status, x, type); + break; + case "HumanName": + renderHumanName(status, x, type); + break; + case "Address": + renderAddress(status, x, type); + break; + case "Expression": + renderExpression(status, x, type); + break; + case "Money": + renderMoney(status, x, type); + break; + case "ContactPoint": + renderContactPoint(status, x, type); + break; + case "Quantity": + renderQuantity(status, x, type); + break; + case "Range": + renderRange(status, x, type); + break; + case "Period": + renderPeriod(status, x, type); + break; + case "Timing": + renderTiming(status, x, type); + break; + case "SampledData": + renderSampledData(status, x, type); + break; + case "Reference": + renderReference(status, x, type); + break; + case "UsageContext": + renderUsageContext(status, x, type); + break; + case "ContactDetail": + renderContactDetail(status, x, type); + break; + case "Ratio": + renderRatio(status, x, type); + break; + case "CodeableReference": + if (type.has("concept")) { + renderCodeableConcept(status, x, type.child("concept")); } else { - renderReference(x, cr.getReference()); + renderReference(status, x, type.child("reference")); } - } else if (type instanceof MarkdownType) { - addMarkdown(x, context.getTranslated((MarkdownType) type)); - } else if (type instanceof Base64BinaryType) { - Base64BinaryType b64 = (Base64BinaryType) type; - x.tx(context.formatPhrase(RenderingContext.DATA_REND_BASE64, (b64.getValue() == null ? "0" : b64.getValue().length))); - } else if (type.isPrimitive()) { - x.tx(context.getTranslated((PrimitiveType) type)); - } else { - x.tx(context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, type.fhirType()) + " "); - } - } - - protected void renderReference(XhtmlNode x, Reference ref) { - if (ref.hasDisplay()) { - x.tx(context.getTranslated(ref.getDisplayElement())); - } else if (ref.hasReference()) { - x.tx(ref.getReference()); - } else { - x.tx("??"); - } - } - - public void renderDateTime(XhtmlNode x, Base e) { - if (e.hasPrimitiveValue()) { - x.addText(displayDateTime((DateTimeType) e)); - } - } - - public void renderDate(XhtmlNode x, Base e) { - if (e.hasPrimitiveValue()) { - x.addText(displayDateTime((DateType) e)); - } - } - - public void renderDateTime(XhtmlNode x, String s) { - if (s != null) { - DateTimeType dt = new DateTimeType(s); - x.addText(displayDateTime(dt)); - } - } - - protected void renderUri(XhtmlNode x, UriType uri) { - if (uri.getValue().startsWith("mailto:")) { - x.ah(uri.getValue()).addText(uri.getValue().substring(7)); - } else { - Resource r = context.getContext().fetchResource(Resource.class, uri.getValue()); - if (r != null && r.getWebPath() != null) { - if (r instanceof CanonicalResource) { - x.ah(r.getWebPath()).addText(crPresent((CanonicalResource) r)); - } else { - x.ah(r.getWebPath()).addText(uri.getValue()); - } + break; + case "code": + x.tx(getTranslatedCode(type)); + break; + case "markdown": + addMarkdown(parent == null ? x : parent, context.getTranslated(type)); // note parent not focus, because of paragraph issues and markdown + break; + case "base64Binary": + int length = type.primitiveValue().length(); + if (length >= context.getBase64Limit()) { + x.tx(context.formatPhrase(RenderingContext.DATA_REND_BASE64, length)); + } else { + x.code(type.primitiveValue()); + + } + break; + default: + if (type.isPrimitive()) { + if (!renderPrimitiveWithNoValue(status, x, type)) { + x.tx(context.getTranslated(type)); + } } else { - String url = context.getResolver() != null ? context.getResolver().resolveUri(context, uri.getValue()) : null; - if (url != null) { - x.ah(url).addText(uri.getValue()); - } else if (Utilities.isAbsoluteUrlLinkable(uri.getValue()) && !(uri instanceof IdType)) { - x.ah(uri.getValue()).addText(uri.getValue()); - } else { - x.addText(uri.getValue()); - } - } + x.tx(context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, type.fhirType()) + " "); + return false; + } + } + return true; + } + + // overide in ResourceRenderer + protected void renderCanonical(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + renderUri(status, x, type); + } + + private void renderRatio(RenderingStatus status, XhtmlNode x, ResourceWrapper type) { + renderQuantity(status, x, type.child("numerator")); + x.tx("/"); + renderQuantity(status, x, type.child("denominator")); + } + + private void renderContactDetail(RenderingStatus status, XhtmlNode x, ResourceWrapper cd) { + if (cd.has("name")) { + x.tx(cd.primitiveValue("name")+": "); + } + boolean first = true; + for (ResourceWrapper c : cd.children("telecom")) { + if (first) first = false; else x.tx(","); + renderContactPoint(status, x, c); + } + } + + private void renderDateTime(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + if (!renderPrimitiveWithNoValue(status, x, type)) { + x.tx(displayDateTime(type)); + } + } + + /** + * this is overriden in ResourceRenderer where a better rendering is performed + * @param status + * @param x + * @param ref + * @throws IOException + * @throws DefinitionException + * @throws FHIRFormatError + */ + protected void renderReference(RenderingStatus status, XhtmlNode x, ResourceWrapper ref) throws FHIRFormatError, DefinitionException, IOException { + if (ref.has("display")) { + x.tx(context.getTranslated(ref.child("display"))); + } else if (ref.has("reference")) { + x.tx(ref.primitiveValue("reference")); + } else { + x.tx("??"); } } - - protected void renderUri(XhtmlNode x, UriType uriD, String path, String id, Resource src) { - String uri = uriD.getValue(); - if (isCanonical(path)) { - x.code().tx(uri); - } else { - if (uri == null) { - x.b().tx(uri); - } else if (uri.startsWith("mailto:")) { - x.ah(uri).addText(uri.substring(7)); + // + // public void renderDateTime(RenderingStatus status, XhtmlNode x, Base e) { + // if (e.hasPrimitiveValue()) { + // x.addText(displayDateTime((DateTimeType) e)); + // } + // } + // + // public void renderDate(RenderingStatus status, XhtmlNode x, Base e) { + // if (e.hasPrimitiveValue()) { + // x.addText(displayDateTime((DateType) e)); + // } + // } + // + // public void renderDateTime(XhtmlNode x, String s) { + // if (s != null) { + // DateTimeType dt = new DateTimeType(s); + // x.addText(displayDateTime(dt)); + // } + // } + + + protected boolean renderPrimitiveWithNoValue(RenderingStatus status, XhtmlNode x, PrimitiveType prim) throws FHIRFormatError, DefinitionException, IOException { + if (prim.hasPrimitiveValue()) { + return false; + } + boolean first = true; + for (Extension ext : prim.getExtension()) { + if (first) first = false; else x.tx(", "); + String url = ext.getUrl(); + if (url.equals(ToolingExtensions.EXT_DAR)) { + x.tx("Absent because : "); + displayCode(x, wrapNC(ext.getValue())); + } else if (url.equals(ToolingExtensions.EXT_NF)) { + x.tx("Null because: "); + displayCode(x, wrapNC(ext.getValue())); + } else if (url.equals(ToolingExtensions.EXT_OT)) { + x.code().tx("Text: "); + displayCode(x, wrapNC(ext.getValue())); + } else if (url.equals(ToolingExtensions.EXT_CQF_EXP)) { + x.code().tx("Value calculated by: "); + renderExpression(status, x, wrapNC(ext.getValue())); + } else { + StructureDefinition def = context.getContext().fetchResource(StructureDefinition.class, url); + if (def == null) { + x.code().tx(tail(url)+": "); + } else { + x.code().tx(def.present()+": "); + } + renderDataType(status, x, wrapNC(ext.getValue())); + } + } + status.setExtensions(true); + return true; + } + + protected boolean renderPrimitiveWithNoValue(RenderingStatus status, XhtmlNode x, ResourceWrapper prim) throws FHIRFormatError, DefinitionException, IOException { + if (prim.hasPrimitiveValue()) { + return false; + } + boolean first = true; + for (ResourceWrapper ext : prim.extensions()) { + if (first) first = false; else x.tx(", "); + String url = ext.primitiveValue("url"); + if (url.equals(ToolingExtensions.EXT_DAR)) { + x.tx("Absent because : "); + displayCode(x, ext.child("value")); + } else if (url.equals(ToolingExtensions.EXT_NF)) { + x.tx("Null because: "); + displayCode(x, ext.child("value")); + } else if (url.equals(ToolingExtensions.EXT_OT)) { + x.code().tx("Text: "); + displayCode(x, ext.child("value")); + } else if (url.equals(ToolingExtensions.EXT_CQF_EXP)) { + x.code().tx("Value calculated by: "); + renderExpression(status, x, ext.child("value")); + } else { + StructureDefinition def = context.getContext().fetchResource(StructureDefinition.class, url); + if (def == null) { + x.code().tx(tail(url)+": "); + } else { + x.code().tx(def.present()+": "); + } + renderDataType(status, x, ext.child("value")); + } + } + status.setExtensions(true); + return true; + } + + private String tail(String url) { + return url.contains("/") ? url.substring(url.lastIndexOf("/")+1) : url; + } + + private void displayCode(XhtmlNode x, ResourceWrapper code) { + x.tx(code.primitiveValue()); + } + + protected void renderUri(RenderingStatus status, XhtmlNode x, ResourceWrapper uri) throws FHIRFormatError, DefinitionException, IOException { + if (!renderPrimitiveWithNoValue(status, x, uri)) { + String v = uri.primitiveValue(); + if ("/Binary/1-note".equals(v)) { + DebugUtilities.breakpoint(); + } + + + if (context.getContextUtilities().isResource(v)) { + v = "http://hl7.org/fhir/"+v; + } + if (v.startsWith("mailto:")) { + x.ah(v).addText(v.substring(7)); } else { - Resource target = context.getContext().fetchResource(Resource.class, uri, src); - if (target != null && target.hasWebPath()) { - String title = target instanceof CanonicalResource ? crPresent((CanonicalResource) target) : uri; - x.ah(target.getWebPath()).addText(title); - } else { - String url = context.getResolver() != null ? context.getResolver().resolveUri(context, uri) : null; - if (url != null) { - x.ah(url).addText(uri); - } else if (uri.contains("|")) { - x.ah(uri.substring(0, uri.indexOf("|"))).addText(uri); - } else if (uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("ftp:")) { - x.ah(uri).addText(uri); + Resource r = context.getContext().fetchResource(Resource.class, v); + if (r != null && r.getWebPath() != null) { + if (r instanceof CanonicalResource) { + x.ah(context.prefixLocalHref(r.getWebPath())).addText(crPresent((CanonicalResource) r)); } else { - x.code().addText(uri); + x.ah(context.prefixLocalHref(r.getWebPath())).addText(v); + } + } else { + String url = context.getResolver() != null ? context.getResolver().resolveUri(context, v) : null; + if (url != null) { + x.ah(context.prefixLocalHref(url)).addText(v); + } else if (Utilities.isAbsoluteUrlLinkable(v) && !uri.fhirType().equals("id")) { + x.ah(context.prefixLocalHref(v)).addText(v); + } else { + x.addText(v); } } } - } + } } - - protected void renderAnnotation(XhtmlNode x, Annotation annot) { - renderAnnotation(x, annot, false); - } - - protected void renderAnnotation(XhtmlNode x, Annotation a, boolean showCodeDetails) throws FHIRException { + + protected void renderAnnotation(RenderingStatus status, XhtmlNode x, ResourceWrapper a) throws FHIRException { StringBuilder b = new StringBuilder(); - if (a.hasText()) { - b.append(context.getTranslated(a.getTextElement())); + if (a.has("text")) { + b.append(context.getTranslated(a.child("text"))); } - - if (a.hasText() && (a.hasAuthor() || a.hasTimeElement())) { + + if (a.has("text") && (a.has("author") || a.has("time"))) { b.append(" ("); } - - if (a.hasAuthor()) { + + if (a.has("author")) { b.append(context.formatPhrase(RenderingContext.DATA_REND_BY) + " "); - if (a.hasAuthorReference()) { - b.append(a.getAuthorReference().getReference()); - } else if (a.hasAuthorStringType()) { - b.append(context.getTranslated(a.getAuthorStringType())); + ResourceWrapper auth = a.child("author"); + if (auth.fhirType().equals("Reference")) { + b.append(auth.primitiveValue("reference")); + } else if (auth.fhirType().equals("string")) { + b.append(context.getTranslated(auth)); } } - - - if (a.hasTimeElement()) { + + + if (a.has("time")) { if (b.length() > 0) { b.append(" "); } - b.append("@").append(a.getTimeElement().toHumanDisplay()); + b.append("@").append(displayDateTime(a.child("time"))); } - if (a.hasText() && (a.hasAuthor() || a.hasTimeElement())) { + if (a.has("text") && (a.has("author") || a.has("time"))) { b.append(")"); } - - + + x.addText(b.toString()); } - - public String displayCoding(Coding c) { + + public String displayCoding(ResourceWrapper c) { String s = ""; if (context.isTechnicalMode()) { - s = context.getTranslated(c.getDisplayElement()); + s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) { - s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); } if (Utilities.noString(s)) { - s = displayCodeTriple(c.getSystem(), c.getVersion(), c.getCode()); - } else if (c.hasSystem()) { - s = s + " ("+displayCodeTriple(c.getSystem(), c.getVersion(), c.getCode())+")"; - } else if (c.hasCode()) { - s = s + " ("+c.getCode()+")"; + s = displayCodeTriple(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); + } else if (c.has("system")) { + s = s + " ("+displayCodeTriple(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code"))+")"; + } else if (c.has("code")) { + s = s + " ("+c.primitiveValue("code")+")"; } } else { - if (c.hasDisplayElement()) - return context.getTranslated(c.getDisplayElement()); - if (Utilities.noString(s)) - s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); - if (Utilities.noString(s)) - s = c.getCode(); + if (c.has("display")) + return context.getTranslated(c.child("display")); + if (Utilities.noString(s)) + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); + if (Utilities.noString(s)) + s = c.primitiveValue("code"); } return s; } - + private String displayCodeSource(String system, String version) { String s = displaySystem(system); if (version != null) { @@ -905,7 +1082,7 @@ public class DataRenderer extends Renderer implements CodeResolver { } return s; } - + private String displayCodeTriple(String system, String version, String code) { if (system == null) { if (code == null) { @@ -921,24 +1098,20 @@ public class DataRenderer extends Renderer implements CodeResolver { return s; } } - + public String displayCoding(List list) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (Coding c : list) { - b.append(displayCoding(c)); + b.append(displayCoding(wrapNC(c))); } return b.toString(); } - - protected void renderCoding(XhtmlNode x, Coding c) { - renderCoding(x, c, false); - } - + protected void renderCoding(HierarchicalTableGenerator gen, List pieces, Coding c) { if (c.isEmpty()) { return; } - + String url = getLinkForSystem(c.getSystem(), c.getVersion()); String name = displayCodeSource(c.getSystem(), c.getVersion()); if (!Utilities.noString(url)) { @@ -955,7 +1128,29 @@ public class DataRenderer extends Renderer implements CodeResolver { pieces.add(gen.new Piece(null, " \""+s+"\"", null)); } } - + + protected void renderCoding(HierarchicalTableGenerator gen, List pieces, ResourceWrapper c) { + if (c.isEmpty()) { + return; + } + + String url = getLinkForSystem(c.primitiveValue("system"), c.primitiveValue("version")); + String name = displayCodeSource(c.primitiveValue("system"), c.primitiveValue("version")); + if (!Utilities.noString(url)) { + pieces.add(gen.new Piece(url, name, c.primitiveValue("system")+(c.has("version") ? "#"+c.primitiveValue("version") : ""))); + } else { + pieces.add(gen.new Piece(null, name, c.primitiveValue("system")+(c.has("version") ? "#"+c.primitiveValue("version") : ""))); + } + pieces.add(gen.new Piece(null, "#"+c.primitiveValue("code"), null)); + String s = context.getTranslated(c.child("display")); + if (Utilities.noString(s)) { + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); + } + if (!Utilities.noString(s)) { + pieces.add(gen.new Piece(null, " \""+s+"\"", null)); + } + } + private String getLinkForSystem(String system, String version) { if ("http://snomed.info/sct".equals(system)) { return "https://browser.ihtsdotools.org/"; @@ -975,7 +1170,7 @@ public class DataRenderer extends Renderer implements CodeResolver { return null; } } - + protected String getLinkForCode(String system, String version, String code) { if ("http://snomed.info/sct".equals(system)) { if (!Utilities.noString(code)) { @@ -1013,35 +1208,39 @@ public class DataRenderer extends Renderer implements CodeResolver { } return null; } - + public CodeResolution resolveCode(String system, String code) { return resolveCode(new Coding().setSystem(system).setCode(code)); } - - public CodeResolution resolveCode(Coding c) { + + public CodeResolution resolveCode(ResourceWrapper c) { String systemName; String systemLink; String link; String display = null; String hint; - - if (c.hasDisplayElement()) - display = context.getTranslated(c.getDisplayElement()); + + if (c.has("display")) + display = context.getTranslated(c.child("display")); if (Utilities.noString(display)) - display = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); + display = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (Utilities.noString(display)) { - display = c.getCode(); + display = c.primitiveValue("code"); } - - CodeSystem cs = context.getWorker().fetchCodeSystem(c.getSystem()); + + CodeSystem cs = context.getWorker().fetchCodeSystem(c.primitiveValue("system")); systemLink = cs != null ? cs.getWebPath() : null; - systemName = cs != null ? crPresent(cs) : displaySystem(c.getSystem()); - link = getLinkForCode(c.getSystem(), c.getVersion(), c.getCode()); - - hint = systemName+": "+display+(c.hasVersion() ? " "+ context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.getVersion(), ")") : ""); + systemName = cs != null ? crPresent(cs) : displaySystem(c.primitiveValue("system")); + link = getLinkForCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); + + hint = systemName+": "+display+(c.has("version") ? " "+ context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.primitiveValue("version"), ")") : ""); return new CodeResolution(systemName, systemLink, link, display, hint); } - + + public CodeResolution resolveCode(Coding code) { + return resolveCode(wrapNC(code)); + } + public CodeResolution resolveCode(CodeableConcept code) { if (code.hasCoding()) { return resolveCode(code.getCodingFirstRep()); @@ -1049,451 +1248,449 @@ public class DataRenderer extends Renderer implements CodeResolver { return new CodeResolution(null, null, null, code.getText(), code.getText()); } } - protected void renderCodingWithDetails(XhtmlNode x, Coding c) { + protected void renderCodingWithDetails(RenderingStatus status, XhtmlNode x, ResourceWrapper c) { String s = ""; - if (c.hasDisplayElement()) - s = context.getTranslated(c.getDisplayElement()); + if (c.has("display")) + s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) - s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); - - CodeSystem cs = context.getWorker().fetchCodeSystem(c.getSystem()); - - String sn = cs != null ? crPresent(cs) : displaySystem(c.getSystem()); - String link = getLinkForCode(c.getSystem(), c.getVersion(), c.getCode()); + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); + + CodeSystem cs = context.getWorker().fetchCodeSystem(c.primitiveValue("system")); + + String sn = cs != null ? crPresent(cs) : displaySystem(c.primitiveValue("system")); + String link = getLinkForCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (link != null) { - x.ah(link).tx(sn); + x.ah(context.prefixLocalHref(link)).tx(sn); } else { x.tx(sn); } - + x.tx(" "); - x.tx(c.getCode()); + x.tx(c.primitiveValue("code")); if (!Utilities.noString(s)) { x.tx(": "); x.tx(s); } - if (c.hasVersion()) { - x.tx(" "+context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.getVersion(), ")")); + if (c.has("version")) { + x.tx(" "+context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.primitiveValue("version"), ")")); } } - - protected void renderCoding(XhtmlNode x, Coding c, boolean showCodeDetails) { + + protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c) { String s = ""; - if (c.hasDisplayElement()) - s = context.getTranslated(c.getDisplayElement()); + if (c.has("display")) + s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) - s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); - + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); + if (Utilities.noString(s)) - s = c.getCode(); - - if (showCodeDetails) { - x.addText(s+" "+context.formatPhrase(RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.getSystem()), c.getCode(), " = '", lookupCode(c.getSystem(), c.getVersion(), c.getCode()), c.getDisplay(), "')")); + s = c.primitiveValue("code"); + + if (context.isTechnicalMode()) { + x.addText(s+" "+context.formatPhrase(RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.primitiveValue("system")), c.primitiveValue("code"), " = '", lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")), c.primitiveValue("display"), "')")); } else - x.span(null, "{"+c.getSystem()+" "+c.getCode()+"}").addText(s); + x.span(null, "{"+c.primitiveValue("system")+" "+c.primitiveValue("code")+"}").addText(s); } - - public String displayCodeableConcept(CodeableConcept cc) { - String s = context.getTranslated(cc.getTextElement()); + + public String displayCodeableConcept(ResourceWrapper cc) { + String s = context.getTranslated(cc.child("Text")); if (Utilities.noString(s)) { - for (Coding c : cc.getCoding()) { - if (c.hasDisplayElement()) { - s = context.getTranslated(c.getDisplayElement()); + for (ResourceWrapper c : cc.children("coding")) { + if (c.has("display")) { + s = context.getTranslated(c.child("display")); break; } } } if (Utilities.noString(s)) { // still? ok, let's try looking it up - for (Coding c : cc.getCoding()) { - if (c.hasCode() && c.hasSystem()) { - s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); + for (ResourceWrapper c : cc.children("coding")) { + if (c.has("code") && c.has("system")) { + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (!Utilities.noString(s)) break; } } } - + if (Utilities.noString(s)) { - if (cc.getCoding().isEmpty()) + if (!cc.has("coding")) s = ""; else - s = cc.getCoding().get(0).getCode(); + s = cc.children("coding").get(0).primitiveValue("code"); } return s; } - - protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc) throws FHIRFormatError, DefinitionException, IOException { - renderCodeableConcept(x, cc, false); - } - - protected void renderCodeableReference(XhtmlNode x, CodeableReference e, boolean showCodeDetails) throws FHIRFormatError, DefinitionException, IOException { - if (e.hasConcept()) { - renderCodeableConcept(x, e.getConcept(), showCodeDetails); + + + protected void renderCodeableReference(RenderingStatus status, XhtmlNode x, ResourceWrapper e) throws FHIRFormatError, DefinitionException, IOException { + if (e.has("concept")) { + renderCodeableConcept(status, x, e.child("concept")); } - if (e.hasReference()) { - renderReference(x, e.getReference()); + if (e.has("reference")) { + renderReference(status, x, e.child("reference")); } } - - protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc, boolean showCodeDetails) throws FHIRFormatError, DefinitionException, IOException { + + protected void renderCodeableConcept(RenderingStatus status, XhtmlNode x, ResourceWrapper cc) throws FHIRFormatError, DefinitionException, IOException { if (cc.isEmpty()) { return; } - - String s = context.getTranslated(cc.getTextElement()); + + String s = context.getTranslated(cc.child("text")); if (Utilities.noString(s)) { - for (Coding c : cc.getCoding()) { - if (c.hasDisplayElement()) { - s = context.getTranslated(c.getDisplayElement()); + for (ResourceWrapper c : cc.children("coding")) { + if (c.has("display")) { + s = context.getTranslated(c.child("display")); break; } } } if (Utilities.noString(s)) { // still? ok, let's try looking it up - for (Coding c : cc.getCoding()) { - if (c.hasCodeElement() && c.hasSystemElement()) { - s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); + for (ResourceWrapper c : cc.children("coding")) { + if (c.has("code") && c.has("system")) { + s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (!Utilities.noString(s)) break; } } } - + if (Utilities.noString(s)) { - if (cc.getCoding().isEmpty()) + if (!cc.has("coding")) s = ""; else - s = cc.getCoding().get(0).getCode(); + s = cc.children("coding").get(0).primitiveValue("code"); } - - if (showCodeDetails) { + + if (status.isShowCodeDetails()) { x.addText(s+" "); XhtmlNode sp = x.span("background: LightGoldenRodYellow; margin: 4px; border: 1px solid khaki", null); sp.tx(" ("); boolean first = true; - for (Coding c : cc.getCoding()) { + for (ResourceWrapper c : cc.children("coding")) { if (first) { first = false; } else { sp.tx("; "); } - String url = getLinkForSystem(c.getSystem(), c.getVersion()); + String url = getLinkForSystem(c.primitiveValue("system"), c.primitiveValue("version")); if (url != null) { - sp.ah(url).tx(displayCodeSource(c.getSystem(), c.getVersion())); + sp.ah(context.prefixLocalHref(url)).tx(displayCodeSource(c.primitiveValue("system"), c.primitiveValue("version"))); } else { - sp.tx(displayCodeSource(c.getSystem(), c.getVersion())); + sp.tx(displayCodeSource(c.primitiveValue("system"), c.primitiveValue("version"))); } - if (c.hasCode()) { - sp.tx("#"+c.getCode()); + if (c.has("code")) { + sp.tx("#"+c.primitiveValue("code")); } - if (c.hasDisplay() && !s.equals(c.getDisplay())) { - sp.tx(" \""+context.getTranslated(c.getDisplayElement())+"\""); + if (c.has("display") && !s.equals(c.primitiveValue("display"))) { + sp.tx(" \""+context.getTranslated(c.child("display"))+"\""); } } if (hasRenderableExtensions(cc)) { if (!first) { sp.tx("; "); } - renderExtensionsInText(sp, cc, ";"); + renderExtensionsInText(status, sp, cc, ";"); } sp.tx(")"); } else { - + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - for (Coding c : cc.getCoding()) { - if (c.hasCodeElement() && c.hasSystemElement()) { - b.append("{"+c.getSystem()+" "+c.getCode()+"}"); + for (ResourceWrapper c : cc.children("coding")) { + if (c.has("code") && c.has("system")) { + b.append("{"+c.primitiveValue("system")+" "+c.primitiveValue("code")+"}"); } } - + x.span(null, context.formatPhrase(RenderingContext.DATA_REND_CODES) +b.toString()).addText(s); } } - - protected String displayIdentifier(Identifier ii) { - String s = Utilities.noString(ii.getValue()) ? "?ngen-9?" : ii.getValue(); - if ("urn:ietf:rfc:3986".equals(ii.getSystem()) && s.startsWith("urn:oid:")) { + + protected String displayIdentifier(ResourceWrapper ii) { + String s = Utilities.noString(ii.primitiveValue("value")) ? "?ngen-9?" : ii.primitiveValue("value"); + if ("urn:ietf:rfc:3986".equals(ii.primitiveValue("system")) && s.startsWith("urn:oid:")) { s = "OID:"+s.substring(8); - } else if ("urn:ietf:rfc:3986".equals(ii.getSystem()) && s.startsWith("urn:uuid:")) { + } else if ("urn:ietf:rfc:3986".equals(ii.primitiveValue("system")) && s.startsWith("urn:uuid:")) { s = "UUID:"+s.substring(9); } else { - NamingSystem ns = context.getContext().getNSUrlMap().get(ii.getSystem()); + NamingSystem ns = context.getContext().getNSUrlMap().get(ii.primitiveValue("system")); if (ns != null) { s = crPresent(ns)+"#"+s; } - if (ii.hasType()) { - if (ii.getType().hasText()) - s = context.getTranslated(ii.getType().getTextElement())+":\u00A0"+s; - else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay()) - s = context.getTranslated(ii.getType().getCoding().get(0).getDisplayElement())+": "+s; - else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasCode()) - s = lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getVersion(), ii.getType().getCoding().get(0).getCode())+": "+s; - } else if (ii.hasSystem()) { - s = ii.getSystem()+"#"+s; + if (ii.has("type")) { + ResourceWrapper type = ii.child("type"); + if (type.has("text")) + s = context.getTranslated(type.child("text"))+":\u00A0"+s; + else if (type.has("coding") && type.children("coding").get(0).has("display")) + s = context.getTranslated(type.children("coding").get(0).child("display"))+": "+s; + else if (type.has("coding") && type.children("coding").get(0).has("code")) + s = lookupCode(type.children("coding").get(0).primitiveValue("system"), type.children("coding").get(0).primitiveValue("version"), type.children("coding").get(0).primitiveValue("code")); + } else if (ii.has("system")) { + s = ii.primitiveValue("system")+"#"+s; } } - - if (ii.hasUse() || ii.hasPeriod()) { + + if (ii.has("use") || ii.has("period")) { s = s + "\u00A0("; - if (ii.hasUse()) { - s = s + "use:\u00A0"+ii.getUse().toCode(); + if (ii.has("use")) { + s = s + "use:\u00A0"+ii.primitiveValue("use"); } - if (ii.hasUse() && ii.hasPeriod()) { + if (ii.has("use") || ii.has("period")) { s = s + ",\u00A0"; } - if (ii.hasPeriod()) { - s = s + "period:\u00A0"+displayPeriod(ii.getPeriod()); + if (ii.has("period")) { + s = s + "period:\u00A0"+displayPeriod(ii.child("period")); } s = s + ")"; } return s; } - - protected void renderIdentifier(XhtmlNode x, Identifier ii) { - if (ii.hasType()) { - if (ii.getType().hasText()) { - x.tx(context.getTranslated(ii.getType().getTextElement())); - } else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay()) { - x.tx(context.getTranslated(ii.getType().getCoding().get(0).getDisplayElement())); - } else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasCode()) { - x.tx(lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getVersion(), ii.getType().getCoding().get(0).getCode())); + + protected void renderIdentifier(RenderingStatus status, XhtmlNode x, ResourceWrapper ii) { + if (ii.has("type")) { + ResourceWrapper type = ii.child("type"); + if (type.has("text")) { + x.tx(context.getTranslated(type.child("text"))); + } else if (type.has("coding") && type.children("coding").get(0).has("display")) { + x.tx(context.getTranslated(type.children("coding").get(0).child("display"))); + } else if (type.has("coding") && type.children("coding").get(0).has("code")) { + x.tx(lookupCode(type.children("coding").get(0).primitiveValue("system"), type.children("coding").get(0).primitiveValue("version"), type.children("coding").get(0).primitiveValue("code"))); } x.tx("/"); - } else if (ii.hasSystem()) { - NamingSystem ns = context.getContext().getNSUrlMap().get(ii.getSystem()); + } else if (ii.has("system")) { + NamingSystem ns = context.getContext().getNSUrlMap().get(ii.primitiveValue("system")); if (ns != null) { if (ns.hasWebPath()) { - x.ah(ns.getWebPath(), ns.getDescription()).tx(crPresent(ns)); + x.ah(context.prefixLocalHref(ns.getWebPath()), ns.getDescription()).tx(crPresent(ns)); } else { x.tx(crPresent(ns)); } } else { - switch (ii.getSystem()) { + switch (ii.primitiveValue("system")) { case "urn:oid:2.51.1.3": x.ah("https://www.gs1.org/standards/id-keys/gln", context.formatPhrase(RenderingContext.DATA_REND_GLN)).tx("GLN"); break; default: - x.code(ii.getSystem()); + x.code(ii.primitiveValue("system")); } } x.tx("/"); } - x.tx(Utilities.noString(ii.getValue()) ? "?ngen-9?" : ii.getValue()); - - if (ii.hasUse() || ii.hasPeriod()) { + x.tx(Utilities.noString(ii.primitiveValue("value")) ? "?ngen-9?" : ii.primitiveValue("value")); + + if (ii.has("use") || ii.has("period")) { x.nbsp(); x.tx("("); - if (ii.hasUse()) { + if (ii.has("use")) { x.tx(context.formatPhrase(RenderingContext.DATA_REND_USE)); x.nbsp(); - x.tx(ii.getUse().toCode()); + x.tx(ii.primitiveValue("use")); } - if (ii.hasUse() && ii.hasPeriod()) { + if (ii.has("use") || ii.has("period")) { x.tx(","); x.nbsp(); } - if (ii.hasPeriod()) { + if (ii.has("period")) { x.tx(context.formatPhrase(RenderingContext.DATA_REND_PERIOD)); x.nbsp(); - x.tx(displayPeriod(ii.getPeriod())); + x.tx(displayPeriod(ii.child("period"))); } x.tx(")"); } } - - public static String displayHumanName(HumanName name) { + + public static String displayHumanName(ResourceWrapper name) { StringBuilder s = new StringBuilder(); - if (name.hasText()) - s.append(name.getText()); + if (name.has("text")) + s.append(name.primitiveValue("text")); else { - for (StringType p : name.getGiven()) { - s.append(p.getValue()); + for (ResourceWrapper p : name.children("given")) { + s.append(p.primitiveValue()); s.append(" "); } - if (name.hasFamily()) { - s.append(name.getFamily()); + if (name.has("family")) { + s.append(name.primitiveValue("family")); s.append(" "); } } - if (name.hasUse() && name.getUse() != NameUse.USUAL) - s.append("("+name.getUse().toString()+")"); + if (name.has("use") && !name.primitiveValue("use").equals("usual")) + s.append("("+name.primitiveValue("use")+")"); return s.toString(); } - - - protected void renderHumanName(XhtmlNode x, HumanName name) { + + + protected void renderHumanName(RenderingStatus status, XhtmlNode x, ResourceWrapper name) { StringBuilder s = new StringBuilder(); - if (name.hasText()) - s.append(context.getTranslated(name.getTextElement())); + if (name.has("text")) + s.append(context.getTranslated(name.child("text"))); else { - for (StringType p : name.getGiven()) { + for (ResourceWrapper p : name.children("given")) { s.append(context.getTranslated(p)); s.append(" "); } - if (name.hasFamily()) { - s.append(context.getTranslated(name.getFamilyElement())); + if (name.has("family")) { + s.append(context.getTranslated(name.child("family"))); s.append(" "); } } - if (name.hasUse() && name.getUse() != NameUse.USUAL) - s.append("("+context.getTranslatedCode(name.getUseElement(), "http://hl7.org/fhir/name-use")+")"); - + if (name.has("use") && !name.primitiveValue("use").equals("usual")) { + s.append("("+context.getTranslatedCode(name.primitiveValue("use"), "http://hl7.org/fhir/name-use")+")"); + } x.addText(s.toString()); } - - private String displayAddress(Address address) { + + private String displayAddress(ResourceWrapper address) { StringBuilder s = new StringBuilder(); - if (address.hasText()) - s.append(context.getTranslated(address.getTextElement())); + if (address.has("text")) + s.append(context.getTranslated(address.child("text"))); else { - for (StringType p : address.getLine()) { + for (ResourceWrapper p : address.children("line")) { s.append(context.getTranslated(p)); s.append(" "); } - if (address.hasCity()) { - s.append(context.getTranslated(address.getCityElement())); + if (address.has("city")) { + s.append(context.getTranslated(address.child("city"))); s.append(" "); } - if (address.hasState()) { - s.append(context.getTranslated(address.getStateElement())); + if (address.has("state")) { + s.append(context.getTranslated(address.child("state"))); s.append(" "); } - - if (address.hasPostalCode()) { - s.append(context.getTranslated(address.getPostalCodeElement())); + + if (address.has("postalCode")) { + s.append(context.getTranslated(address.child("postalCode"))); s.append(" "); } - - if (address.hasCountry()) { - s.append(context.getTranslated(address.getCountryElement())); + + if (address.has("country")) { + s.append(context.getTranslated(address.child("country"))); s.append(" "); } } - if (address.hasUse()) - s.append("("+address.getUse().toCode()+")"); + if (address.has("use")) { + s.append("("+address.primitiveValue("use")+")"); + } return s.toString(); } - - protected void renderAddress(XhtmlNode x, Address address) { + + protected void renderAddress(RenderingStatus status, XhtmlNode x, ResourceWrapper address) { x.addText(displayAddress(address)); } - - - public static String displayContactPoint(ContactPoint contact) { + + + public String displayContactPoint(ResourceWrapper contact) { StringBuilder s = new StringBuilder(); - s.append(describeSystem(contact.getSystem())); - if (Utilities.noString(contact.getValue())) + s.append(describeSystem(contact.primitiveValue("system"))); + if (Utilities.noString(contact.primitiveValue("value"))) s.append("-unknown-"); else - s.append(contact.getValue()); - if (contact.hasUse()) - s.append("("+contact.getUse().toString()+")"); + s.append(contact.primitiveValue("value")); + if (contact.has("use")) + s.append("("+getTranslatedCode(contact.child("use"))+")"); return s.toString(); } - - public static String displayContactDetail(ContactDetail contact) { + + public String displayContactDetail(ResourceWrapper contact) { CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder(); - for (ContactPoint cp : contact.getTelecom()) { + for (ResourceWrapper cp : contact.children("telecom")) { s.append(displayContactPoint(cp)); } - return contact.getName()+(s.length() == 0 ? "" : " ("+s.toString()+")"); + return contact.primitiveValue("name")+(s.length() == 0 ? "" : " ("+s.toString()+")"); } - + protected String getLocalizedBigDecimalValue(BigDecimal input, Currency c) { NumberFormat numberFormat = NumberFormat.getNumberInstance(context.getLocale()); numberFormat.setGroupingUsed(true); numberFormat.setMaximumFractionDigits(c.getDefaultFractionDigits()); numberFormat.setMinimumFractionDigits(c.getDefaultFractionDigits()); return numberFormat.format(input); -} - - protected void renderMoney(XhtmlNode x, Money money) { + } + + protected void renderMoney(RenderingStatus status, XhtmlNode x, ResourceWrapper money) { if (x.getName().equals("blockquote")) { x = x.para(); } - Currency c = money.hasCurrency() ? Currency.getInstance(money.getCurrency()) : null; + Currency c = money.has("currency") ? Currency.getInstance(money.primitiveValue("currency")) : null; if (c != null) { XhtmlNode s = x.span(null, c.getDisplayName()); s.tx(c.getSymbol(context.getLocale())); - s.tx(getLocalizedBigDecimalValue(money.getValue(), c)); + s.tx(getLocalizedBigDecimalValue(new BigDecimal(money.primitiveValue("value")), c)); x.tx(" ("+c.getCurrencyCode()+")"); } else { - if (money.getCurrency() != null) { - x.tx(money.getCurrency()); + if (money.has("currency")) { + x.tx(money.primitiveValue("currency")); } - x.tx(money.getValue().toPlainString()); + x.tx(money.primitiveValue("value")); } } - - protected void renderExpression(XhtmlNode x, Expression expr) { - // there's two parts: what the expression is, and how it's described. + + protected void renderExpression(RenderingStatus status, XhtmlNode x, ResourceWrapper expr) { + // there's two parts: what the expression is, and how it's described. // we start with what it is, and then how it's described XhtmlNode p = x; if (p.getName().equals("blockquote")) { p = p.para(); } - if (expr.hasExpression()) { - if (expr.hasReference()) { - p = x.ah(expr.getReference()); + if (expr.has("expression")) { + if (expr.has("reference")) { + p = x.ah(context.prefixLocalHref(expr.primitiveValue("reference"))); } XhtmlNode c = p; - if (expr.hasLanguage()) { - c = c.span(null, expr.getLanguage()); + if (expr.has("language")) { + c = c.span(null, expr.primitiveValue("language")); } - c.code().tx(expr.getExpression()); - } else if (expr.hasReference()) { - p.ah(expr.getReference()).tx(context.formatPhrase(RenderingContext.DATA_REND_SOURCE)); + c.code().tx(expr.primitiveValue("expression")); + } else if (expr.has("reference")) { + p.ah(context.prefixLocalHref(expr.primitiveValue("reference"))).tx(context.formatPhrase(RenderingContext.DATA_REND_SOURCE)); } - if (expr.hasName() || expr.hasDescription()) { + if (expr.has("name") || expr.has("description")) { p.tx("("); - if (expr.hasName()) { - p.b().tx(expr.getName()); + if (expr.has("name")) { + p.b().tx(expr.primitiveValue("name")); } - if (expr.hasDescription()) { + if (expr.has("description")) { p.tx("\""); - p.tx(context.getTranslated(expr.getDescriptionElement())); + p.tx(context.getTranslated(expr.child("description"))); p.tx("\""); } p.tx(")"); } } - - - protected void renderContactPoint(XhtmlNode x, ContactPoint contact) { + + + protected void renderContactPoint(RenderingStatus status, XhtmlNode x, ResourceWrapper contact) { if (contact != null) { - if (!contact.hasSystem()) { + if (!contact.has("system")) { x.addText(displayContactPoint(contact)); } else { - switch (contact.getSystem()) { - case EMAIL: - x.ah("mailto:"+contact.getValue()).tx(contact.getValue()); + String v = contact.primitiveValue("value"); + switch (contact.primitiveValue("system")) { + case "email": + x.ah("mailto:"+v).tx(v); break; - case FAX: + case "fax": x.addText(displayContactPoint(contact)); break; - case NULL: + case "other": x.addText(displayContactPoint(contact)); break; - case OTHER: + case "pager": x.addText(displayContactPoint(contact)); break; - case PAGER: - x.addText(displayContactPoint(contact)); - break; - case PHONE: - if (contact.hasValue() && contact.getValue() != null && contact.getValue().startsWith("+")) { - x.ah("tel:"+contact.getValue().replace(" ", "")).tx(contact.getValue()); + case "phone": + if (contact.has("value") && v != null && v.startsWith("+")) { + x.ah("tel:"+v.replace(" ", "")).tx(v); } else { x.addText(displayContactPoint(contact)); } break; - case SMS: + case "sms": x.addText(displayContactPoint(contact)); break; - case URL: - x.ah(contact.getValue()).tx(contact.getValue()); + case "url": + x.ah(context.prefixLocalHref(v)).tx(v); break; default: break; @@ -1501,7 +1698,7 @@ public class DataRenderer extends Renderer implements CodeResolver { } } } - + protected void displayContactPoint(XhtmlNode p, ContactPoint c) { if (c != null) { if (c.getSystem() == ContactPointSystem.PHONE) { @@ -1519,289 +1716,298 @@ public class DataRenderer extends Renderer implements CodeResolver { } } } - - protected void addTelecom(XhtmlNode p, ContactPoint c) { - if (c.getSystem() == ContactPointSystem.PHONE) { - p.tx(context.formatPhrase(RenderingContext.DATA_REND_PHONE, c.getValue()) + " "); - } else if (c.getSystem() == ContactPointSystem.FAX) { - p.tx(context.formatPhrase(RenderingContext.DATA_REND_FAX, c.getValue()) + " "); - } else if (c.getSystem() == ContactPointSystem.EMAIL) { - p.ah("mailto:"+c.getValue()).addText(c.getValue()); - } else if (c.getSystem() == ContactPointSystem.URL) { - if (c.getValue().length() > 30) - p.ah(c.getValue()).addText(c.getValue().substring(0, 30)+"..."); + + protected void addTelecom(XhtmlNode p, ResourceWrapper c) { + String sys = c.primitiveValue("system"); + String value = c.primitiveValue("value"); + if (sys.equals("phone")) { + p.tx(context.formatPhrase(RenderingContext.DATA_REND_PHONE, value) + " "); + } else if (sys.equals("fax")) { + p.tx(context.formatPhrase(RenderingContext.DATA_REND_FAX, value) + " "); + } else if (sys.equals("email")) { + p.ah("mailto:"+value).addText(value); + } else if (sys.equals("url")) { + if (value.length() > 30) + p.ah(context.prefixLocalHref(value)).addText(value.substring(0, 30)+"..."); else - p.ah(c.getValue()).addText(c.getValue()); + p.ah(context.prefixLocalHref(value)).addText(value); } } - private static String describeSystem(ContactPointSystem system) { + private static String describeSystem(String system) { if (system == null) return ""; switch (system) { - case PHONE: return "ph: "; - case FAX: return "fax: "; + case "phone": return "ph: "; + case "fax": return "fax: "; default: return ""; } } - - protected String displayQuantity(Quantity q) { + + protected String displayQuantity(ResourceWrapper q) { + if (q == null) { + return ""; + } StringBuilder s = new StringBuilder(); - - s.append(q.hasValue() ? q.getValue() : "?"); - if (q.hasUnit()) - s.append(" ").append(q.getUnit()); - else if (q.hasCode()) - s.append(" ").append(q.getCode()); - + + s.append(q.has("value") ? q.primitiveValue("value") : "?"); + if (q.has("unit")) + s.append(" ").append(q.primitiveValue("unit")); + else if (q.has("code")) + s.append(" ").append(q.primitiveValue("code")); + return s.toString(); } - - protected void renderQuantity(XhtmlNode x, Quantity q) { - renderQuantity(x, q, false); - } - - protected void renderQuantity(XhtmlNode x, Quantity q, boolean showCodeDetails) { - if (q.hasComparator()) - x.addText(q.getComparator().toCode()); - if (q.hasValue()) { - x.addText(context.getTranslated(q.getValueElement())); + + protected void renderQuantity(RenderingStatus status, XhtmlNode x, ResourceWrapper q) { + if (q.has("comparator")) + x.addText(q.primitiveValue("comparator")); + if (q.has("value")) { + x.addText(context.getTranslated(q.child("value"))); } - if (q.hasUnit()) - x.tx(" "+context.getTranslated(q.getUnitElement())); - else if (q.hasCode() && q.hasSystem()) { + if (q.has("unit")) + x.tx(" "+context.getTranslated(q.child("unit"))); + else if (q.has("code") && q.has("system")) { // if there's a code there *shall* be a system, so if we've got one and not the other, things are invalid and we won't bother trying to render - if (q.hasSystem() && q.getSystem().equals("http://unitsofmeasure.org")) - x.tx(" "+q.getCode()); + if (q.has("system") && q.primitiveValue("system").equals("http://unitsofmeasure.org")) + x.tx(" "+q.primitiveValue("code")); else - x.tx("(unit "+q.getCode()+" from "+q.getSystem()+")"); + x.tx("(unit "+q.primitiveValue("code")+" from "+q.primitiveValue("system")+")"); } - if (showCodeDetails && q.hasCode()) { - x.span("background: LightGoldenRodYellow", null).tx(" "+ (context.formatPhrase(RenderingContext.DATA_REND_DETAILS, displaySystem(q.getSystem()))) +q.getCode()+" = '"+lookupCode(q.getSystem(), null, q.getCode())+"')"); + if (context.isTechnicalMode() && q.has("code")) { + x.span("background: LightGoldenRodYellow", null).tx(" "+ (context.formatPhrase(RenderingContext.DATA_REND_DETAILS, displaySystem(q.primitiveValue("system")))) +q.primitiveValue("code")+" = '"+lookupCode(q.primitiveValue("system"), null, q.primitiveValue("code"))+"')"); } } - - - protected void renderQuantity(HierarchicalTableGenerator gen, List pieces, Quantity q, boolean showCodeDetails) { + + + protected void renderQuantity(HierarchicalTableGenerator gen, List pieces, ResourceWrapper q, boolean showCodeDetails) { pieces.add(gen.new Piece(null, displayQuantity(q), null)); } - - public String displayRange(Range q) { - if (!q.hasLow() && !q.hasHigh()) + + protected void renderQuantity(HierarchicalTableGenerator gen, List pieces, Quantity q, boolean showCodeDetails) { + pieces.add(gen.new Piece(null, displayQuantity(wrapNC(q)), null)); + } + + public String displayRange(ResourceWrapper q) { + if (!q.has("low") && !q.has("high")) return "?"; - + StringBuilder b = new StringBuilder(); - - boolean sameUnits = (q.getLow().hasUnit() && q.getHigh().hasUnit() && q.getLow().getUnit().equals(q.getHigh().getUnit())) - || (q.getLow().hasCode() && q.getHigh().hasCode() && q.getLow().getCode().equals(q.getHigh().getCode())); + + ResourceWrapper lowC = q.child("low"); + ResourceWrapper highC = q.child("high"); + boolean sameUnits = (lowC != null && highC != null) && ((lowC.has("unit") && highC.has("unit") && lowC.child("unit").matches(highC.child("unit"))) + || (lowC.has("code") && highC.has("code") && lowC.child("code").matches(highC.child("code")))); String low = "?"; - if (q.hasLow() && q.getLow().hasValue()) - low = sameUnits ? q.getLow().getValue().toString() : displayQuantity(q.getLow()); - String high = displayQuantity(q.getHigh()); + if (q.has("low") && lowC.has("value")) + low = sameUnits ? lowC.primitiveValue("value").toString() : displayQuantity(lowC); + String high = displayQuantity(highC); if (high.isEmpty()) high = "?"; b.append(low).append("\u00A0to\u00A0").append(high); return b.toString(); } - - protected void renderRange(XhtmlNode x, Range q) { - if (q.hasLow()) - x.addText(q.getLow().getValue().toString()); + + protected void renderRange(RenderingStatus status, XhtmlNode x, ResourceWrapper q) { + if (q.has("low")) + x.addText(q.child("low").primitiveValue("value").toString()); else x.tx("?"); x.tx("-"); - if (q.hasHigh()) - x.addText(q.getHigh().getValue().toString()); + if (q.has("high")) + x.addText(q.child("high").primitiveValue("value").toString()); else x.tx("?"); - if (q.getLow().hasUnit()) - x.tx(" "+q.getLow().getUnit()); + if (q.child("low").has("unit")) + x.tx(" "+q.child("low").child("unit")); } - - public String displayPeriod(Period p) { - String s = !p.hasStart() ? "(?)" : displayDateTime(p.getStartElement()); + + public String displayPeriod(ResourceWrapper p) { + String s = !p.has("start") ? "(?)" : displayDateTime(p.child("start")); s = s + " --> "; - return s + (!p.hasEnd() ? context.formatPhrase(RenderingContext.DATA_REND_ONGOING) : displayDateTime(p.getEndElement())); + return s + (!p.has("end") ? context.formatPhrase(RenderingContext.DATA_REND_ONGOING) : displayDateTime(p.child("end"))); } - - public void renderPeriod(XhtmlNode x, Period p) { - x.addText(!p.hasStart() ? "??" : displayDateTime(p.getStartElement())); + + public void renderPeriod(RenderingStatus status, XhtmlNode x, ResourceWrapper p) { + x.addText(!p.has("start") ? "??" : displayDateTime(p.child("start"))); x.tx(" --> "); - x.addText(!p.hasEnd() ? context.formatPhrase(RenderingContext.DATA_REND_ONGOING) : displayDateTime(p.getEndElement())); + x.addText(!p.has("end") ? context.formatPhrase(RenderingContext.DATA_REND_ONGOING) : displayDateTime(p.child("end"))); } - - public void renderUsageContext(XhtmlNode x, UsageContext u) throws FHIRFormatError, DefinitionException, IOException { - renderCoding(x, u.getCode()); + + public void renderUsageContext(RenderingStatus status, XhtmlNode x, ResourceWrapper u) throws FHIRFormatError, DefinitionException, IOException { + renderCoding(status, x, u.child("code")); x.tx(": "); - render(x, u.getValue()); + renderDataType(status, x, u.child("value")); } - - - public void renderTriggerDefinition(XhtmlNode x, TriggerDefinition td) throws FHIRFormatError, DefinitionException, IOException { + + + public void renderTriggerDefinition(RenderingStatus status, XhtmlNode x, ResourceWrapper td) throws FHIRFormatError, DefinitionException, IOException { if (x.isPara()) { x.b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE)); x.tx(": "); - x.tx(td.getType().getDisplay()); - - if (td.hasName()) { + x.tx(td.child("type").primitiveValue("display")); + + if (td.has("name")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.GENERAL_NAME)); x.tx(": "); - x.tx(context.getTranslated(td.getNameElement())); + x.tx(context.getTranslated(td.child("name"))); } - if (td.hasCode()) { + if (td.has("code")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE)); x.tx(": "); - renderCodeableConcept(x, td.getCode()); + renderCodeableConcept(status, x, td.child("code")); } - if (td.hasTiming()) { + if (td.has("timing")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.DATA_REND_TIMING)); x.tx(": "); - render(x, td.getTiming()); + renderDataType(status, x, td.child("timing")); } - if (td.hasCondition()) { + if (td.has("condition")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.DATA_REND_COND)); x.tx(": "); - renderExpression(x, td.getCondition()); + renderExpression(status, x, td.child("condition")); } } else { XhtmlNode tbl = x.table("grid"); - + XhtmlNode tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE)); - tr.td().tx(td.getType().getDisplay()); - - if (td.hasName()) { + tr.td().tx(td.child("type").primitiveValue("display")); + + if (td.has("name")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_NAME)); - tr.td().tx(context.getTranslated(td.getNameElement())); + tr.td().tx(context.getTranslated(td.child("name"))); } - if (td.hasCode()) { + if (td.has("code")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE)); - renderCodeableConcept(tr.td(), td.getCode()); + renderCodeableConcept(status, tr.td(), td.child("code")); } - if (td.hasTiming()) { + if (td.has("timing")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.DATA_REND_TIMING)); - render(tr.td(), td.getTiming()); + renderDataType(status, tr.td(), td.child("timing")); } - if (td.hasCondition()) { + if (td.has("condition")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.DATA_REND_COND)); - renderExpression(tr.td(), td.getCondition()); + renderExpression(status, tr.td(), td.child("condition")); } } } - - public void renderDataRequirement(XhtmlNode x, DataRequirement dr) throws FHIRFormatError, DefinitionException, IOException { + + public void renderDataRequirement(RenderingStatus status, XhtmlNode x, ResourceWrapper dr) throws FHIRFormatError, DefinitionException, IOException { XhtmlNode tbl = x.table("grid"); XhtmlNode tr = tbl.tr(); XhtmlNode td = tr.td().colspan("2"); td.b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE)); td.tx(": "); - StructureDefinition sd = context.getWorker().fetchTypeDefinition(dr.getType().toCode()); + StructureDefinition sd = context.getWorker().fetchTypeDefinition(dr.primitiveValue("type")); if (sd != null && sd.hasWebPath()) { - td.ah(sd.getWebPath()).tx(dr.getType().toCode()); + td.ah(context.prefixLocalHref(sd.getWebPath())).tx(dr.primitiveValue("type")); } else { - td.tx(dr.getType().toCode()); + td.tx(dr.primitiveValue("type")); } - if (dr.hasProfile()) { + if (dr.has("profile")) { td.tx(" ("); boolean first = true; - for (CanonicalType p : dr.getProfile()) { + for (ResourceWrapper p : dr.children("profile")) { if (first) first = false; else td.tx(" | "); - sd = context.getWorker().fetchResource(StructureDefinition.class, p.getValue()); + sd = context.getWorker().fetchResource(StructureDefinition.class, p.primitiveValue()); if (sd != null && sd.hasWebPath()) { - td.ah(sd.getWebPath()).tx(crPresent(sd)); + td.ah(context.prefixLocalHref(sd.getWebPath())).tx(crPresent(sd)); } else { - td.tx(p.asStringValue()); + td.tx(p.primitiveValue()); } } td.tx(")"); } - if (dr.hasSubject()) { + if (dr.has("subject")) { tr = tbl.tr(); td = tr.td().colspan("2"); td.b().tx(context.formatPhrase(RenderingContext.GENERAL_SUBJ)); - if (dr.hasSubjectReference()) { - renderReference(td, dr.getSubjectReference()); + ResourceWrapper subj = dr.child("subject"); + if (subj.fhirType().equals("reference")) { + renderReference(status, td, subj); } else { - renderCodeableConcept(td, dr.getSubjectCodeableConcept()); + renderCodeableConcept(status, td, subj); } } - if (dr.hasCodeFilter() || dr.hasDateFilter()) { + if (dr.has("codeFilter") || dr.has("dateFilter")) { tr = tbl.tr().backgroundColor("#efefef"); tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_FILTER)); tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_VALUE)); } - for (DataRequirementCodeFilterComponent cf : dr.getCodeFilter()) { + for (ResourceWrapper cf : dr.children("codeFilter")) { tr = tbl.tr(); - if (cf.hasPath()) { - tr.td().tx(cf.getPath()); + if (cf.has("path")) { + tr.td().tx(cf.primitiveValue("path")); } else { - tr.td().tx(context.formatPhrase(RenderingContext.DATA_REND_SEARCH, cf.getSearchParam()) + " "); + tr.td().tx(context.formatPhrase(RenderingContext.DATA_REND_SEARCH, cf.primitiveValue("searchParam")) + " "); } - if (cf.hasValueSet()) { + if (cf.has("valueSet")) { td = tr.td(); td.tx(context.formatPhrase(RenderingContext.DATA_REND_VALUESET) + " "); - render(td, cf.getValueSetElement()); + renderDataType(status, td, cf.child("valueSet")); } else { boolean first = true; td = tr.td(); td.tx(context.formatPhrase(RenderingContext.DATA_REND_THESE_CODES) + " "); - for (Coding c : cf.getCode()) { + for (ResourceWrapper c : cf.children("code")) { if (first) first = false; else td.tx(", "); - render(td, c); + renderDataType(status, td, c); } } } - for (DataRequirementDateFilterComponent cf : dr.getDateFilter()) { + for (ResourceWrapper cf : dr.children("dateFilter")) { tr = tbl.tr(); - if (cf.hasPath()) { - tr.td().tx(cf.getPath()); + if (cf.has("path")) { + tr.td().tx(cf.primitiveValue("path")); } else { - tr.td().tx(context.formatPhrase(RenderingContext.DATA_REND_SEARCH, cf.getSearchParam()) + " "); + tr.td().tx(context.formatPhrase(RenderingContext.DATA_REND_SEARCH, cf.primitiveValue("searchParam")) + " "); } - render(tr.td(), cf.getValue()); + renderDataType(status, tr.td(), cf.child("value")); } - if (dr.hasSort() || dr.hasLimit()) { + if (dr.has("sort") || dr.has("limit")) { tr = tbl.tr(); td = tr.td().colspan("2"); - if (dr.hasLimit()) { + if (dr.has("limit")) { td.b().tx(context.formatPhrase(RenderingContext.DATA_REND_LIMIT)); td.tx(": "); - td.tx(dr.getLimit()); - if (dr.hasSort()) { + td.tx(dr.primitiveValue("limit")); + if (dr.has("sort")) { td.tx(", "); } } - if (dr.hasSort()) { + if (dr.has("sort")) { td.b().tx(context.formatPhrase(RenderingContext.DATA_REND_SORT)); td.tx(": "); boolean first = true; - for (DataRequirementSortComponent p : dr.getSort()) { + for (ResourceWrapper p : dr.children("sort")) { if (first) first = false; else td.tx(" | "); - td.tx(p.getDirection() == SortDirection.ASCENDING ? "+" : "-"); - td.tx(p.getPath()); + td.tx(p.primitiveValue("direction").equals("ascending") ? "+" : "-"); + td.tx(p.primitiveValue("path")); } } } } - - - private String displayTiming(Timing s) throws FHIRException { + + + private String displayTiming(ResourceWrapper s) throws FHIRException { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - if (s.hasCode()) - b.append(context.formatPhrase(RenderingContext.GENERAL_CODE, displayCodeableConcept(s.getCode())) + " "); - - if (s.getEvent().size() > 0) { + if (s.has("code")) { + b.append(context.formatPhrase(RenderingContext.GENERAL_CODE, displayCodeableConcept(s.child("code"))) + " "); + } + + if (s.has("event")) { CommaSeparatedStringBuilder c = new CommaSeparatedStringBuilder(); - for (DateTimeType p : s.getEvent()) { - if (p.hasValue()) { + for (ResourceWrapper p : s.children("event")) { + if (p.hasPrimitiveValue()) { c.append(displayDateTime(p)); } else if (!renderExpression(c, p)) { c.append("??"); @@ -1809,135 +2015,136 @@ public class DataRenderer extends Renderer implements CodeResolver { } b.append(context.formatPhrase(RenderingContext.DATA_REND_EVENTS, c.toString()) + " "); } - - if (s.hasRepeat()) { - TimingRepeatComponent rep = s.getRepeat(); - if (rep.hasBoundsPeriod() && rep.getBoundsPeriod().hasStart()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_STARTING, displayDateTime(rep.getBoundsPeriod().getStartElement())) + " "); - if (rep.hasCount()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_COUNT, Integer.toString(rep.getCount())) + " " + " times"); - if (rep.hasDuration()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_DURATION, rep.getDuration().toPlainString()+displayTimeUnits(rep.getPeriodUnit())) + " "); - - if (rep.hasWhen()) { + + if (s.has("repeat")) { + ResourceWrapper rep = s.child("repeat"); + if (rep.has("boundsPeriod") && rep.child("boundsPeriod").has("start")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_STARTING, displayDateTime(rep.child("boundsPeriod").child("start"))) + " "); + if (rep.has("count")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_COUNT, rep.primitiveValue("count")) + " " + " times"); + if (rep.has("duration")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_DURATION, rep.primitiveValue("duration")+displayTimeUnits(rep.primitiveValue("periodUnit"))) + " "); + + if (rep.has("when")) { String st = ""; - if (rep.hasOffset()) { - st = Integer.toString(rep.getOffset())+"min "; + if (rep.has("offset")) { + st = rep.primitiveValue("offset")+"min "; } b.append(st); - for (Enumeration wh : rep.getWhen()) - b.append(displayEventCode(wh.getValue())); + for (ResourceWrapper wh : rep.children("when")) { + b.append(displayEventCode(wh.primitiveValue())); + } } else { String st = ""; - if (!rep.hasFrequency() || (!rep.hasFrequencyMax() && rep.getFrequency() == 1) ) + if (!rep.has("frequency") || (!rep.has("frequencyMax") && rep.primitiveValue("frequency").equals("1"))) { st = context.formatPhrase(RenderingContext.DATA_REND_ONCE); - else { - st = Integer.toString(rep.getFrequency()); - if (rep.hasFrequencyMax()) - st = st + "-"+Integer.toString(rep.getFrequency()); + } else { + st = rep.primitiveValue("frequency"); + if (rep.has("frequencyMax")) + st = st + "-"+rep.primitiveValue("frequencyMax"); } - if (rep.hasPeriod()) { - st = st + " "+ (context.formatPhrase(RenderingContext.DATA_REND_PER))+rep.getPeriod().toPlainString(); - if (rep.hasPeriodMax()) - st = st + "-"+rep.getPeriodMax().toPlainString(); - st = st + " "+displayTimeUnits(rep.getPeriodUnit()); + if (rep.has("period")) { + st = st + " "+ (context.formatPhrase(RenderingContext.DATA_REND_PER))+rep.primitiveValue("period"); + if (rep.has("periodMax")) + st = st + "-"+rep.primitiveValue("periodMax"); + st = st + " "+displayTimeUnits(rep.primitiveValue("periodUnit")); } b.append(st); } - if (rep.hasBoundsPeriod() && rep.getBoundsPeriod().hasEnd()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_UNTIL, displayDateTime(rep.getBoundsPeriod().getEndElement())) + " "); + if (rep.has("boundsPeriod") && rep.child("boundsPeriod").has("end")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_UNTIL, displayDateTime(rep.child("boundsPeriod").child("end"))) + " "); } return b.toString(); } - - private boolean renderExpression(CommaSeparatedStringBuilder c, PrimitiveType p) { - Extension exp = p.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/cqf-expression"); + + private boolean renderExpression(CommaSeparatedStringBuilder c, ResourceWrapper p) { + ResourceWrapper exp = p.extensionValue("http://hl7.org/fhir/StructureDefinition/cqf-expression"); if (exp == null) { return false; } - c.append(exp.getValueExpression().getExpression()); + c.append(exp.child("value").primitiveValue("expression")); return true; } - - private String displayEventCode(EventTiming when) { + + private String displayEventCode(String when) { switch (when) { - case C: return (context.formatPhrase(RenderingContext.DATA_REND_MEALS)); - case CD: return (context.formatPhrase(RenderingContext.DATA_REND_ATLUNCH)); - case CM: return (context.formatPhrase(RenderingContext.DATA_REND_ATBKFST)); - case CV: return (context.formatPhrase(RenderingContext.DATA_REND_ATDINR)); - case AC: return (context.formatPhrase(RenderingContext.DATA_REND_BFMEALS)); - case ACD: return (context.formatPhrase(RenderingContext.DATA_REND_BFLUNCH)); - case ACM: return (context.formatPhrase(RenderingContext.DATA_REND_BFBKFST)); - case ACV: return (context.formatPhrase(RenderingContext.DATA_REND_BFDINR)); - case HS: return (context.formatPhrase(RenderingContext.DATA_REND_BFSLEEP)); - case PC: return (context.formatPhrase(RenderingContext.DATA_REND_AFTRMEALS)); - case PCD: return (context.formatPhrase(RenderingContext.DATA_REND_AFTRLUNCH)); - case PCM: return (context.formatPhrase(RenderingContext.DATA_REND_AFTRBKFST)); - case PCV: return (context.formatPhrase(RenderingContext.DATA_REND_AFTRDINR)); - case WAKE: return (context.formatPhrase(RenderingContext.DATA_REND_AFTRWKNG)); + case "c": return (context.formatPhrase(RenderingContext.DATA_REND_MEALS)); + case "cd": return (context.formatPhrase(RenderingContext.DATA_REND_ATLUNCH)); + case "cm": return (context.formatPhrase(RenderingContext.DATA_REND_ATBKFST)); + case "cv": return (context.formatPhrase(RenderingContext.DATA_REND_ATDINR)); + case "ac": return (context.formatPhrase(RenderingContext.DATA_REND_BFMEALS)); + case "acd": return (context.formatPhrase(RenderingContext.DATA_REND_BFLUNCH)); + case "acm": return (context.formatPhrase(RenderingContext.DATA_REND_BFBKFST)); + case "acv": return (context.formatPhrase(RenderingContext.DATA_REND_BFDINR)); + case "hs": return (context.formatPhrase(RenderingContext.DATA_REND_BFSLEEP)); + case "pc": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRMEALS)); + case "pcd": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRLUNCH)); + case "pcm": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRBKFST)); + case "pcv": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRDINR)); + case "wake": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRWKNG)); default: return "?ngen-6?"; } } - - private String displayTimeUnits(UnitsOfTime units) { + + private String displayTimeUnits(String units) { if (units == null) return "?ngen-7?"; switch (units) { - case A: return "years"; - case D: return "days"; - case H: return "hours"; - case MIN: return "minutes"; - case MO: return "months"; - case S: return "seconds"; - case WK: return "weeks"; + case "a": return "years"; + case "d": return "days"; + case "h": return "hours"; + case "min": return "minutes"; + case "mo": return "months"; + case "s": return "seconds"; + case "wk": return "weeks"; default: return "?ngen-8?"; } } - - protected void renderTiming(XhtmlNode x, Timing s) throws FHIRException { + + protected void renderTiming(RenderingStatus status, XhtmlNode x, ResourceWrapper s) throws FHIRException { x.addText(displayTiming(s)); } - - - private String displaySampledData(SampledData s) { + + + private String displaySampledData(ResourceWrapper s) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - if (s.hasOrigin()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_ORIGIN, displayQuantity(s.getOrigin())) + " "); - - if (s.hasInterval()) { - b.append(context.formatPhrase(RenderingContext.DATA_REND_INT, s.getInterval().toString()) + " "); - - if (s.hasIntervalUnit()) - b.append(s.getIntervalUnit().toString()); + if (s.has("origin")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_ORIGIN, displayQuantity(s.child("origin"))) + " "); + + if (s.has("interval")) { + b.append(context.formatPhrase(RenderingContext.DATA_REND_INT, s.primitiveValue("interval")) + " "); + + if (s.has("intervalUnit")) + b.append(s.primitiveValue("intervalUnit")); } - - if (s.hasFactor()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_FACT, s.getFactor().toString()) + " "); - - if (s.hasLowerLimit()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_LOWER, s.getLowerLimit().toString()) + " "); - - if (s.hasUpperLimit()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_UP, s.getUpperLimit().toString()) + " "); - - if (s.hasDimensions()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_DIM, s.getDimensions()) + " "); - - if (s.hasData()) - b.append(context.formatPhrase(RenderingContext.DATA_REND_DATA, s.getData()) + " "); - + + if (s.has("factor")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_FACT, s.primitiveValue("factor")) + " "); + + if (s.has("lowerLimit")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_LOWER, s.primitiveValue("lowerLimit")) + " "); + + if (s.has("upperLimit")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_UP, s.primitiveValue("upperLimit")) + " "); + + if (s.has("dimensions")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_DIM, s.primitiveValue("dimensions")) + " "); + + if (s.has("data")) + b.append(context.formatPhrase(RenderingContext.DATA_REND_DATA, s.primitiveValue("data")) + " "); + return b.toString(); } - - protected void renderSampledData(XhtmlNode x, SampledData sampledData) { + + protected void renderSampledData(RenderingStatus status, XhtmlNode x, ResourceWrapper sampledData) { x.addText(displaySampledData(sampledData)); } - + public RenderingContext getContext() { return context; } - - + + public XhtmlNode makeExceptionXhtml(Exception e, String function) { XhtmlNode xn; xn = new XhtmlNode(NodeType.Element, "div"); @@ -1946,7 +2153,7 @@ public class DataRenderer extends Renderer implements CodeResolver { p.addComment(getStackTrace(e)); return xn; } - + private String getStackTrace(Exception e) { StringBuilder b = new StringBuilder(); b.append("\r\n"); @@ -1956,5 +2163,26 @@ public class DataRenderer extends Renderer implements CodeResolver { } return b.toString(); } - + + protected String versionFromCanonical(String system) { + if (system == null) { + return null; + } else if (system.contains("|")) { + return system.substring(0, system.indexOf("|")); + } else { + return null; + } + } + + protected String systemFromCanonical(String system) { + if (system == null) { + return null; + } else if (system.contains("|")) { + return system.substring(system.indexOf("|")+1); + } else { + return system; + } + } + + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java index 5c5d97e8c..a3187026a 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java @@ -1,201 +1,174 @@ package org.hl7.fhir.r5.renderers; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.DataType; -import org.hl7.fhir.r5.model.DiagnosticReport; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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; -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; -import org.hl7.fhir.r5.utils.EOperationOutcome; -import org.hl7.fhir.utilities.Utilities; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; +import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; - + public class DiagnosticReportRenderer extends ResourceRenderer { - + public class ObservationNode { private String ref; - private ResourceWithReference obs; + private ResourceWithReference resolution; private List contained; } - - + public DiagnosticReportRenderer(RenderingContext context) { super(context); } - - public DiagnosticReportRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome { - return render(x, (DiagnosticReport) dr); - } - - public boolean render(XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome { + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome { + renderDiagnosticReport(status, x, dr); + } + + public void renderDiagnosticReport(RenderingStatus status, XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(dr, x); + XhtmlNode h2 = x.h2(); - render(h2, getProperty(dr, "code").value()); + renderDataType(status, h2, dr.child("code")); h2.tx(" "); - PropertyWrapper pw = getProperty(dr, "category"); - if (valued(pw)) { + List cats = dr.children("category"); + if (!cats.isEmpty()) { h2.tx("("); boolean first = true; - for (BaseWrapper b : pw.getValues()) { + for (ResourceWrapper b : cats) { if (first) first = false; else h2.tx(", "); - render(h2, b); + renderDataType(status, h2, b); } h2.tx(") "); } XhtmlNode tbl = x.table("grid"); XhtmlNode tr; if (dr.has("subject")) { - tr = tbl.tr(); - tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_SUBJ)); - populateSubjectSummary(tr.td(), getProperty(dr, "subject").value()); + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_SUBJ)); + populateSubjectSummary(status, tr.td(), dr.child("subject")); } - - DataType eff = null; - DataType iss = null; - + + ResourceWrapper eff = null; + ResourceWrapper iss = null; if (dr.has("effective[x]")) { tr = tbl.tr(); - tr.td().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_WHEN)); - eff = (DataType) getProperty(dr, "effective[x]").value().getBase(); - render(tr.td(), eff); + tr.td().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_WHEN)); + eff = dr.child("effective[x]"); + renderDataType(status, tr.td(), eff); } if (dr.has("issued")) { tr = tbl.tr(); tr.td().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REP)); - eff = (DataType) getProperty(dr, "issued").value().getBase(); - render(tr.td(), getProperty(dr, "issued").value()); + iss = dr.child("issued"); + renderDataType(status, tr.td(), iss); } - - pw = getProperty(dr, "perfomer"); - if (valued(pw)) { - tr = tbl.tr(); - tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.DIAG_REP_REND_PER)), pw.getValues().size())); - XhtmlNode tdr = tr.td(); - for (BaseWrapper v : pw.getValues()) { - tdr.tx(" "); - render(tdr, v); - } - } - pw = getProperty(dr, "identifier"); - if (valued(pw)) { - tr = tbl.tr(); - tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.DIAG_REP_REND_IDENTIFIER)), pw.getValues().size())+":"); - XhtmlNode tdr = tr.td(); - for (BaseWrapper v : pw.getValues()) { - tdr.tx(" "); - render(tdr, v); - } - } - pw = getProperty(dr, "request"); - if (valued(pw)) { - tr = tbl.tr(); - tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.GENERAL_REQUEST)), pw.getValues().size())+":"); - XhtmlNode tdr = tr.td(); - for (BaseWrapper v : pw.getValues()) { - tdr.tx(" "); - render(tdr, v); - } - tdr.br(); - } - - + + addTableRow(status, tbl, dr, RenderingContext.DIAG_REP_REND_PER, "performer"); + addTableRow(status, tbl, dr, RenderingContext.DIAG_REP_REND_IDENTIFIER, "identifier"); + addTableRow(status, tbl, dr, RenderingContext.GENERAL_REQUEST, "request"); + x.para().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REPDET)); - - pw = getProperty(dr, "result"); - if (valued(pw)) { - List observations = fetchObservations(pw.getValues(), dr); - buildObservationsTable(x, observations, eff, iss); + + List items = dr.children("result"); + if (!items.isEmpty()) { + List observations = fetchObservations(items); + buildObservationsTable(status, x, observations, eff, iss); } - - pw = getProperty(dr, "conclusion"); - if (valued(pw)) { - if (pw.fhirType().equals("markdown")) { - render(x, pw.value()); + + if (dr.has("conclusion")) { + ResourceWrapper conc = dr.child("conclusion"); + if (conc.fhirType().equals("markdown")) { + renderDataType(status, x, conc); } else { - render(x.para(), pw.value()); + renderDataType(status, x.para(), conc); } } - - pw = getProperty(dr, "conclusionCode"); - if (!valued(pw)) { - pw = getProperty(dr, "codedDiagnosis"); - } - if (valued(pw)) { - XhtmlNode p = x.para(); - p.b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_CODECON)); - XhtmlNode ul = x.ul(); - for (BaseWrapper v : pw.getValues()) { - render(ul.li(), v); + + if (dr.hasMN("conclusionCode", "codedDiagnosis")) { + x.para().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_CODECON)); + addListRows(status, x.ul(), dr, RenderingContext.DIAG_REP_REND_CODECON, "conclusionCode", "codedDiagnosis"); + } + + for (ResourceWrapper cont : dr.children("contained")) { + x.hr(); + RendererFactory.factory(cont, context.forContained()).buildNarrative(status, x, cont); + } + } + + private void addTableRow(RenderingStatus status, XhtmlNode tbl, ResourceWrapper dr, String constName, String... names) throws FHIRFormatError, DefinitionException, IOException { + List items = dr.childrenMN(names); + if (!items.isEmpty()) { + XhtmlNode tr = tbl.tr(); + tr.td().tx(Utilities.pluralize(context.formatPhrase(constName), items.size())); + XhtmlNode tdr = tr.td(); + for (ResourceWrapper v : items) { + tdr.tx(" "); + renderDataType(status, tdr, v); } } - return false; + } + + private void addListRows(RenderingStatus status, XhtmlNode ul, ResourceWrapper dr, String constName, String... names) throws FHIRFormatError, DefinitionException, IOException { + List items = dr.childrenMN(names); + if (!items.isEmpty()) { + for (ResourceWrapper v : items) { + XhtmlNode li = ul.li(); + renderDataType(status, li, v); + } + } + } + + public void describeDiagnosticReport(XhtmlNode x, ResourceWrapper dr) { + x.tx(displayDiagnosticReport(dr)); } - - public boolean render(XhtmlNode x, DiagnosticReport dr) throws IOException, FHIRException, EOperationOutcome { - render(x, new DirectWrappers.ResourceWrapperDirect(this.context, dr)); - - return true; + + public String displayDiagnosticReport(ResourceWrapper dr) { + ResourceWrapper c = dr.child("code"); + String cd = c == null ? context.formatPhrase(RenderingContext.DIAG_REP_UNSPECIFIED_CODE) : displayCodeableConcept(c); + ResourceWrapper s = dr.child("subject"); + String sd = s == null ? context.formatPhrase(RenderingContext.DIAG_REP_UNSPECIFIED_SUBJECT) : displayReference(s); + return context.formatPhrase(RenderingContext.DIAG_REP_SUMMARY, cd, sd); } - - public void describe(XhtmlNode x, DiagnosticReport dr) { - x.tx(display(dr)); - } - - public String display(DiagnosticReport dr) { - return display(dr.getCode()); - } - + @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return display((DiagnosticReport) r); + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return displayDiagnosticReport(r); } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - return "Not done yet"; - } - - private void populateSubjectSummary(XhtmlNode container, BaseWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome { - ResourceWrapper r = fetchResource(subject); + + + private void populateSubjectSummary(RenderingStatus status, XhtmlNode container, ResourceWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome { + ResourceWithReference r = resolveReference(subject); if (r == null) container.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_UNABLE)); - else if (r.getName().equals("Patient")) - generatePatientSummary(container, r); + else if (r.getResource().fhirType().equals("Patient")) + generatePatientSummary(container, r.getResource()); else container.tx(context.formatPhrase(RenderingContext.GENERAL_TODO)); } - + private void generatePatientSummary(XhtmlNode c, ResourceWrapper r) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { new PatientRenderer(context).describe(c, r); } - - private List fetchObservations(List list, ResourceWrapper rw) throws UnsupportedEncodingException, FHIRException, IOException { + + private List fetchObservations(List list) throws UnsupportedEncodingException, FHIRException, IOException { List res = new ArrayList(); - for (BaseWrapper b : list) { + for (ResourceWrapper b : list) { if (b.has("reference")) { ObservationNode obs = new ObservationNode(); - obs.ref = b.get("reference").primitiveValue(); - obs.obs = resolveReference(rw, obs.ref); - if (obs.obs != null && obs.obs.getResource() != null) { - PropertyWrapper t = getProperty(obs.obs.getResource(), "contained"); - if (t != null && t.hasValues()) { - obs.contained = fetchObservations(t.getValues(), rw); + obs.ref = b.primitiveValue("reference"); + obs.resolution = resolveReference(b.child("reference")); + if (obs.resolution != null && obs.resolution.getResource() != null) { + List t = obs.resolution.getResource().children("contained"); + if (!t.isEmpty()) { + obs.contained = fetchObservations(t); } } res.add(obs); @@ -203,8 +176,8 @@ public class DiagnosticReportRenderer extends ResourceRenderer { } return res; } - - private void buildObservationsTable(XhtmlNode root, List observations, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException { + + private void buildObservationsTable(RenderingStatus status, XhtmlNode root, List observations, ResourceWrapper eff, ResourceWrapper iss) throws UnsupportedEncodingException, FHIRException, IOException { XhtmlNode tbl = root.table("grid"); boolean refRange = scanObsForRefRange(observations); boolean flags = scanObsForFlags(observations); @@ -236,253 +209,213 @@ public class DiagnosticReportRenderer extends ResourceRenderer { tr.td().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REP)); } for (ObservationNode o : observations) { - addObservationToTable(tbl, o, 0, Integer.toString(cs), refRange, flags, note, effectiveTime, issued, eff, iss); + addObservationToTable(status, tbl, o, 0, Integer.toString(cs), refRange, flags, note, effectiveTime, issued, eff, iss); } } - + private boolean scanObsForRefRange(List observations) { - for (ObservationNode o : observations) { - if (o.obs != null && o.obs.getResource() != null) { - PropertyWrapper pw = getProperty(o.obs.getResource(), "referenceRange"); - if (valued(pw)) { - return true; - } - } - if (o.contained != null) { - if (scanObsForRefRange(o.contained)) { + for (ObservationNode o : observations) { + if (o.resolution != null) { + ResourceWrapper obs = o.resolution.getResource(); + if (obs != null && obs.has("referenceRange")) { return true; } - } + if (o.contained != null) { + if (scanObsForRefRange(o.contained)) { + return true; + } + } + } } return false; } - + private boolean scanObsForNote(List observations) { for (ObservationNode o : observations) { - if (o.obs != null && o.obs.getResource() != null) { - PropertyWrapper pw = getProperty(o.obs.getResource(), "note"); - if (valued(pw)) { - return true; - } - } - if (o.contained != null) { - if (scanObsForNote(o.contained)) { + if (o.resolution != null) { + ResourceWrapper obs = o.resolution.getResource(); + if (obs != null && obs.has("note")) { return true; } - } - } - return false; - } - - private boolean scanObsForIssued(List observations, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException { - for (ObservationNode o : observations) { - if (o.obs != null && o.obs.getResource() != null) { - PropertyWrapper pw = getProperty(o.obs.getResource(), "issued"); - if (valued(pw)) { - if (!Base.compareDeep(pw.value().getBase(), iss, true)) { + if (o.contained != null) { + if (scanObsForNote(o.contained)) { return true; } - } - } - if (o.contained != null) { - if (scanObsForIssued(o.contained, iss)) { - return true; } - } + } } return false; } - - private boolean scanObsForEffective(List observations, DataType eff) throws UnsupportedEncodingException, FHIRException, IOException { + + private boolean scanObsForIssued(List observations, ResourceWrapper iss) throws UnsupportedEncodingException, FHIRException, IOException { for (ObservationNode o : observations) { - if (o.obs != null && o.obs.getResource() != null) { - PropertyWrapper pw = getProperty(o.obs.getResource(), "effective[x]"); - if (valued(pw)) { - if (!Base.compareDeep(pw.value().getBase(), eff, true)) { + if (o.resolution != null) { + ResourceWrapper obs = o.resolution.getResource(); + if (obs != null && obs.has("issued") && (iss == null || !iss.matches(obs.child("issued")))) { + return true; + } + if (o.contained != null) { + if (scanObsForIssued(o.contained, iss)) { return true; } - } - } - if (o.contained != null) { - if (scanObsForEffective(o.contained, eff)) { - return true; } - } + } } return false; } - + + private boolean scanObsForEffective(List observations, ResourceWrapper eff) throws UnsupportedEncodingException, FHIRException, IOException { + for (ObservationNode o : observations) { + if (o.resolution != null) { + ResourceWrapper obs = o.resolution.getResource(); + if (obs != null && obs.has("effective[x]") && (eff == null || !eff.matches(obs.child("effective[x]")))) { + return true; + } + if (o.contained != null) { + if (scanObsForEffective(o.contained, eff)) { + return true; + } + } + } + } + return false; + } + private boolean scanObsForFlags(List observations) throws UnsupportedEncodingException, FHIRException, IOException { for (ObservationNode o : observations) { - if (o.obs != null && o.obs.getResource() != null) { - PropertyWrapper pw = getProperty(o.obs.getResource(), "interpretation"); - if (valued(pw)) { + if (o.resolution != null) { + ResourceWrapper obs = o.resolution.getResource(); + if (obs != null && (obs.has("interpretation") || obs.has("status"))) { return true; } - pw = getProperty(o.obs.getResource(), "status"); - if (valued(pw)) { - if (!pw.value().getBase().primitiveValue().equals("final")) { + if (o.contained != null) { + if (scanObsForFlags(o.contained)) { return true; } } - - } - if (o.contained != null) { - if (scanObsForFlags(o.contained)) { - return true; - } - } + } } return false; } - - private void addObservationToTable(XhtmlNode tbl, ObservationNode o, int i, String cs, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException { + + private void addObservationToTable(RenderingStatus status, XhtmlNode tbl, ObservationNode o, int i, String cs, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, ResourceWrapper eff, ResourceWrapper iss) throws UnsupportedEncodingException, FHIRException, IOException { XhtmlNode tr = tbl.tr(); - if (o.obs != null && o.obs.getReference() == null) { + if (o.resolution == null) { XhtmlNode td = tr.td().colspan(cs); - td.i().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_NOTRES)); + td.i().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_NOTRES, o.ref)); } else { - if (o.obs != null && o.obs.getResource() != null) { - addObservationToTable(tr, o.obs.getResource(), i, o.obs.getReference(), refRange, flags, note, effectiveTime, issued, eff, iss); + if (o.resolution.getResource() != null) { + addObservationToTable(status, tr, o.resolution.getResource(), i, o.resolution.getWebPath(), refRange, flags, note, effectiveTime, issued, eff, iss); } else { XhtmlNode td = tr.td().colspan(cs); td.i().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_OBS)); } if (o.contained != null) { for (ObservationNode c : o.contained) { - addObservationToTable(tbl, c, i+1, cs, refRange, flags, note, effectiveTime, issued, eff, iss); + addObservationToTable(status, tbl, c, i+1, cs, refRange, flags, note, effectiveTime, issued, eff, iss); } } } } - - private void addObservationToTable(XhtmlNode tr, ResourceWrapper obs, int i, String ref, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException { - + + private void addObservationToTable(RenderingStatus status, XhtmlNode tr, ResourceWrapper obs, int i, String ref, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, ResourceWrapper eff, ResourceWrapper iss) throws UnsupportedEncodingException, FHIRException, IOException { + // code (+bodysite) XhtmlNode td = tr.td(); - PropertyWrapper pw = getProperty(obs, "code"); - if (valued(pw)) { - render(td.ah(ref), pw.value()); + if (obs.has("code")) { + renderDataType(status, td.ah(context.prefixLocalHref(ref)), obs.child("code")); } - pw = getProperty(obs, "bodySite"); - if (valued(pw)) { + if (obs.has("bodySite")) { td.tx(" ("); - render(td, pw.value()); + renderDataType(status, td, obs.child("bodySite")); td.tx(")"); } - + // value / dataAbsentReason (in red) td = tr.td(); - pw = getProperty(obs, "value[x]"); - if (valued(pw)) { - render(td, pw.value()); - } else { - pw = getProperty(obs, "dataAbsentReason"); - if (valued(pw)) { - XhtmlNode span = td.span("color: maroon", "Error"); - span.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_ERR) + " "); - render(span.b(), pw.value()); - } + if (obs.has("value[x]")) { + renderDataType(status, td, obs.child("value[x]")); + } else if (obs.has("dataAbsentReason")) { + XhtmlNode span = td.span("color: maroon", "Error"); + span.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_ERR) + " "); + renderDataType(status, span.b(), obs.child("dataAbsentReason")); } + if (refRange) { // reference range td = tr.td(); - pw = getProperty(obs, "referenceRange"); - if (valued(pw)) { + List items = obs.children("referenceRange"); + if (!items.isEmpty()) { boolean first = true; - for (BaseWrapper v : pw.getValues()) { + for (ResourceWrapper v : items) { if (first) first = false; else td.br(); - PropertyWrapper pwr = getProperty(v, "type"); - if (valued(pwr)) { - render(td, pwr.value()); + ResourceWrapper pwr = v.child("type"); + if (pwr != null) { + renderDataType(status, td, pwr); td.tx(": "); } - PropertyWrapper pwt = getProperty(v, "text"); - if (valued(pwt)) { - render(td, pwt.value()); + ResourceWrapper pwt = v.child("text"); + if (pwt != null) { + renderDataType(status, td, pwt); } else { - PropertyWrapper pwl = getProperty(v, "low"); - PropertyWrapper pwh = getProperty(v, "high"); - if (valued(pwl) && valued(pwh)) { - render(td, pwl.value()); + ResourceWrapper pwl = v.child("low"); + ResourceWrapper pwh = v.child("high"); + if (pwl != null && pwh != null) { + renderDataType(status, td, pwl); td.tx(" - "); - render(td, pwh.value()); - } else if (valued(pwl)) { + renderDataType(status, td, pwh); + } else if (pwl != null) { td.tx(">"); - render(td, pwl.value()); - } else if (valued(pwh)) { + renderDataType(status, td, pwl); + } else if (pwh != null) { td.tx("<"); - render(td, pwh.value()); + renderDataType(status, td, pwh); } else { td.tx("??"); } } - pwr = getProperty(v, "appliesTo"); - PropertyWrapper pwrA = getProperty(v, "age"); - if (valued(pwr) || valued(pwrA)) { + List pwrF = v.children("appliesTo"); + ResourceWrapper pwrA = v.child("age"); + if (!pwrF.isEmpty() || pwrA != null) { boolean firstA = true; td.tx(" "+ (context.formatPhrase(RenderingContext.DIAG_REP_REND_FOR)) + " "); - if (valued(pwr)) { - for (BaseWrapper va : pwr.getValues()) { + if (!pwrF.isEmpty()) { + for (ResourceWrapper va : pwrF) { if (firstA) firstA = false; else td.tx(", "); - render(td, va); + renderDataType(status, td, va); } } - if (valued(pwrA)) { + if (pwrA != null) { if (firstA) firstA = false; else td.tx(", "); td.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_AGE) + " "); - render(td, pwrA.value()); + renderDataType(status, td, pwrA); } } } } } - if (flags) { - // flags (status other than F, interpretation, ) - td = tr.td(); - boolean first = true; - pw = getProperty(obs, "status"); - if (valued(pw)) { - if (!pw.value().getBase().primitiveValue().equals("final")) { - if (first) first = false; else td.br(); - render(td, pw.value()); - } + + addCellToTable(flags, status, tr, obs, null, "status", "interpretation"); + addCellToTable(note, status, tr, obs, null, "note"); + addCellToTable(effectiveTime, status, tr, obs, eff, "effective[x]"); + addCellToTable(issued, status, tr, obs, iss, "issued"); + + } + + private void addCellToTable(boolean included, RenderingStatus status, XhtmlNode tr, ResourceWrapper obs, ResourceWrapper diff, String... names) throws FHIRFormatError, DefinitionException, IOException { + if (included) { + XhtmlNode td = tr.td(); + List list = obs.childrenMN(names); + if (!list.isEmpty()) { + boolean first = true; + for (ResourceWrapper b : list) { + if (diff == null || !diff.matches(b)) { + if (first) first = false; else td.tx(", "); + renderDataType(status, td, b); + } + } } - pw = getProperty(obs, "interpretation"); - if (valued(pw)) { - for (BaseWrapper v : pw.getValues()) { - if (first) first = false; else td.br(); - render(td, v); - } - } - } - - if (note) { - td = tr.td(); - pw = getProperty(obs, "note"); - if (valued(pw)) { - render(td, pw.value()); - } - } - if (effectiveTime) { - // effective if different to DR - td = tr.td(); - pw = getProperty(obs, "effective[x]"); - if (valued(pw)) { - if (!Base.compareDeep(pw.value().getBase(), eff, true)) { - render(td, pw.value()); - } - } - } - if (issued) { - // issued if different to DR - td = tr.td(); - pw = getProperty(obs, "issued"); - if (valued(pw)) { - if (!Base.compareDeep(pw.value().getBase(), eff, true)) { - render(td, pw.value()); - } - } - } + } } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/EncounterRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/EncounterRenderer.java index 72aa9aada..561d51931 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/EncounterRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/EncounterRenderer.java @@ -3,31 +3,30 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; import java.io.UnsupportedEncodingException; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class EncounterRenderer extends ResourceRenderer { - - public EncounterRenderer(RenderingContext context) { - super(context); - } - - public boolean render(XhtmlNode x, Resource dr) throws UnsupportedEncodingException, IOException { - describe(x, dr); - return false; - } - - public String display(Resource dr) { - return "Not done yet"; + public EncounterRenderer(RenderingContext context) { + super(context); + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return "todo"; } @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - return "Not done yet"; + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(r, x); + x.tx("Not done yet"); } - + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ExampleScenarioRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ExampleScenarioRenderer.java index ed3439d5a..f4a71b158 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ExampleScenarioRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ExampleScenarioRenderer.java @@ -1,47 +1,79 @@ package org.hl7.fhir.r5.renderers; -import net.sourceforge.plantuml.FileFormat; -import net.sourceforge.plantuml.FileFormatOption; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r5.context.ContextUtilities; -import org.hl7.fhir.r5.model.*; -import org.hl7.fhir.r5.model.ExampleScenario.*; -import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; -import org.hl7.fhir.utilities.xhtml.XhtmlDocument; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; -import net.sourceforge.plantuml.SourceStringReader; - import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.context.ContextUtilities; +import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.Enumerations; +import org.hl7.fhir.r5.model.ExampleScenario; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioActorComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioInstanceComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioInstanceContainedInstanceComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioInstanceVersionComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioProcessComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioProcessStepAlternativeComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioProcessStepComponent; +import org.hl7.fhir.r5.model.ExampleScenario.ExampleScenarioProcessStepOperationComponent; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; +import org.hl7.fhir.utilities.xhtml.XhtmlDocument; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; + +import net.sourceforge.plantuml.FileFormat; +import net.sourceforge.plantuml.FileFormatOption; +import net.sourceforge.plantuml.SourceStringReader; + public class ExampleScenarioRenderer extends TerminologyRenderer { - public ExampleScenarioRenderer(RenderingContext context) { - super(context); + public ExampleScenarioRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (ExampleScenario) r.getBase()); + render(status, x, (ExampleScenario) r.getBase(), r); + } else { + throw new Error("ExampleScenarioRenderer only renders native resources directly"); + } } - public boolean render(XhtmlNode x, Resource scen) throws IOException { - return render(x, (ExampleScenario) scen); + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public boolean render(XhtmlNode x, ExampleScenario scen) throws FHIRException { + public void render(RenderingStatus status, XhtmlNode x, ExampleScenario scen, ResourceWrapper res) throws FHIRException { try { if (context.getScenarioMode() == null) { - return renderActors(x, scen); + renderActors(status, res, x, scen); } else { switch (context.getScenarioMode()) { case ACTORS: - return renderActors(x, scen); + renderActors(status, res, x, scen); + break; case INSTANCES: - return renderInstances(x, scen); + renderInstances(status, res, x, scen); + break; case PROCESSES: - return renderProcesses(x, scen); + renderProcesses(status, x, scen); + break; default: throw new FHIRException(context.formatPhrase(RenderingContext.EX_SCEN_UN, context.getScenarioMode()) + " "); } @@ -51,8 +83,8 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { } } - public String renderDiagram(ExampleScenario scen) throws IOException { - String plantUml = toPlantUml(scen); + public String renderDiagram(RenderingStatus status, ResourceWrapper res, ExampleScenario scen) throws IOException { + String plantUml = toPlantUml(status, res, scen); SourceStringReader reader = new SourceStringReader(plantUml); final ByteArrayOutputStream os = new ByteArrayOutputStream(); reader.outputImage(os, new FileFormatOption(FileFormat.SVG)); @@ -62,7 +94,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return svg; } - protected String toPlantUml(ExampleScenario scen) throws IOException { + protected String toPlantUml(RenderingStatus status, ResourceWrapper res, ExampleScenario scen) throws IOException { String plantUml = "@startuml\r\n"; plantUml += "Title " + (scen.hasTitle() ? scen.getTitle() : scen.getName()) + "\r\n\r\n"; Map actorKeys = new HashMap(); @@ -76,7 +108,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { int processNum = 1; for (ExampleScenarioProcessComponent process: scen.getProcess()) { - plantUml += toPlantUml(process, Integer.toString(processNum), scen, actorKeys); + plantUml += toPlantUml(status, res, process, Integer.toString(processNum), scen, actorKeys); processNum++; } plantUml += "@enduml"; @@ -94,7 +126,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return new String(chars); } - protected String toPlantUml(ExampleScenarioProcessComponent process, String prefix, ExampleScenario scen, Map actorKeys) throws IOException { + protected String toPlantUml(RenderingStatus status, ResourceWrapper res, ExampleScenarioProcessComponent process, String prefix, ExampleScenario scen, Map actorKeys) throws IOException { String plantUml = "group " + process.getTitle() + " " + creolLink("details", "#p_" + prefix, process.getDescription()) + "\r\n"; Map actorsActive = new HashMap(); @@ -103,7 +135,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { } int stepCount = 1; for (ExampleScenarioProcessStepComponent step: process.getStep()) { - plantUml += toPlantUml(step, stepPrefix(prefix, step, stepCount), scen, actorsActive, actorKeys); + plantUml += toPlantUml(status, res, step, stepPrefix(prefix, step, stepCount), scen, actorsActive, actorKeys); if (step.getPause()) plantUml += context.formatPhrase(RenderingContext.EX_SCEN_TIME)+"\n"; stepCount++; @@ -113,15 +145,15 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return plantUml; } - protected String toPlantUml(ExampleScenarioProcessStepComponent step, String prefix, ExampleScenario scen, Map actorsActive, Map actorKeys) throws IOException { + protected String toPlantUml(RenderingStatus status, ResourceWrapper res, ExampleScenarioProcessStepComponent step, String prefix, ExampleScenario scen, Map actorsActive, Map actorKeys) throws IOException { String plantUml = ""; if (step.hasWorkflow()) { XhtmlNode n = new XhtmlDocument(); - renderCanonical(scen, n, step.getWorkflow()); + renderCanonical(status, res, n, Resource.class, step.getWorkflowElement()); XhtmlNode ref = n.getChildNodes().get(0); plantUml += noteOver(scen.getActor(), context.formatPhrase(RenderingContext.EXAMPLE_SCEN_STEP_SCEN, trimPrefix(prefix), creolLink((ref.getContent()), ref.getAttribute("href")))); } else if (step.hasProcess()) - plantUml += toPlantUml(step.getProcess(), prefix, scen, actorKeys); + plantUml += toPlantUml(status, res, step.getProcess(), prefix, scen, actorKeys); else { // Operation plantUml += toPlantUml(step.getOperation(), prefix, scen, actorsActive, actorKeys); @@ -208,7 +240,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return s; } - public boolean renderActors(XhtmlNode x, ExampleScenario scen) throws IOException { + public boolean renderActors(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ExampleScenario scen) throws IOException { XhtmlNode tbl = x.table("table-striped table-bordered"); XhtmlNode thead = tbl.tr(); thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_NAME)); @@ -217,7 +249,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { for (ExampleScenarioActorComponent actor : scen.getActor()) { XhtmlNode tr = tbl.tr(); XhtmlNode nameCell = tr.td(); - nameCell.an("a_" + actor.getKey()); + nameCell.an(context.prefixAnchor("a_" + actor.getKey())); nameCell.tx(actor.getTitle()); tr.td().tx(actor.getType().getDisplay()); addMarkdown(tr.td().style("overflow-wrap:break-word"), actor.getDescription()); @@ -225,7 +257,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return true; } - public boolean renderInstances(XhtmlNode x, ExampleScenario scen) throws IOException { + public boolean renderInstances(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ExampleScenario scen) throws IOException { XhtmlNode tbl = x.table("table-striped table-bordered"); XhtmlNode thead = tbl.tr(); thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_NAME)); @@ -246,7 +278,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { for (ExampleScenarioInstanceComponent instance : scen.getInstance()) { XhtmlNode row = tbl.tr(); XhtmlNode nameCell = row.td(); - nameCell.an("i_" + instance.getKey()); + nameCell.an(context.prefixAnchor("i_" + instance.getKey())); nameCell.tx(instance.getTitle()); XhtmlNode typeCell = row.td(); if (instance.hasVersion()) @@ -255,24 +287,29 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { if (!instance.hasStructureVersion() || instance.getStructureType().getSystem().equals("")) { if (instance.hasStructureVersion()) typeCell.tx((context.formatPhrase(RenderingContext.EX_SCEN_FVER, instance.getStructureVersion()) + " ") + " "); - if (instance.hasStructureProfile()) { - renderCanonical(scen, typeCell, instance.getStructureProfile().toString()); + if (instance.hasStructureProfileCanonicalType()) { + renderCanonical(status, res, typeCell, StructureDefinition.class, instance.getStructureProfileCanonicalType()); + } else if (instance.hasStructureProfileUriType()) { + renderBase(status, typeCell, instance.getStructureProfileUriType()); } else { - renderCanonical(scen, typeCell, "http://hl7.org/fhir/StructureDefinition/" + instance.getStructureType().getCode()); + CanonicalType ct = new CanonicalType("http://hl7.org/fhir/StructureDefinition/" + instance.getStructureType().getCode()); + renderCanonical(status, res, typeCell, StructureDefinition.class, ct); } } else { - render(typeCell, instance.getStructureVersionElement()); + renderDataType(status, typeCell, wrapWC(res, instance.getStructureVersionElement())); typeCell.tx(" "+(context.formatPhrase(RenderingContext.GENERAL_VER_LOW, instance.getStructureVersion())+" ")); if (instance.hasStructureProfile()) { typeCell.tx(" "); - renderCanonical(scen, typeCell, instance.getStructureProfile().toString()); + if (instance.hasStructureProfileCanonicalType()) { + renderCanonical(status, res, typeCell, StructureDefinition.class, instance.getStructureProfileCanonicalType()); + } } } if (instance.hasContent() && instance.getContent().hasReference()) { // Force end-user mode to avoid ugly references RenderingContext.ResourceRendererMode mode = context.getMode(); context.setMode(RenderingContext.ResourceRendererMode.END_USER); - renderReference(scen, row.td(), instance.getContent().copy().setDisplay("here")); + renderReference(status, row.td(), wrapWC(res, instance.getContent().copy().setDisplay("here"))); context.setMode(mode); } else row.td(); @@ -289,7 +326,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { String description = instanceNames.get(key); if (description==null) throw new FHIRException("Unable to find contained instance " + key + " under " + instance.getKey()); - descCell.ah("#" + key).tx(description); + descCell.ah(context.prefixLocalHref("#" + key)).tx(description); containedCount++; if (instance.getContainedInstance().size() > containedCount) descCell.tx(", "); @@ -307,7 +344,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { // Force end-user mode to avoid ugly references RenderingContext.ResourceRendererMode mode = context.getMode(); context.setMode(RenderingContext.ResourceRendererMode.END_USER); - renderReference(scen, row.td(), version.getContent().copy().setDisplay("here")); + renderReference(status, row.td(), wrapWC(res, version.getContent().copy().setDisplay("here"))); context.setMode(mode); } else row.td(); @@ -319,7 +356,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return true; } - public boolean renderProcesses(XhtmlNode x, ExampleScenario scen) throws IOException { + public boolean renderProcesses(RenderingStatus status, XhtmlNode x, ExampleScenario scen) throws IOException { Map actors = new HashMap<>(); for (ExampleScenarioActorComponent actor: scen.getActor()) { actors.put(actor.getKey(), actor); @@ -332,15 +369,15 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { int num = 1; for (ExampleScenarioProcessComponent process : scen.getProcess()) { - renderProcess(x, process, Integer.toString(num), actors, instances); + renderProcess(status, x, process, Integer.toString(num), actors, instances); num++; } return true; } - public void renderProcess(XhtmlNode x, ExampleScenarioProcessComponent process, String prefix, Map actors, Map instances) throws IOException { + public void renderProcess(RenderingStatus status, XhtmlNode x, ExampleScenarioProcessComponent process, String prefix, Map actors, Map instances) throws IOException { XhtmlNode div = x.div(); - div.an("p_" + prefix); + div.an(context.prefixAnchor("p_" + prefix)); div.b().tx(context.formatPhrase(RenderingContext.EX_SCEN_PROC, process.getTitle())+" "); if (process.hasDescription()) addMarkdown(div, process.getDescription()); @@ -363,14 +400,14 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { thead.th().addText(context.formatPhrase(RenderingContext.EX_SCEN_RES)); int stepCount = 1; for (ExampleScenarioProcessStepComponent step: process.getStep()) { - renderStep(tbl, step, stepPrefix(prefix, step, stepCount), actors, instances); + renderStep(status, tbl, step, stepPrefix(prefix, step, stepCount), actors, instances); stepCount++; } // Now go through the steps again and spit out any child processes stepCount = 1; for (ExampleScenarioProcessStepComponent step: process.getStep()) { - stepSubProcesses(tbl, step, stepPrefix(prefix, step, stepCount), actors, instances); + stepSubProcesses(status, tbl, step, stepPrefix(prefix, step, stepCount), actors, instances); stepCount++; } } @@ -384,15 +421,15 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { return stepPrefix(prefix + "-Alt" + Integer.toString(altNum) + ".", step, stepCount); } - private void stepSubProcesses(XhtmlNode x, ExampleScenarioProcessStepComponent step, String prefix, Map actors, Map instances) throws IOException { + private void stepSubProcesses(RenderingStatus status, XhtmlNode x, ExampleScenarioProcessStepComponent step, String prefix, Map actors, Map instances) throws IOException { if (step.hasProcess()) - renderProcess(x, step.getProcess(), prefix, actors, instances); + renderProcess(status, x, step.getProcess(), prefix, actors, instances); if (step.hasAlternative()) { int altNum = 1; for (ExampleScenarioProcessStepAlternativeComponent alt: step.getAlternative()) { int stepCount = 1; for (ExampleScenarioProcessStepComponent altStep: alt.getStep()) { - stepSubProcesses(x, altStep, altStepPrefix(prefix, altStep, altNum, stepCount), actors, instances); + stepSubProcesses(status, x, altStep, altStepPrefix(prefix, altStep, altNum, stepCount), actors, instances); stepCount++; } altNum++; @@ -400,22 +437,22 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { } } - private boolean renderStep(XhtmlNode tbl, ExampleScenarioProcessStepComponent step, String stepLabel, Map actors, Map instances) throws IOException { + private boolean renderStep(RenderingStatus status, XhtmlNode tbl, ExampleScenarioProcessStepComponent step, String stepLabel, Map actors, Map instances) throws IOException { XhtmlNode row = tbl.tr(); XhtmlNode prefixCell = row.td(); - prefixCell.an("s_" + stepLabel); + prefixCell.an(context.prefixAnchor("s_" + stepLabel)); prefixCell.tx(stepLabel.substring(stepLabel.indexOf(".") + 1)); if (step.hasProcess()) { XhtmlNode n = row.td().colspan(6); n.tx(context.formatPhrase(RenderingContext.EX_SCEN_SEE)); - n.ah("#p_" + stepLabel, step.getProcess().getTitle()); + n.ah(context.prefixLocalHref("#p_" + stepLabel), step.getProcess().getTitle()); n.tx(" "+ context.formatPhrase(RenderingContext.EX_SCEN_BEL)); } else if (step.hasWorkflow()) { XhtmlNode n = row.td().colspan(6); n.tx(context.formatPhrase(RenderingContext.EX_SCEN_OTH)); String link = new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), step.getWorkflow()); - n.ah(link, step.getProcess().getTitle()); + n.ah(context.prefixLocalHref(link), step.getProcess().getTitle()); } else { // Must be an operation @@ -424,7 +461,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { name.tx(op.getTitle()); if (op.hasType()) { name.tx(" - "); - renderCoding(name, op.getType()); + renderCoding(status, name, wrapNC(op.getType())); } XhtmlNode descCell = row.td(); addMarkdown(descCell, op.getDescription()); @@ -443,7 +480,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { addMarkdown(altHeading, alt.getDescription()); int stepCount = 1; for (ExampleScenarioProcessStepComponent subStep : alt.getStep()) { - renderStep(tbl, subStep, altStepPrefix(stepLabel, step, altNum, stepCount), actors, instances); + renderStep(status, tbl, subStep, altStepPrefix(stepLabel, step, altNum, stepCount), actors, instances); stepCount++; } altNum++; @@ -479,9 +516,9 @@ public class ExampleScenarioRenderer extends TerminologyRenderer { } if (theVersion==null) throw new FHIRException("Unable to find referenced version " + instanceRef.getVersionReference() + " within instance " + instanceRef.getInstanceReference()); - instanceCell.ah("#i_" + instance.getKey() + "v_"+ theVersion.getKey() , theVersion.getDescription()).tx(theVersion.getTitle()); + instanceCell.ah(context.prefixLocalHref("#i_" + instance.getKey() + "v_"+ theVersion.getKey()) , theVersion.getDescription()).tx(theVersion.getTitle()); } else - instanceCell.ah("#i_" + instance.getKey(), instance.getDescription()).tx(instance.getTitle()); + instanceCell.ah(context.prefixLocalHref("#i_" + instance.getKey()), instance.getDescription()).tx(instance.getTitle()); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ImplementationGuideRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ImplementationGuideRenderer.java index 29a3bf2d2..a3bd14f29 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ImplementationGuideRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ImplementationGuideRenderer.java @@ -4,34 +4,43 @@ import java.io.IOException; 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.model.ImplementationGuide; -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.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class ImplementationGuideRenderer extends ResourceRenderer { - public ImplementationGuideRenderer(RenderingContext context) { - super(context); - } - - public ImplementationGuideRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); + public ImplementationGuideRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (ImplementationGuide) r.getBase()); + render(status, x, (ImplementationGuide) r.getBase()); + } else { + throw new Error("ImplementationGuideRenderer only renders native resources directly"); + } } - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (ImplementationGuide) dr); + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public boolean render(XhtmlNode x, ImplementationGuide ig) throws FHIRFormatError, DefinitionException, IOException { + + public void render(RenderingStatus status, XhtmlNode x, ImplementationGuide ig) throws FHIRFormatError, DefinitionException, IOException { + x.h2().addText(ig.getName()); x.para().tx(context.formatPhrase(RenderingContext.IMP_GUIDE_URL)+" "); x.pre().tx(ig.getUrl()); addMarkdown(x, ig.getDescription()); - return true; } public void describe(XhtmlNode x, ImplementationGuide ig) { @@ -42,19 +51,5 @@ public class ImplementationGuideRenderer extends ResourceRenderer { return ig.present(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((ImplementationGuide) r).present(); - } - - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LibraryRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LibraryRenderer.java index e0ec18632..1e0b02701 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LibraryRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/LibraryRenderer.java @@ -8,126 +8,117 @@ import org.apache.commons.codec.binary.Base64; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Attachment; import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.ContactDetail; -import org.hl7.fhir.r5.model.ContactPoint; -import org.hl7.fhir.r5.model.DataRequirement; -import org.hl7.fhir.r5.model.Library; -import org.hl7.fhir.r5.model.ParameterDefinition; -import org.hl7.fhir.r5.model.RelatedArtifact; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class LibraryRenderer extends ResourceRenderer { - private static final int DATA_IMG_SIZE_CUTOFF = 4000; - - public LibraryRenderer(RenderingContext context) { - super(context); - } - - public LibraryRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } + private static final int DATA_IMG_SIZE_CUTOFF = 4000; - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (Library) dr); + public LibraryRenderer(RenderingContext context) { + super(context); + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public boolean render(XhtmlNode x, ResourceWrapper lib) throws FHIRFormatError, DefinitionException, IOException { - PropertyWrapper authors = lib.getChildByName("author"); - PropertyWrapper editors = lib.getChildByName("editor"); - PropertyWrapper reviewers = lib.getChildByName("reviewer"); - PropertyWrapper endorsers = lib.getChildByName("endorser"); - if ((authors != null && authors.hasValues()) || (editors != null && editors.hasValues()) || (reviewers != null && reviewers.hasValues()) || (endorsers != null && endorsers.hasValues())) { + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper lib) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(lib, x); + genSummaryTable(status, x, (CanonicalResource) lib.getResourceNative()); + List authors = lib.children("author"); + List editors = lib.children("editor"); + List reviewers = lib.children("reviewer"); + List endorsers = lib.children("endorser"); + if (!authors.isEmpty() || !editors.isEmpty() || !reviewers.isEmpty() || !endorsers.isEmpty()) { boolean email = hasCT(authors, "email") || hasCT(editors, "email") || hasCT(reviewers, "email") || hasCT(endorsers, "email"); boolean phone = hasCT(authors, "phone") || hasCT(editors, "phone") || hasCT(reviewers, "phone") || hasCT(endorsers, "phone"); boolean url = hasCT(authors, "url") || hasCT(editors, "url") || hasCT(reviewers, "url") || hasCT(endorsers, "url"); x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_PAR)); XhtmlNode t = x.table("grid"); - if (authors != null) { - for (BaseWrapper cd : authors.getValues()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_AUT)), cd, email, phone, url); - } + for (ResourceWrapper cd : authors) { + participantRow(status, t, (context.formatPhrase(RenderingContext.LIB_REND_AUT)), cd, email, phone, url); } - if (authors != null) { - for (BaseWrapper cd : editors.getValues()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_ED)), cd, email, phone, url); - } + + for (ResourceWrapper cd : editors) { + participantRow(status, t, (context.formatPhrase(RenderingContext.LIB_REND_ED)), cd, email, phone, url); } - if (authors != null) { - for (BaseWrapper cd : reviewers.getValues()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_REV)), cd, email, phone, url); - } + for (ResourceWrapper cd : reviewers) { + participantRow(status, t, (context.formatPhrase(RenderingContext.LIB_REND_REV)), cd, email, phone, url); } - if (authors != null) { - for (BaseWrapper cd : endorsers.getValues()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_END)), cd, email, phone, url); - } + for (ResourceWrapper cd : endorsers) { + participantRow(status, t, (context.formatPhrase(RenderingContext.LIB_REND_END)), cd, email, phone, url); } } - PropertyWrapper artifacts = lib.getChildByName("relatedArtifact"); - if (artifacts != null && artifacts.hasValues()) { + List artifacts = lib.children("relatedArtifact"); + if (!artifacts.isEmpty()) { x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_ART)); XhtmlNode t = x.table("grid"); boolean label = false; boolean display = false; boolean citation = false; - for (BaseWrapper ra : artifacts.getValues()) { + for (ResourceWrapper ra : artifacts) { label = label || ra.has("label"); display = display || ra.has("display"); citation = citation || ra.has("citation"); } - for (BaseWrapper ra : artifacts.getValues()) { - renderArtifact(t, ra, lib, label, display, citation); + for (ResourceWrapper ra : artifacts) { + renderArtifact(status, t, ra, lib, label, display, citation); } } - PropertyWrapper parameters = lib.getChildByName("parameter"); - if (parameters != null && parameters.hasValues()) { + List parameters = lib.children("parameter"); + if (!parameters.isEmpty()) { x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS)); XhtmlNode t = x.table("grid"); boolean doco = false; - for (BaseWrapper p : parameters.getValues()) { + for (ResourceWrapper p : parameters) { doco = doco || p.has("documentation"); } - for (BaseWrapper p : parameters.getValues()) { + for (ResourceWrapper p : parameters) { renderParameter(t, p, doco); } } - PropertyWrapper dataRequirements = lib.getChildByName("dataRequirement"); - if (dataRequirements != null && dataRequirements.hasValues()) { + List dataRequirements = lib.children("dataRequirement"); + if (!dataRequirements.isEmpty()) { x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_REQ)); - for (BaseWrapper p : dataRequirements.getValues()) { - renderDataRequirement(x, (DataRequirement) p.getBase()); + for (ResourceWrapper p : dataRequirements) { + renderDataRequirement(status, x, p); } } - PropertyWrapper contents = lib.getChildByName("content"); - if (contents != null) { + List contents = lib.children("content"); + if (!contents.isEmpty()) { x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_CONT)); boolean isCql = false; int counter = 0; - for (BaseWrapper p : contents.getValues()) { - Attachment att = (Attachment) p.getBase(); - renderAttachment(x, att, isCql, counter, lib.getId()); - isCql = isCql || (att.hasContentType() && att.getContentType().startsWith("text/cql")); + for (ResourceWrapper p : contents) { + renderAttachment(x, p, isCql, counter, lib.getId()); + isCql = isCql || (p.has("contentType") && p.primitiveValue("contentType").startsWith("text/cql")); counter++; } } - return false; } - private boolean hasCT(PropertyWrapper prop, String type) throws UnsupportedEncodingException, FHIRException, IOException { - if (prop != null) { - for (BaseWrapper cd : prop.getValues()) { - PropertyWrapper telecoms = cd.getChildByName("telecom"); - if (getContactPoint(telecoms, type) != null) { + private boolean hasCT(List list, String type) throws UnsupportedEncodingException, FHIRException, IOException { + for (ResourceWrapper cd : list) { + List telecoms = cd.children("telecom"); + if (hasContactPoint(telecoms, type)) { + return true; + } + } + return false; + } + + private boolean hasContactPoint(List list, String type) { + for (ResourceWrapper cd : list) { + for (ResourceWrapper t : cd.children("telecom")) { + if (type.equals(t.primitiveValue("system"))) { return true; } } @@ -135,273 +126,135 @@ public class LibraryRenderer extends ResourceRenderer { return false; } - private boolean hasCT(List list, String type) { - for (ContactDetail cd : list) { - for (ContactPoint t : cd.getTelecom()) { - if (type.equals(t.getSystem().toCode())) { - return true; + private ResourceWrapper getContactPoint(List list, String type) { + for (ResourceWrapper cd : list) { + for (ResourceWrapper t : cd.children("telecom")) { + if (type.equals(t.primitiveValue("system"))) { + return t; } } } - return false; - } - - - public boolean render(XhtmlNode x, Library lib) throws FHIRFormatError, DefinitionException, IOException { - if (lib.hasAuthor() || lib.hasEditor() || lib.hasReviewer() || lib.hasEndorser()) { - boolean email = hasCT(lib.getAuthor(), "email") || hasCT(lib.getEditor(), "email") || hasCT(lib.getReviewer(), "email") || hasCT(lib.getEndorser(), "email"); - boolean phone = hasCT(lib.getAuthor(), "phone") || hasCT(lib.getEditor(), "phone") || hasCT(lib.getReviewer(), "phone") || hasCT(lib.getEndorser(), "phone"); - boolean url = hasCT(lib.getAuthor(), "url") || hasCT(lib.getEditor(), "url") || hasCT(lib.getReviewer(), "url") || hasCT(lib.getEndorser(), "url"); - x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_PAR)); - XhtmlNode t = x.table("grid"); - for (ContactDetail cd : lib.getAuthor()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_AUT)), cd, email, phone, url); - } - for (ContactDetail cd : lib.getEditor()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_ED)), cd, email, phone, url); - } - for (ContactDetail cd : lib.getReviewer()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_REV)), cd, email, phone, url); - } - for (ContactDetail cd : lib.getEndorser()) { - participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_END)), cd, email, phone, url); - } - } - if (lib.hasRelatedArtifact()) { - x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_ART)); - XhtmlNode t = x.table("grid"); - boolean label = false; - boolean display = false; - boolean citation = false; - for (RelatedArtifact ra : lib.getRelatedArtifact()) { - label = label || ra.hasLabel(); - display = display || ra.hasDisplay(); - citation = citation || ra.hasCitation(); - } - for (RelatedArtifact ra : lib.getRelatedArtifact()) { - renderArtifact(t, ra, lib, label, display, citation); - } - } - if (lib.hasParameter()) { - x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS)); - XhtmlNode t = x.table("grid"); - boolean doco = false; - for (ParameterDefinition p : lib.getParameter()) { - doco = doco || p.hasDocumentation(); - } - for (ParameterDefinition p : lib.getParameter()) { - renderParameter(t, p, doco); - } - } - if (lib.hasDataRequirement()) { - x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_REQ)); - for (DataRequirement p : lib.getDataRequirement()) { - renderDataRequirement(x, p); - } - } - if (lib.hasContent()) { - x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_CONT)); - boolean isCql = false; - int counter = 0; - for (Attachment att : lib.getContent()) { - renderAttachment(x, att, isCql, counter, lib.getId()); - isCql = isCql || (att.hasContentType() && att.getContentType().startsWith("text/cql")); - counter++; - } - } - return false; - } - - private void renderParameter(XhtmlNode t, BaseWrapper p, boolean doco) throws UnsupportedEncodingException, FHIRException, IOException { - XhtmlNode tr = t.tr(); - tr.td().tx(p.has("name") ? p.get("name").primitiveValue() : null); - tr.td().tx(p.has("use") ? p.get("use").primitiveValue() : null); - tr.td().tx(p.has("min") ? p.get("min").primitiveValue() : null); - tr.td().tx(p.has("max") ? p.get("max").primitiveValue() : null); - tr.td().tx(p.has("type") ? p.get("type").primitiveValue() : null); - if (doco) { - tr.td().tx(p.has("documentation") ? p.get("documentation").primitiveValue() : null); - } - } - - private void renderParameter(XhtmlNode t, ParameterDefinition p, boolean doco) { - XhtmlNode tr = t.tr(); - tr.td().tx(p.getName()); - tr.td().tx(p.getUse().getDisplay()); - tr.td().tx(p.getMin()); - tr.td().tx(p.getMax()); - tr.td().tx(p.getType().getDisplay()); - if (doco) { - tr.td().tx(p.getDocumentation()); - } - } - - private void renderArtifact(XhtmlNode t, BaseWrapper ra, ResourceWrapper lib, boolean label, boolean display, boolean citation) throws UnsupportedEncodingException, FHIRException, IOException { - XhtmlNode tr = t.tr(); - tr.td().tx(ra.has("type") ? ra.get("type").primitiveValue() : null); - if (label) { - tr.td().tx(ra.has("label") ? ra.get("label").primitiveValue() : null); - } - if (display) { - tr.td().tx(ra.has("display") ? ra.get("display").primitiveValue() : null); - } - if (citation) { - tr.td().markdown(ra.has("citation") ? ra.get("citation").primitiveValue() : null, "Citation"); - } - if (ra.has("resource")) { - renderCanonical(lib, tr.td(), ra.get("resource").primitiveValue()); - } else { - tr.td().tx(ra.has("url") ? ra.get("url").primitiveValue() : null); - } - } - - private void renderArtifact(XhtmlNode t, RelatedArtifact ra, Resource lib, boolean label, boolean display, boolean citation) throws IOException { - XhtmlNode tr = t.tr(); - tr.td().tx(ra.getType().getDisplay()); - if (label) { - tr.td().tx(ra.getLabel()); - } - if (display) { - tr.td().tx(ra.getDisplay()); - } - if (citation) { - tr.td().markdown(ra.getCitation(), "Citation"); - } - if (ra.hasResource()) { - renderCanonical(lib, tr.td(), ra.getResource()); - } else { - renderAttachment(tr.td(), ra.getDocument(), false, 0, lib.getId()); - } - } - - private void participantRow(XhtmlNode t, String label, BaseWrapper cd, boolean email, boolean phone, boolean url) throws UnsupportedEncodingException, FHIRException, IOException { - XhtmlNode tr = t.tr(); - tr.td().tx(label); - tr.td().tx(cd.get("name") != null ? cd.get("name").primitiveValue() : null); - PropertyWrapper telecoms = cd.getChildByName("telecom"); - if (email) { - renderContactPoint(tr.td(), getContactPoint(telecoms, "email")); - } - if (phone) { - renderContactPoint(tr.td(), getContactPoint(telecoms, "phone")); - } - if (url) { - renderContactPoint(tr.td(), getContactPoint(telecoms, "url")); - } - } - - private ContactPoint getContactPoint(PropertyWrapper telecoms, String value) throws UnsupportedEncodingException, FHIRException, IOException { - for (BaseWrapper t : telecoms.getValues()) { - if (t.has("system")) { - String system = t.get("system").primitiveValue(); - if (value.equals(system)) { - return (ContactPoint) t.getBase(); - } - } - } return null; } - private void participantRow(XhtmlNode t, String label, ContactDetail cd, boolean email, boolean phone, boolean url) { + private void renderParameter(XhtmlNode t, ResourceWrapper p, boolean doco) throws UnsupportedEncodingException, FHIRException, IOException { + XhtmlNode tr = t.tr(); + tr.td().tx(p.has("name") ? p.primitiveValue("name") : null); + tr.td().tx(p.has("use") ? p.primitiveValue("use") : null); + tr.td().tx(p.has("min") ? p.primitiveValue("min") : null); + tr.td().tx(p.has("max") ? p.primitiveValue("max") : null); + tr.td().tx(p.has("type") ? p.primitiveValue("type") : null); + if (doco) { + tr.td().tx(p.has("documentation") ? p.primitiveValue("documentation") : null); + } + } + + + private void renderArtifact(RenderingStatus status, XhtmlNode t, ResourceWrapper ra, ResourceWrapper lib, boolean label, boolean display, boolean citation) throws UnsupportedEncodingException, FHIRException, IOException { + XhtmlNode tr = t.tr(); + tr.td().tx(ra.has("type") ? getTranslatedCode(ra.child("type")) : null); + if (label) { + tr.td().tx(ra.has("label") ? ra.primitiveValue("label") : null); + } + if (display) { + tr.td().tx(ra.has("display") ? ra.primitiveValue("display") : null); + } + if (citation) { + tr.td().markdown(ra.has("citation") ? ra.primitiveValue("citation") : null, "Citation"); + } + if (ra.has("resource")) { + renderCanonical(status, tr.td(), Resource.class, ra.child("resource")); + } else { + tr.td().tx(ra.has("url") ? ra.primitiveValue("url") : null); + } + } + + private void participantRow(RenderingStatus status, XhtmlNode t, String label, ResourceWrapper cd, boolean email, boolean phone, boolean url) throws UnsupportedEncodingException, FHIRException, IOException { XhtmlNode tr = t.tr(); tr.td().tx(label); - tr.td().tx(cd.getName()); + tr.td().tx(cd.has("name") ? cd.primitiveValue("name") : null); + List telecoms = cd.children("telecom"); if (email) { - renderContactPoint(tr.td(), cd.getEmail()); + renderContactPoint(status, tr.td(), getContactPoint(telecoms, "email")); } if (phone) { - renderContactPoint(tr.td(), cd.getPhone()); + renderContactPoint(status, tr.td(), getContactPoint(telecoms, "phone")); } if (url) { - renderContactPoint(tr.td(), cd.getUrl()); + renderContactPoint(status, tr.td(), getContactPoint(telecoms, "url")); } } - public void describe(XhtmlNode x, Library lib) { - x.tx(display(lib)); - } - public String display(Library lib) { - return lib.present(); - } - - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((Library) r).present(); - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - return "??"; - } - - private void renderAttachment(XhtmlNode x, Attachment att, boolean noShowData, int counter, String baseId) { - boolean ref = !att.hasData() && att.hasUrl(); + private void renderAttachment(XhtmlNode x, ResourceWrapper att, boolean noShowData, int counter, String baseId) { + String url = att.primitiveValue("url"); + String title = att.primitiveValue("title"); + String ct = att.primitiveValue("contentType"); + + boolean ref = !att.has("data") && att.has("url"); if (ref) { XhtmlNode p = x.para(); - if (att.hasTitle()) { - p.tx(att.getTitle()); + if (att.has("title")) { + p.tx(title); p.tx(": "); } - Resource res = context.getContext().fetchResource(Resource.class, att.getUrl()); + Resource res = context.getContext().fetchResource(Resource.class, url); if (res == null || !res.hasWebPath()) { - p.code().ah(att.getUrl()).tx(att.getUrl()); + p.code().ah(context.prefixLocalHref(url)).tx(url); } else if (res instanceof CanonicalResource) { - p.code().ah(res.getWebPath()).tx(((CanonicalResource) res).present()); + p.code().ah(context.prefixLocalHref(res.getWebPath())).tx(((CanonicalResource) res).present()); } else { - p.code().ah(res.getWebPath()).tx(att.getUrl()); + p.code().ah(context.prefixLocalHref(res.getWebPath())).tx(url); } p.tx(" ("); - p.code().tx(att.getContentType()); + p.code().tx(ct); p.tx(lang(att)); p.tx(")"); - } else if (!att.hasData()) { + } else if (!att.has("data")) { XhtmlNode p = x.para(); - if (att.hasTitle()) { - p.tx(att.getTitle()); + if (att.has("title")) { + p.tx(title); p.tx(": "); } p.code().tx(context.formatPhrase(RenderingContext.LIB_REND_NOCONT)); p.tx(" ("); - p.code().tx(att.getContentType()); + p.code().tx(ct); p.tx(lang(att)); p.tx(")"); } else { - String txt = getText(att); - if (isImage(att.getContentType())) { + byte[] cnt = Base64.decodeBase64(att.primitiveValue("data")); + String txt = getText(cnt); + if (isImage(ct)) { XhtmlNode p = x.para(); - if (att.hasTitle()) { - p.tx(att.getTitle()); + if (att.has("title")) { + p.tx(title); p.tx(": ("); - p.code().tx(att.getContentType()); + p.code().tx(ct); p.tx(lang(att)); p.tx(")"); } else { - p.code().tx(att.getContentType()+lang(att)); + p.code().tx(ct+lang(att)); } - if (att.getData().length < LibraryRenderer.DATA_IMG_SIZE_CUTOFF) { - x.img("data: "+att.getContentType()+">;base64,"+b64(att.getData()), "data"); + if (cnt.length < LibraryRenderer.DATA_IMG_SIZE_CUTOFF) { + x.img("data: "+ct+">;base64,"+b64(cnt), "data"); } else { - String filename = "Library-"+baseId+(counter == 0 ? "" : "-"+Integer.toString(counter))+"."+imgExtension(att.getContentType()); + String filename = "Library-"+baseId+(counter == 0 ? "" : "-"+Integer.toString(counter))+"."+imgExtension(ct); x.img(filename, "data"); } } else if (txt != null && !noShowData) { XhtmlNode p = x.para(); - if (att.hasTitle()) { - p.tx(att.getTitle()); + if (att.has("title")) { + p.tx(title); p.tx(": ("); - p.code().tx(att.getContentType()); + p.code().tx(ct); p.tx(lang(att)); p.tx(")"); } else { - p.code().tx(att.getContentType()+lang(att)); + p.code().tx(ct+lang(att)); } - String prismCode = determinePrismCode(att); + String prismCode = determinePrismCode(ct); if (prismCode != null && !tooBig(txt)) { x.pre().code().setAttribute("class", "language-"+prismCode).tx(txt); } else { @@ -409,14 +262,14 @@ public class LibraryRenderer extends ResourceRenderer { } } else { XhtmlNode p = x.para(); - if (att.hasTitle()) { - p.tx(att.getTitle()); + if (att.has("title")) { + p.tx(title); p.tx(": "); } p.code().tx(context.formatPhrase(RenderingContext.LIB_REND_SHOW)); - p.code().tx(att.getContentType()); + p.code().tx(ct); p.tx(lang(att)); - p.tx((context.formatPhrase(RenderingContext.LIB_REND_SIZE, Utilities.describeSize(att.getData().length))+" ")+")"); + p.tx((context.formatPhrase(RenderingContext.LIB_REND_SIZE, Utilities.describeSize(cnt.length))+" ")+")"); } } } @@ -446,17 +299,17 @@ public class LibraryRenderer extends ResourceRenderer { return imgExtension(contentType) != null; } - private String lang(Attachment att) { - if (att.hasLanguage()) { - return ", language = "+describeLang(att.getLanguage()); + private String lang(ResourceWrapper att) { + if (att.has("language")) { + return ", language = "+describeLang(att.primitiveValue("language")); } return ""; } - private String getText(Attachment att) { + private String getText( byte[] cnt) { try { try { - String src = new String(att.getData(), "UTF-8"); + String src = new String(cnt, "UTF-8"); if (checkString(src)) { return src; } @@ -464,7 +317,7 @@ public class LibraryRenderer extends ResourceRenderer { // ignore } try { - String src = new String(att.getData(), "UTF-16"); + String src = new String(cnt, "UTF-16"); if (checkString(src)) { return src; } @@ -472,7 +325,7 @@ public class LibraryRenderer extends ResourceRenderer { // ignore } try { - String src = new String(att.getData(), "ASCII"); + String src = new String(cnt, "ASCII"); if (checkString(src)) { return src; } @@ -494,9 +347,8 @@ public class LibraryRenderer extends ResourceRenderer { return true; } - private String determinePrismCode(Attachment att) { - if (att.hasContentType()) { - String ct = att.getContentType(); + private String determinePrismCode(String ct) { + if (!Utilities.noString(ct)) { if (ct.contains(";")) { ct = ct.substring(0, ct.indexOf(";")); } @@ -524,10 +376,10 @@ public class LibraryRenderer extends ResourceRenderer { case "application/typescript" : return "typescript"; case "text/cql" : return "sql"; // not that bad... } - if (att.getContentType().contains("json+") || att.getContentType().contains("+json")) { + if (ct.contains("json+") || ct.contains("+json")) { return "json"; } - if (att.getContentType().contains("xml+") || att.getContentType().contains("+xml")) { + if (ct.contains("xml+") || ct.contains("+xml")) { return "xml"; } } 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 cb5a1afa5..78f7c2f75 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 @@ -9,11 +9,8 @@ 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.Reference; -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.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.LiquidEngine; import org.hl7.fhir.r5.utils.LiquidEngine.ILiquidRenderingSupport; @@ -25,33 +22,27 @@ 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) { - super(context); - this.liquidTemplate = liquidTemplate; + private class LiquidRendererContext { + private RenderingStatus status; + private ResourceWrapper resource; + protected LiquidRendererContext(RenderingStatus status, ResourceWrapper resource) { + super(); + this.status = status; + this.resource = resource; + } + } - - public LiquidRenderer(RenderingContext context, ResourceContext rcontext, String liquidTemplate) { - super(context); - this.rcontext = rcontext; + + public LiquidRenderer(RenderingContext context, String liquidTemplate) { + super(context); this.liquidTemplate = liquidTemplate; + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } /** @@ -72,14 +63,14 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering } @Override - public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { LiquidEngine engine = new LiquidEngine(context.getWorker(), context.getServices()); XhtmlNode xn; try { engine.setIncludeResolver(new LiquidRendererIncludeResolver(context)); engine.setRenderingSupport(this); LiquidDocument doc = engine.parse(liquidTemplate, "template"); - String html = engine.evaluate(doc, r, rcontext); + String html = engine.evaluate(doc, r.getBase(), new LiquidRendererContext(status, r)); xn = new XhtmlParser().parseFragment(html); if (!x.getName().equals("div")) throw new FHIRException("Error in template: Root element is not 'div'"); @@ -88,42 +79,7 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering xn.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage()); } x.getChildNodes().addAll(xn.getChildNodes()); - return true; - } - - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return "not done yet"; - } - - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } - - @Override - public boolean render(XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - LiquidEngine engine = new LiquidEngine(context.getWorker(), context.getServices()); - XhtmlNode xn; - try { - engine.setIncludeResolver(new LiquidRendererIncludeResolver(context)); - LiquidDocument doc = engine.parse(liquidTemplate, "template"); - engine.setRenderingSupport(this); - 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'"); - } catch (FHIRException | IOException e) { - xn = new XhtmlNode(NodeType.Element, "div"); - xn.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage()); - } - x.getChildNodes().addAll(xn.getChildNodes()); - return true; + status.setExtensions(true); } public RendererType getRendererType() { @@ -133,17 +89,17 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering @Override public String renderForLiquid(Object appContext, Base base) throws FHIRException { try { + LiquidRendererContext ctxt = (LiquidRendererContext) appContext; + ResourceWrapper r = null; if (base instanceof Element) { - base = context.getParser().parseType((Element) base); - } - XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - if (base instanceof Reference) { - renderReference(((LiquidRendererContxt) appContext).getResource(), x, (Reference) base); + r = ResourceWrapper.forType(context.getContextUtilities(), (Element) base); } else if (base instanceof DataType) { - render(x, (DataType) base); + r = ResourceWrapper.forType(context.getContextUtilities(), (DataType) base); } else { - x.tx(base.toString()); + return base.toString(); } + XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); + renderDataType(ctxt.status, x, r); String res = new XhtmlComposer(true).compose(x); res = res.substring(5); if (res.length() < 6) { 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 8d4e20b13..33612c21f 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 @@ -1,21 +1,15 @@ package org.hl7.fhir.r5.renderers; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Annotation; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.ListResource; -import org.hl7.fhir.r5.model.ListResource.ListResourceEntryComponent; -import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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.r5.renderers.utils.Resolver.ResourceWithReference; +import java.io.IOException; +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.model.ListResource; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class ListRenderer extends ResourceRenderer { @@ -24,57 +18,59 @@ public class ListRenderer extends ResourceRenderer { super(context); } - public ListRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (ListResource) dr); - } - - public boolean render(XhtmlNode x, ResourceWrapper list) throws FHIRFormatError, DefinitionException, IOException { + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + ResourceWrapper c = r.child("code"); + String cd = c == null ? context.formatPhrase(RenderingContext.LIST_UNSPECIFIED_CODE) : displayCodeableConcept(c); + ResourceWrapper s = r.child("subject"); + String sd = s == null ? context.formatPhrase(RenderingContext.LIST_UNSPECIFIED_SUBJECT) : displayReference(s); + return context.formatPhrase(RenderingContext.LIST_SUMMARY, cd, sd); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper list) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(list, x); if (list.has("title")) { - x.h2().tx(list.get("title").primitiveValue()); + x.h2().tx(list.primitiveValue("title")); } XhtmlNode t = x.table("clstu"); XhtmlNode tr = t.tr(); - XhtmlNode td = tr.td(); if (list.has("date")) { - td.tx(context.formatPhrase(RenderingContext.LIST_REND_DATE, displayDateTime(list.get("date").dateTimeValue()))+" "); + tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DATE, displayDateTime(list.child("date")))+" "); } if (list.has("mode")) { - td.tx(context.formatPhrase(RenderingContext.LIST_REND_MODE, list.get("mode").primitiveValue())+" "); + tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_MODE, getTranslatedCode(list.child("mode")))+" "); } if (list.has("status")) { - td.tx(context.formatPhrase(RenderingContext.LIST_REND_STAT, list.get("status").primitiveValue())+" "); + tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_STAT, getTranslatedCode(list.child("status")))+" "); } if (list.has("code")) { - td.tx(context.formatPhrase(RenderingContext.LIST_REND_CODE, displayBase(list.get("code")))+" "); + tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_CODE, displayDataType(list.child("code")))+" "); } tr = t.tr(); - td = tr.td(); + XhtmlNode td = tr.td(); if (list.has("subject")) { td.tx(context.formatPhrase(RenderingContext.LIST_REND_SUB)+" "); - shortForRef(td, list.get("subject")); + renderReference(status, td, list.child("subject")); } if (list.has("encounter")) { td.tx(context.formatPhrase(RenderingContext.LIST_REND_ENC)+" "); - shortForRef(td, list.get("encounter")); + renderReference(status, td, list.child("encounter")); } if (list.has("source")) { td.tx(context.formatPhrase(RenderingContext.GENERAL_SRC)+" "); - shortForRef(td, list.get("encounter")); + renderReference(status, td, list.child("encounter")); } if (list.has("orderedBy")) { - td.tx(context.formatPhrase(RenderingContext.LIST_REND_ORD, displayBase(list.get("orderedBy")))+" "); + td.tx(context.formatPhrase(RenderingContext.LIST_REND_ORD, displayDataType(list.child("orderedBy")))+" "); + } + for (ResourceWrapper a : list.children("note")) { + renderAnnotation(status, x, a); } - // for (Annotation a : list.getNote()) { - // renderAnnotation(a, x); - // } boolean flag = false; boolean deleted = false; boolean date = false; - for (BaseWrapper e : list.children("entry")) { + for (ResourceWrapper e : list.children("entry")) { flag = flag || e.has("flag"); deleted = deleted || e.has("deleted"); date = date || e.has("date"); @@ -91,105 +87,21 @@ public class ListRenderer extends ResourceRenderer { if (deleted) { tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DEL)); } - for (BaseWrapper e : list.children("entry")) { + for (ResourceWrapper e : list.children("entry")) { tr = t.tr(); - shortForRef(tr.td(), e.get("item")); + renderReference(status, tr.td(), e.child("item")); if (date) { - tr.td().tx(e.has("date") ? e.get("date").dateTimeValue().toHumanDisplay() : ""); + tr.td().tx(e.has("date") ? displayDateTime(e.child("date")) : ""); } if (flag) { - tr.td().tx(e.has("flag") ? displayBase(e.get("flag")) : ""); + tr.td().tx(e.has("flag") ? displayDataType(e.child("flag")) : ""); } if (deleted) { - tr.td().tx(e.has("deleted") ? e.get("deleted").primitiveValue() : ""); + tr.td().tx(e.has("deleted") ? e.primitiveValue("deleted") : ""); } } - return false; } - public boolean render(XhtmlNode x, ListResource list) throws FHIRFormatError, DefinitionException, IOException { - if (list.hasTitle()) { - x.h2().tx(list.getTitle()); - } - XhtmlNode t = x.table("clstu"); - XhtmlNode tr = t.tr(); - if (list.hasDate()) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DATE, displayDateTime(list.getDateElement()))+" "); - } - if (list.hasMode()) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_MODE, list.getMode().getDisplay())+" "); - } - if (list.hasStatus()) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_STAT, list.getStatus().getDisplay())+" "); - } - if (list.hasCode()) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_CODE, display(list.getCode()))+" "); - } - tr = t.tr(); - if (list.hasSubject()) { - if (list.getSubject().size() == 1) { - shortForRef(tr.td().txN("Subject: "), list.getSubjectFirstRep()); - } else { - XhtmlNode td = tr.td(); - td.txN(context.formatPhrase(RenderingContext.LIST_REND_SUB)+" "); - int i = 0; - for (Reference subj : list.getSubject()) { - if (i == list.getSubject().size() - 1) { - td.tx(" and "); - } else if (i > 0) { - td.tx(", "); - } - shortForRef(td, subj); - } - } - } - if (list.hasEncounter()) { - shortForRef(tr.td().txN(context.formatPhrase(RenderingContext.LIST_REND_ENC)+" "), list.getEncounter()); - } - if (list.hasSource()) { - shortForRef(tr.td().txN(context.formatPhrase(RenderingContext.GENERAL_SRC)+" "), list.getEncounter()); - } - if (list.hasOrderedBy()) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_ORD, display(list.getOrderedBy()))+" "); - } - for (Annotation a : list.getNote()) { - renderAnnotation(x, a); - } - boolean flag = false; - boolean deleted = false; - boolean date = false; - for (ListResourceEntryComponent e : list.getEntry()) { - flag = flag || e.hasFlag(); - deleted = deleted || e.hasDeleted(); - date = date || e.hasDate(); - } - t = x.table("grid"); - tr = t.tr().style("backgound-color: #eeeeee"); - tr.td().b().tx(context.formatPhrase(RenderingContext.LIST_REND_ITEM)); - if (date) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DAT)); - } - if (flag) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_FLAG)); - } - if (deleted) { - tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DEL)); - } - for (ListResourceEntryComponent e : list.getEntry()) { - tr = t.tr(); - shortForRef(tr.td(), e.getItem()); - if (date) { - tr.td().tx(e.hasDate() ? e.getDate().toLocaleString() : ""); - } - if (flag) { - tr.td().tx(e.hasFlag() ? display(e.getFlag()) : ""); - } - if (deleted) { - tr.td().tx(e.hasDeleted() ? Boolean.toString(e.getDeleted()) : ""); - } - } - return false; - } - + public void describe(XhtmlNode x, ListResource list) { x.tx(display(list)); } @@ -198,56 +110,5 @@ public class ListRenderer extends ResourceRenderer { return list.getTitle(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((ListResource) r).getTitle(); - } - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - return "??"; - } - - private void shortForRef(XhtmlNode x, Reference ref) throws UnsupportedEncodingException, IOException { - ResourceWithReference r = context.getResolver() == null ? null : context.getResolver().resolve(context, ref.getReference()); - if (r == null) { - x.tx(display(ref)); - } else { - RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, ref); - } - } - - private XhtmlNode shortForRef(XhtmlNode x, Base ref) throws UnsupportedEncodingException, IOException { - if (ref == null) { - x.tx("(null)"); - } else { - 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(); - if (url.startsWith("#")) { - x.tx("?ngen-16a?"); - } else { - 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); - } else { - x.tx("?ngen-16?"); - } - } - return x; - } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/NamingSystemRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/NamingSystemRenderer.java index e750f31f2..29f26f9ff 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/NamingSystemRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/NamingSystemRenderer.java @@ -4,32 +4,43 @@ import java.io.IOException; 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.model.NamingSystem; import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent; -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.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class NamingSystemRenderer extends ResourceRenderer { - public NamingSystemRenderer(RenderingContext context) { - super(context); + + public NamingSystemRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (NamingSystem) r.getBase()); + render(status, x, (NamingSystem) r.getBase()); + } else { + throw new Error("NamingSystemRenderer only renders native resources directly"); + } } - public NamingSystemRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } + - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (NamingSystem) dr); - } - public boolean render(XhtmlNode x, NamingSystem ns) throws FHIRFormatError, DefinitionException, IOException { + public void render(RenderingStatus status, XhtmlNode x, NamingSystem ns) throws FHIRFormatError, DefinitionException, IOException { x.h3().tx(context.formatPhrase(RenderingContext.GENERAL_SUMM)); XhtmlNode tbl = x.table("grid"); row(tbl, (context.formatPhrase(RenderingContext.GENERAL_DEFINING_URL)), ns.getUrl()); @@ -53,7 +64,7 @@ public class NamingSystemRenderer extends ResourceRenderer { renderCommitteeLink(row(tbl, "Committee"), ns); } if (CodeSystemUtilities.hasOID(ns)) { - row(tbl, (context.formatPhrase(RenderingContext.GENERAL_OID)), CodeSystemUtilities.getOID(ns)).tx("("+(context.formatPhrase(RenderingContext.CODE_SYS_FOR_OID))+")"); + row(tbl, context.formatPhrase(RenderingContext.GENERAL_OID)).tx(context.formatPhrase(RenderingContext.CODE_SYS_FOR_OID, CodeSystemUtilities.getOID(ns))); } if (ns.hasCopyright()) { addMarkdown(row(tbl, (context.formatPhrase(RenderingContext.GENERAL_COPYRIGHT))), ns.getCopyright()); @@ -88,13 +99,12 @@ public class NamingSystemRenderer extends ResourceRenderer { tr.td().tx(id.getPreferredElement().primitiveValue()); } if (hasPeriod) { - tr.td().tx(display(id.getPeriod())); + tr.td().tx(displayDataType(id.getPeriod())); } if (hasComment) { tr.td().tx(id.getComment()); } } - return false; } private XhtmlNode row(XhtmlNode tbl, String name) { @@ -117,19 +127,4 @@ public class NamingSystemRenderer extends ResourceRenderer { return ns.present(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((NamingSystem) r).present(); - } - - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } - } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java index dc40ca976..3f2e76701 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ObligationsRenderer.java @@ -4,34 +4,21 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Set; -import org.fhir.ucum.Canonical; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.conformance.profile.BindingResolution; -import org.hl7.fhir.r5.conformance.profile.ProfileKnowledgeProvider; import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.r5.model.ActorDefinition; import org.hl7.fhir.r5.model.CanonicalType; -import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.UsageContext; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.renderers.CodeResolver.CodeResolution; -import org.hl7.fhir.r5.renderers.ObligationsRenderer.ObligationDetail; import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.utils.PublicationHacker; -import org.hl7.fhir.r5.utils.ToolingExtensions; -import org.hl7.fhir.utilities.MarkDownProcessor; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.VersionUtilities; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; @@ -40,7 +27,7 @@ import org.hl7.fhir.utilities.xhtml.XhtmlComposer; import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlNodeList; -public class ObligationsRenderer { +public class ObligationsRenderer extends Renderer { public static class ObligationDetail { private List codes = new ArrayList<>(); private List elementIds = new ArrayList<>(); @@ -167,6 +154,7 @@ public class ObligationsRenderer { private CodeResolver cr; public ObligationsRenderer(String corePath, StructureDefinition profile, String path, RenderingContext context, IMarkdownProcessor md, CodeResolver cr) { + super(context); this.corePath = corePath; this.profile = profile; this.path = path; @@ -286,24 +274,24 @@ public class ObligationsRenderer { return abr; } - public String render(String defPath, String anchorPrefix, List inScopeElements) throws IOException { + public String render(RenderingStatus status, ResourceWrapper res, String defPath, String anchorPrefix, List inScopeElements) throws IOException { if (obligations.isEmpty()) { return ""; } else { XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table"); tbl.attribute("class", "grid"); - renderTable(tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements); + renderTable(status, res, tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements); return new XhtmlComposer(false).compose(tbl); } } - public void renderTable(HierarchicalTableGenerator gen, Cell c, List inScopeElements) throws FHIRFormatError, DefinitionException, IOException { + public void renderTable(RenderingStatus status, ResourceWrapper res, HierarchicalTableGenerator gen, Cell c, List inScopeElements) throws FHIRFormatError, DefinitionException, IOException { if (obligations.isEmpty()) { return; } else { Piece piece = gen.new Piece("table").attr("class", "grid"); c.getPieces().add(piece); - renderTable(piece.getChildren(), false, gen.getDefPath(), gen.getAnchorPrefix(), inScopeElements); + renderTable(status, res, piece.getChildren(), false, gen.getDefPath(), gen.getAnchorPrefix(), inScopeElements); } } @@ -348,7 +336,7 @@ public class ObligationsRenderer { children.tx("="); } CodeResolution ccr = this.cr.resolveCode(uc.getValueCodeableConcept()); - children.ah(ccr.getLink(), ccr.getHint()).tx(ccr.getDisplay()); + children.ah(context.prefixLocalHref(ccr.getLink()), ccr.getHint()).tx(ccr.getDisplay()); } children.tx(")"); } @@ -358,7 +346,7 @@ public class ObligationsRenderer { } - public void renderTable(List children, boolean fullDoco, String defPath, String anchorPrefix, List inScopeElements) throws FHIRFormatError, DefinitionException, IOException { + public void renderTable(RenderingStatus status, ResourceWrapper res, List children, boolean fullDoco, String defPath, String anchorPrefix, List inScopeElements) throws FHIRFormatError, DefinitionException, IOException { boolean doco = false; boolean usage = false; boolean actor = false; @@ -441,7 +429,7 @@ public class ObligationsRenderer { } actorId = actorId.span(STYLE_REMOVED, null); if (compAd.hasWebPath()) { - actorId.ah(compAd.getWebPath(), compActor.toString()).tx(compAd.present()); + actorId.ah(context.prefixLocalHref(compAd.getWebPath()), compActor.toString()).tx(compAd.present()); } else { actorId.span(null, compActor.toString()).tx(compAd.present()); } @@ -462,7 +450,7 @@ public class ObligationsRenderer { String name = eid.substring(eid.indexOf(".") + 1); if (ed != null && inScope) { String link = defPath + "#" + anchorPrefix + eid; - elementIds.ah(link).tx(name); + elementIds.ah(context.prefixLocalHref(link)).tx(name); } else { elementIds.code().tx(name); } @@ -483,7 +471,7 @@ public class ObligationsRenderer { XhtmlNode td = tr.td(); for (UsageContext u : ob.usage) { if (first) first = false; else td.tx(", "); - new DataRenderer(context).render(td, u); + new DataRenderer(context).renderDataType(status, td, wrapWC(res, u)); } } else { tr.td(); @@ -545,7 +533,7 @@ public class ObligationsRenderer { CodeResolution cr = this.cr.resolveCode("http://hl7.org/fhir/tools/CodeSystem/obligation", code); code = code.replace("will-", "").replace("can-", ""); if (cr.getLink() != null) { - children.ah(cr.getLink(), cr.getHint()).tx(code); + children.ah(context.prefixLocalHref(cr.getLink()), cr.getHint()).tx(code); } else { children.span(null, cr.getHint()).tx(code); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java index 947e44c67..e9562de16 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationDefinitionRenderer.java @@ -1,47 +1,56 @@ package org.hl7.fhir.r5.renderers; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r5.model.CanonicalType; -import org.hl7.fhir.r5.model.CodeType; -import org.hl7.fhir.r5.model.Enumeration; -import org.hl7.fhir.r5.model.Enumerations.FHIRTypes; -import org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.OperationDefinition; -import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent; -import org.hl7.fhir.r5.model.OperationDefinition.OperationParameterScope; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; -import org.hl7.fhir.r5.utils.EOperationOutcome; -import org.hl7.fhir.r5.utils.ToolingExtensions; -import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; -import org.hl7.fhir.utilities.StandardsStatus; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.VersionUtilities; +import java.io.IOException; +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.model.CanonicalType; +import org.hl7.fhir.r5.model.Enumeration; +import org.hl7.fhir.r5.model.Enumerations.FHIRTypes; +import org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll; +import org.hl7.fhir.r5.model.Extension; +import org.hl7.fhir.r5.model.OperationDefinition; +import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent; +import org.hl7.fhir.r5.model.OperationDefinition.OperationParameterScope; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; +import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.StandardsStatus; +import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class OperationDefinitionRenderer extends TerminologyRenderer { + public OperationDefinitionRenderer(RenderingContext context) { super(context); } - public OperationDefinitionRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (OperationDefinition) r.getBase()); + render(status, x, (OperationDefinition) r.getBase()); + } else { + throw new Error("OperationDefinitionRenderer only renders native resources directly"); + } + } - public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome { - return render(x, (OperationDefinition) dr); - } - - public boolean render(XhtmlNode x, OperationDefinition opd) throws IOException, FHIRException, EOperationOutcome { - if (context.isHeader()) { + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + + public void render(RenderingStatus status, XhtmlNode x, OperationDefinition opd) throws IOException, FHIRException, EOperationOutcome { + if (context.isShowSummaryTable()) { x.h2().addText(opd.getName()); x.para().addText(Utilities.capitalize(opd.getKind().toString())+": "+opd.getName()); x.para().tx(context.formatPhrase(RenderingContext.OP_DEF_OFFIC)+" "); @@ -64,7 +73,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { if (sd == null) { p.pre().tx(opd.getInputProfile()); } else { - p.ah(sd.getWebPath()).tx(sd.present()); + p.ah(context.prefixLocalHref(sd.getWebPath())).tx(sd.present()); } } if (opd.hasOutputProfile()) { @@ -74,7 +83,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { if (sd == null) { p.pre().tx(opd.getOutputProfile()); } else { - p.ah(sd.getWebPath()).tx(sd.present()); + p.ah(context.prefixLocalHref(sd.getWebPath())).tx(sd.present()); } } x.para().tx(context.formatPhrase(RenderingContext.GENERAL_PARS)); @@ -91,7 +100,6 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { genOpParam(tbl, "", p, opd); } addMarkdown(x, opd.getComment()); - return true; } public void describe(XhtmlNode x, OperationDefinition opd) { @@ -138,10 +146,10 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { if (sdt == null) td.tx(p.hasType() ? actualType : ""); else - td.ah(sdt.getWebPath()).tx(s); + td.ah(context.prefixLocalHref(sdt.getWebPath())).tx(s); } } else - td.ah(sd.getWebPath()).tx(actualType); + td.ah(context.prefixLocalHref(sd.getWebPath())).tx(actualType); if (p.hasTargetProfile()) { td.tx(" ("); boolean first = true; @@ -151,7 +159,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { if (sdt == null || !sdt.hasWebPath()) { td.code().tx(tp.asStringValue()); } else { - td.ah(sdt.getWebPath(), tp.asStringValue()).tx(sdt.present()); + td.ah(context.prefixLocalHref(sdt.getWebPath()), tp.asStringValue()).tx(sdt.present()); } } td.tx(")"); @@ -159,7 +167,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer { if (p.hasSearchType()) { td.br(); td.tx("("); - td.ah( context.getLink(KnownLinkType.SPEC) == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "search.html#"+p.getSearchType().toCode())).tx(p.getSearchType().toCode()); + td.ah(context.prefixLocalHref(context.getLink(KnownLinkType.SPEC) == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "search.html#"+p.getSearchType().toCode()))).tx(p.getSearchType().toCode()); td.tx(")"); } td = tr.td(); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationOutcomeRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationOutcomeRenderer.java index b61ac61ae..b725fa17f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationOutcomeRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/OperationOutcomeRenderer.java @@ -1,48 +1,71 @@ package org.hl7.fhir.r5.renderers; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.ExtensionHelper; -import org.hl7.fhir.r5.model.OperationOutcome; -import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity; -import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StringType; -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.r5.utils.ToolingExtensions; -import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.List; + +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.model.OperationOutcome; +import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; +import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class OperationOutcomeRenderer extends ResourceRenderer { - + + public OperationOutcomeRenderer(RenderingContext context) { super(context); } - public OperationOutcomeRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (OperationOutcome) dr); - } - - public boolean render(XhtmlNode x, OperationOutcome op) throws FHIRFormatError, DefinitionException, IOException { + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + List issues = r.children("issue"); + int hint = 0; + int warn = 0; + int err = 0; + for (ResourceWrapper issue : issues) { + switch (issue.primitiveValue("severity")) { + case "information" : + hint++; + break; + case "warning" : + warn++; + break; + case "error" : + case "fatal" : + err++; + break; + } + } + if (hint + warn + err == 0) { + return context.formatPhrase(RenderingContext.OP_OUT_SUMM_ALL_OK); + } else if (hint == 0) { + return context.formatPhrase(RenderingContext.OP_OUT_SUMM_NOHINT, err, warn); + } else { + return context.formatPhrase(RenderingContext.OP_OUT_SUMM, err, warn, hint); + } + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper op) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(op, x); boolean hasSource = false; boolean success = true; - for (OperationOutcomeIssueComponent i : op.getIssue()) { - success = success && i.getSeverity() == IssueSeverity.INFORMATION; - hasSource = hasSource || ExtensionHelper.hasExtension(i, ToolingExtensions.EXT_ISSUE_SOURCE); + for (ResourceWrapper i : op.children("issue")) { + success = success && "information".equals(i.primitiveValue("severity")); + hasSource = hasSource || i.hasExtension(ToolingExtensions.EXT_ISSUE_SOURCE); } - if (success) - x.para().tx(context.formatPhrase(RenderingContext.OP_OUT_OK)); - if (op.getIssue().size() > 0) { + if (success) { + x.para().tx(context.formatPhrase(RenderingContext.OP_OUT_OK)); + } + if (op.has("issue")) { XhtmlNode tbl = x.table("grid"); // on the basis that we'll most likely be rendered using the standard fhir css, but it doesn't really matter XhtmlNode tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SEV)); @@ -50,33 +73,33 @@ public class OperationOutcomeRenderer extends ResourceRenderer { tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE)); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_DETAILS)); tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_DIAG)); - if (hasSource) - tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SRC)); - for (OperationOutcomeIssueComponent i : op.getIssue()) { + if (hasSource) { + tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SRC)); + } + for (ResourceWrapper i : op.children("issue")) { tr = tbl.tr(); - tr.td().addText(i.getSeverity().toString()); + tr.td().addText(getTranslatedCode(i.child("severity"))); XhtmlNode td = tr.td(); boolean d = false; - for (StringType s : i.hasExpression() ? i.getExpression() : i.getLocation()) { + for (ResourceWrapper s : i.has("expression") ? i.children("expression") : i.children("location")) { if (d) td.tx(", "); else d = true; - td.addText(s.getValue()); + td.addText(s.primitiveValue()); } - tr.td().addText(i.getCode().getDisplay()); - tr.td().addText(display(i.getDetails())); - smartAddText(tr.td(), i.getDiagnostics()); + tr.td().addText(getTranslatedCode(i.child("code"))); + tr.td().addText(i.child("details").primitiveValue("text")); + smartAddText(tr.td(), i.primitiveValue("diagnostics")); if (hasSource) { - Extension ext = ExtensionHelper.getExtension(i, ToolingExtensions.EXT_ISSUE_SOURCE); - tr.td().addText(ext == null ? "" : display(ext)); + ResourceWrapper ext = i.extension(ToolingExtensions.EXT_ISSUE_SOURCE); + tr.td().addText(ext == null || !ext.has("value") ? "" : displayDataType(ext.child("value"))); } } } - return true; - } - + + public void describe(XhtmlNode x, OperationOutcome oo) { x.tx(display(oo)); } @@ -85,16 +108,6 @@ public class OperationOutcomeRenderer extends ResourceRenderer { return (context.formatPhrase(RenderingContext.GENERAL_TODO)); } - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - return (context.formatPhrase(RenderingContext.GENERAL_TODO)); - } - - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return display((OperationOutcome) r); - } - public static String toString(OperationOutcome oo) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (OperationOutcomeIssueComponent issue : oo.getIssue()) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java index d72ef5065..402b7d9d8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java @@ -7,28 +7,32 @@ import java.util.List; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Parameters; -import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; -import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class ParametersRenderer extends ResourceRenderer { - - public ParametersRenderer(RenderingContext context) { - super(context); - } - public ParametersRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } + public ParametersRenderer(RenderingContext context) { + super(context); + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + List params = r.children("parameter"); + if (params.size() < 8) { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); + for (ResourceWrapper p : params) { + b.append(p.primitiveValue("name")); + } + return context.formatMessage(RenderingContext.PARS_SUMMARY_LIST, b.toString()); + } else { + return context.formatMessage(RenderingContext.PARS_SUMMARY_SIZE, params.size()); + } + } public ParametersRenderer setMultiLangMode(boolean multiLangMode) { this.multiLangMode = multiLangMode; @@ -36,100 +40,44 @@ public class ParametersRenderer extends ResourceRenderer { } @Override - public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(r, x); x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS)); XhtmlNode tbl = x.table("grid"); - params(tbl, ((Parameters) r).getParameter(), 0); - return false; + params(status, tbl, r.children("parameter"), 0); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return null; - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - return null; - } - - @Override - public boolean render(XhtmlNode x, ResourceWrapper params) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS)); - XhtmlNode tbl = x.table("grid"); - PropertyWrapper pw = getProperty(params, "parameter"); - if (valued(pw)) { - paramsW(tbl, pw.getValues(), 0); - } - return false; - } - - private void paramsW(XhtmlNode tbl, List list, int indent) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { - for (BaseWrapper p : list) { + private void params(RenderingStatus status, XhtmlNode tbl, List list, int indent) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { + for (ResourceWrapper p : list) { XhtmlNode tr = tbl.tr(); XhtmlNode td = tr.td(); for (int i = 0; i < indent; i++) { td.tx(XhtmlNode.NBSP); } if (p.has("name")) { - td.tx(p.get("name").primitiveValue()); + td.tx(p.primitiveValue("name")); } else { td.tx("???"); } if (p.has("value")) { - renderBase(tr.td(), p.get("value")); + renderDataType(status, tr.td(), p.child("value")); } else if (p.has("resource")) { - ResourceWrapper rw = p.getChildByName("resource").getAsResource(); + ResourceWrapper rw = p.child("resource"); td = tr.td(); XhtmlNode para = td.para(); para.tx(rw.fhirType()+"/"+rw.getId()); - para.an(rw.fhirType()+"_"+rw.getId()).tx(" "); - para.an("hc"+rw.fhirType()+"_"+rw.getId()).tx(" "); + para.an(context.prefixAnchor(rw.fhirType()+"_"+rw.getId())).tx(" "); + para.an(context.prefixAnchor("hc"+rw.fhirType()+"_"+rw.getId())).tx(" "); XhtmlNode x = rw.getNarrative(); if (x != null) { td.addChildren(x); } else { - ResourceRenderer rr = RendererFactory.factory(rw, context, rcontext); - rr.render(td, rw); + ResourceRenderer rr = RendererFactory.factory(rw, context); + rr.buildNarrative(status, td, rw); } } else if (p.has("part")) { tr.td(); - PropertyWrapper pw = getProperty(p, "part"); - paramsW(tbl, pw.getValues(), 1); - } - } - } - - public XhtmlNode render(Parameters params) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); - div.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS)); - XhtmlNode tbl = div.table("grid"); - params(tbl, params.getParameter(), 0); - return div; - } - - private void params(XhtmlNode tbl, List list, int indent) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { - for (ParametersParameterComponent p : list) { - XhtmlNode tr = tbl.tr(); - XhtmlNode td = tr.td(); - for (int i = 0; i < indent; i++) { - td.tx(XhtmlNode.NBSP); - } - td.tx(p.getName()); - if (p.hasValue()) { - render(tr.td(), p.getValue()); - } else if (p.hasResource()) { - Resource r = p.getResource(); - td = tr.td(); - XhtmlNode para = td.para(); - para.tx(r.fhirType()+"/"+r.getId()); - para.an(r.fhirType()+"_"+r.getId()).tx(" "); - para.an("hc"+r.fhirType()+"_"+r.getId()).tx(" "); - ResourceRenderer rr = RendererFactory.factory(r, context); - rr.render(td, r); - } else if (p.hasPart()) { - tr.td(); - params(tbl, p.getPart(), 1); + params(status, tbl, p.children("part"), indent+1); } } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java index 63723a81e..1a97548b0 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/PatientRenderer.java @@ -1,9 +1,9 @@ package org.hl7.fhir.r5.renderers; -import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; +import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -12,28 +12,10 @@ import java.util.UUID; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Address; import org.hl7.fhir.r5.model.Attachment; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.ContactPoint; -import org.hl7.fhir.r5.model.DataType; -import org.hl7.fhir.r5.model.DateType; -import org.hl7.fhir.r5.model.Enumeration; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.HumanName; -import org.hl7.fhir.r5.model.HumanName.NameUse; -import org.hl7.fhir.r5.model.Identifier; -import org.hl7.fhir.r5.model.Identifier.IdentifierUse; -import org.hl7.fhir.r5.model.Patient; -import org.hl7.fhir.r5.model.Period; -import org.hl7.fhir.r5.model.PrimitiveType; -import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; @@ -42,68 +24,165 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class PatientRenderer extends ResourceRenderer { - public class NamedReferance { - private String name; - private Reference reference; - private BaseWrapper wrapper; + public PatientRenderer(RenderingContext context) { + super(context); + } - public NamedReferance(String name, Reference ref, BaseWrapper refw) { - this.name = name; - this.reference = ref; - this.wrapper = refw; - } - public String getName() { - return name; - } - - public Reference getReference() { - return reference; - } - - public BaseWrapper getWrapper() { - return wrapper; - } - - } - - private static final int MAX_IMAGE_LENGTH = 2*1024*1024; - - public PatientRenderer(RenderingContext context) { - super(context); - } - - public boolean render(XhtmlNode x, Resource dr) throws UnsupportedEncodingException, IOException { - describe(x, dr); - return false; - } - - // name gender DoB (MRN) - public String display(Resource dr) { - Patient pat = (Patient) dr; - Identifier id = null; - for (Identifier t : pat.getIdentifier()) { + @Override + public String buildSummary(ResourceWrapper pat) throws UnsupportedEncodingException, IOException { + ResourceWrapper id = null; + List list = pat.children("identifier"); + for (ResourceWrapper t : list) { id = chooseId(id, t); } - HumanName n = null; - for (HumanName t : pat.getName()) { + list = pat.children("name"); + ResourceWrapper n = null; + for (ResourceWrapper t : list) { n = chooseName(n, t); } - return display(n, pat.hasGender() ? context.getTranslatedCode(pat.getGenderElement(), "http://hl7.org/fhir/administrative-gender") : null, pat.getBirthDateElement(), id); + String gender = null; + ResourceWrapper item = pat.child("gender"); + if (item != null) { + gender = context.getTranslatedCode(item.primitiveValue(), "http://hl7.org/fhir/administrative-gender"); + } + ResourceWrapper dt = pat.child("birthDate"); + + StringBuilder b = new StringBuilder(); + if (n != null) { + b.append(displayHumanName(n)); + } else { + b.append(context.formatPhrase(RenderingContext.PAT_NO_NAME)); + } + b.append(" "); + if (item == null) { + b.append(context.formatPhrase(RenderingContext.PAT_NO_GENDER)); + } else { + b.append(gender); + } + b.append(", "); + if (dt == null) { + b.append(context.formatPhrase(RenderingContext.PAT_NO_DOB)); + } else { + b.append(context.formatPhrase(RenderingContext.PAT_DOB, displayDateTime(dt))); + } + if (id != null) { + b.append(" ( "); + b.append(displayIdentifier(id)); + b.append(")"); + } + return b.toString(); } - private Identifier chooseId(Identifier oldId, Identifier newId) { + + // // name gender DoB (MRN) + // public String display(Resource dr) { + // Patient pat = (Patient) dr; + // Identifier id = null; + // for (Identifier t : pat.getIdentifier()) { + // id = chooseId(id, t); + // } + // HumanName n = null; + // for (HumanName t : pat.getName()) { + // n = chooseName(n, t); + // } + // return display(n, pat.hasGender() ? context.getTranslatedCode(pat.getGenderElement(), "http://hl7.org/fhir/administrative-gender") : null, pat.getBirthDateElement(), id); + // } + + + private static final int MAX_IMAGE_LENGTH = 2*1024*1024; + private static final boolean SHORT = false; + + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper pat) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(pat, x); + if (context.isShortPatientForm()) { + ResourceWrapper id = null; + List list = pat.children("identifier"); + for (ResourceWrapper t : list) { + id = chooseId(id, t); + } + list = pat.children("name"); + ResourceWrapper n = null; + for (ResourceWrapper t : list) { + n = chooseName(n, t); + } + String gender = null; + ResourceWrapper item = pat.child("gender"); + if (item != null) { + gender = getTranslatedCode(item); + } + ResourceWrapper dt = pat.child("birthDate"); + + if (n == null) { + x.b().tx(context.formatPhrase(RenderingContext.PAT_NO_NAME)); // todo: is this appropriate? + } else { + renderDataType(status, x.b(), n); + } + x.tx(" "); + if (gender == null) { + x.tx(context.formatPhrase(RenderingContext.PAT_NO_GENDER)); + } else { + x.tx(gender); + } + x.tx(", "); + if (dt == null) { + x.tx(context.formatPhrase(RenderingContext.PAT_NO_DOB)); + } else { + x.tx(context.formatPhrase(RenderingContext.PAT_DOB, displayDateTime(dt))); + } + if (id != null) { + x.tx(" ( "); + renderDataType(status, x, id); + x.tx(")"); + } + } else { + // banner + makeBanner(x.para()).tx(buildSummary(pat)); + x.hr(); + XhtmlNode tbl; + if (hasRenderablePhoto(pat)) { + tbl = x.table("none"); + XhtmlNode tr = tbl.tr(); + tbl = tr.td().table("grid"); + renderPhoto(tr.td(), pat); + } else { + tbl = x.table("grid"); + } + + // the table has 4 columns + addStatus(status, tbl, pat); + addIdentifiers(status, tbl, pat); + addNames(status, tbl, pat); + addComms(status, tbl, pat); + addLangs(status, tbl, pat); + addNOKs(status, tbl, pat); + addLinks(status, tbl, pat); + addExtensions(status, tbl, pat); + if (tbl.isEmpty()) { + x.remove(tbl); + } + if (pat.has("contained") && context.isTechnicalMode()) { + x.hr(); + x.para().b().tx(context.formatMessagePlural(pat.children("contained").size(), RenderingContext.PAT_CONTAINED)); + addContained(status, x, pat.children("contained")); + } + } + } + + private ResourceWrapper chooseId(ResourceWrapper oldId, ResourceWrapper newId) { if (oldId == null) { return newId; } if (newId == null) { return oldId; } - return isPreferred(newId.getUse(), oldId.getUse()) ? newId : oldId; + return isPreferredId(newId.primitiveValue("use"), oldId.primitiveValue("use")) ? newId : oldId; } - private boolean isPreferred(IdentifierUse newUse, IdentifierUse oldUse) { + private boolean isPreferredId(String newUse, String oldUse) { if (newUse == null && oldUse == null || newUse == oldUse) { return false; } @@ -111,37 +190,27 @@ public class PatientRenderer extends ResourceRenderer { return true; } switch (newUse) { - case NULL: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.USUAL); - case OFFICIAL: return !existsInList(oldUse, IdentifierUse.USUAL); - case OLD: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.SECONDARY, IdentifierUse.USUAL); - case SECONDARY: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.USUAL); - case TEMP: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.SECONDARY, IdentifierUse.USUAL); - case USUAL: return true; + case "official": return !Utilities.existsInList(oldUse, "usual"); + case "old": return !Utilities.existsInList(oldUse, "official", "secondary", "usual"); + case "secondary": return !Utilities.existsInList(oldUse, "official", "usual"); + case "temp": return !Utilities.existsInList(oldUse, "official", "secondary", "usual"); + case "usual": return true; default: return false; } } - private boolean existsInList(IdentifierUse oldUse, IdentifierUse... values) { - for (IdentifierUse value : values) { - if (value == oldUse) { - return true; - } - } - return false; - } - - private HumanName chooseName(HumanName oldName, HumanName newName) { + private ResourceWrapper chooseName(ResourceWrapper oldName, ResourceWrapper newName) { if (oldName == null) { return newName; } if (newName == null) { return oldName; } - return isPreferred(newName.getUse(), oldName.getUse()) ? newName : oldName; + return isPreferredName(newName.primitiveValue("use"), oldName.primitiveValue("use")) ? newName : oldName; } - private boolean isPreferred(NameUse newUse, NameUse oldUse) { + private boolean isPreferredName(String newUse, String oldUse) { if (newUse == null && oldUse == null || newUse == oldUse) { return false; } @@ -149,248 +218,99 @@ public class PatientRenderer extends ResourceRenderer { return true; } if (oldUse == null) { - return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); + return Utilities.existsInList(newUse, "official", "usual"); } switch (oldUse) { - case ANONYMOUS: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); - case MAIDEN: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); - case NICKNAME: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); - case NULL: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); - case OFFICIAL: return existsInList(newUse, NameUse.USUAL); - case OLD: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); - case TEMP: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL); - case USUAL: return false; + case "anonymous": return Utilities.existsInList(newUse, "official", "usual"); + case "maiden": return Utilities.existsInList(newUse, "official", "usual"); + case "nickname": return Utilities.existsInList(newUse, "official", "usual"); + case "official": return Utilities.existsInList(newUse, "usual"); + case "old": return Utilities.existsInList(newUse, "official", "usual"); + case "temp": return Utilities.existsInList(newUse, "official", "usual"); + case "usual": return false; } return false; } - private boolean existsInList(NameUse oldUse, NameUse... values) { - for (NameUse value : values) { - if (value == oldUse) { - return true; - } - } - return false; - } - @Override - public String display(ResourceWrapper pat) throws UnsupportedEncodingException, IOException { - Identifier id = null; - PropertyWrapper pw = getProperty(pat, "identifier"); - for (BaseWrapper t : pw.getValues()) { - id = chooseId(id, (Identifier) t.getBase()); - } - pw = getProperty(pat, "name"); - HumanName n = null; - for (BaseWrapper t : pw.getValues()) { - n = chooseName(n, (HumanName) t); - } - String gender = null; - pw = getProperty(pat, "gender"); - if (valued(pw)) { - gender = context.getTranslatedCode(pw.value().getBase(), "http://hl7.org/fhir/administrative-gender"); - } - DateType dt = null; - pw = getProperty(pat, "birthDate"); - if (valued(pw)) { - dt = (DateType) pw.value().getBase(); - } - return display(n, gender, dt, id); - } - - public void describe(XhtmlNode x, ResourceWrapper pat) throws UnsupportedEncodingException, IOException { - Identifier id = null; - PropertyWrapper pw = getProperty(pat, "identifier"); - for (BaseWrapper t : pw.getValues()) { - id = chooseId(id, (Identifier) t.getBase()); - } - pw = getProperty(pat, "name"); - HumanName n = null; - for (BaseWrapper t : pw.getValues()) { - n = chooseName(n, (HumanName) t.getBase()); - } - String gender = null; - pw = getProperty(pat, "gender"); - if (valued(pw)) { - gender = context.getTranslatedCode(pw.value().getBase(), "http://hl7.org/fhir/administrative-gender"); - } - DateType dt = null; - pw = getProperty(pat, "birthDate"); - if (valued(pw)) { - dt = (DateType) pw.value().getBase(); - } - describe(x, n, gender, dt, id); - } - - - private String display(HumanName name, String gender, DateType dob, Identifier id) { - StringBuilder b = new StringBuilder(); - if (name == null) { - b.append(display(name)); - } else { - b.append(context.formatPhrase(RenderingContext.PAT_NO_NAME)); - } - b.append(" "); - if (dob == null) { - b.append(context.formatPhrase(RenderingContext.PAT_NO_GENDER)); - } else { - b.append(gender); - } - b.append(", "); - if (dob == null) { - b.append(context.formatPhrase(RenderingContext.PAT_NO_DOB)); - } else { - b.append(context.formatPhrase(RenderingContext.PAT_DOB, display(dob))); - } - if (id != null) { - b.append(" ( "); - b.append(display(id)); - b.append(")"); - } - return b.toString(); - } - - public void describe(XhtmlNode x, HumanName name, String gender, DateType dob, Identifier id) throws UnsupportedEncodingException, IOException { - if (name == null) { - x.b().tx(context.formatPhrase(RenderingContext.PAT_NO_NAME)); // todo: is this appropriate? - } else { - render(x.b(), name); - } - x.tx(" "); - if (gender == null) { - x.tx(context.formatPhrase(RenderingContext.PAT_NO_GENDER)); - } else { - x.tx(gender); - } - x.tx(", "); - if (dob == null) { - x.tx(context.formatPhrase(RenderingContext.PAT_NO_DOB)); - } else { - x.tx(context.formatPhrase(RenderingContext.PAT_DOB, display(dob))); - } - if (id != null) { - x.tx(" ( "); - render(x, id); - x.tx(")"); - } - } - - @Override - public boolean render(XhtmlNode x, ResourceWrapper r) throws IOException, FHIRException, EOperationOutcome { - // banner - describe(makeBanner(x.para()), r); - x.hr(); - XhtmlNode tbl; - if (hasRenderablePhoto(r)) { - tbl = x.table("none"); - XhtmlNode tr = tbl.tr(); - tbl = tr.td().table("grid"); - renderPhoto(tr.td(), r); - } else { - tbl = x.table("grid"); - } - - // the table has 4 columns - addStatus(tbl, r); - addIdentifiers(tbl, r); - addNames(tbl, r); - addComms(tbl, r); - addLangs(tbl, r); - addNOKs(tbl, r); - addLinks(tbl, r); - addExtensions(tbl, r); - if (tbl.isEmpty()) { - x.remove(tbl); - } - if (r.has("contained") && context.isTechnicalMode()) { - x.hr(); - x.para().b().tx(context.formatMessagePlural(r.getContained().size(), RenderingContext.PAT_CONTAINED)); - addContained(x, r.getContained()); - } - return false; - } - - private void addContained(XhtmlNode x, List list) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { + private void addContained(RenderingStatus status, XhtmlNode x, List list) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { for (ResourceWrapper c : list) { x.hr(); - x.an(c.getId()); - new RendererFactory().factory(c, context).render(x, c); + x.an(context.prefixAnchor(c.getId())); + RendererFactory.factory(c, context.forContained()).buildNarrative(status, x, c); } } - private void addExtensions(XhtmlNode tbl, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException { - Map> extensions = new HashMap<>(); - PropertyWrapper pw = getProperty(r, "extension"); - for (BaseWrapper t : pw.getValues()) { - Extension ext = (Extension) t.getBase(); - if (!extensions.containsKey(ext.getUrl())) { - extensions.put(ext.getUrl(), new ArrayList<>()); + private void addExtensions(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException { + Map> extensions = new HashMap<>(); + List pw = r.children("extension"); + for (ResourceWrapper t : pw) { + String url = t.primitiveValue("url"); + if (!extensions.containsKey(url)) { + extensions.put(url, new ArrayList<>()); } - extensions.get(ext.getUrl()).add(ext); + extensions.get(url).add(t); } + for (String url : extensions.keySet()) { - StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, url); + StructureDefinition sd = findCanonical(StructureDefinition.class, url, r); if (sd != null) { - List list = extensions.get(url); + List list = extensions.get(url); boolean anyComplex = false; - for (Extension ext : list) { - anyComplex = anyComplex || ext.hasExtension(); + for (ResourceWrapper ext : list) { + anyComplex = anyComplex || ext.has("extension"); } if (!anyComplex) { XhtmlNode tr = tbl.tr(); nameCell(tr, getContext().getTranslated(sd.getTitleElement()), sd.getDescription(), sd.getWebPath()); XhtmlNode td = tr.td(); td.colspan("3"); - if (list.size() == 1) { + if (list.size() != 1) { XhtmlNode ul = td.ul(); - for (Extension s : list) { + for (ResourceWrapper s : list) { XhtmlNode li = ul.li(); - render(r, li, s.getValue()); + renderDataType(status, li, s.child("value")); } } else { - render(r, td, list.get(0).getValue()); + renderDataType(status, td, list.get(0).child("value")); } } else { - for (Extension ext : list) { + for (ResourceWrapper ext : list) { XhtmlNode tr = tbl.tr(); nameCell(tr, sd.getTitle()+":", sd.getDescription()); XhtmlNode td = tr.td(); td.colspan("3"); - if (ext.hasExtension()) { + if (ext.has("extension")) { XhtmlNode ul = td.ul(); - for (Extension s : ext.getExtension()) { + for (ResourceWrapper s : ext.extensions()) { XhtmlNode li = ul.li(); - li.tx(s.getUrl()+": "); - if (s.hasExtension()) { + li.tx(s.primitiveValue("url")+": "); + if (s.has("extension")) { boolean first = true; - for (Extension t : s.getExtension()) { + for (ResourceWrapper t : s.extensions()) { if (first) first = false; else li.tx("; "); - li.tx(t.getUrl()+"="); - render(r, li, t.getValue()); + li.tx(t.primitiveValue("url")+"="); + renderDataType(status, li, t.child("value")); } } else { - render(r, li, s.getValue()); + renderDataType(status, li, s.child("value")); } } } else { - render(r, td, ext.getValue()); + renderDataType(status, td, ext.child("value")); } } } } } - - + + } - private void addIdentifiers(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { - List ids = new ArrayList<>(); - PropertyWrapper pw = getProperty(r, "identifier"); - for (BaseWrapper t : pw.getValues()) { - ids.add((Identifier) t.getBase()); - } - Identifier id = null; - for (Identifier i : ids) { + private void addIdentifiers(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { + List ids = r.children("identifier"); + ResourceWrapper id = null; + for (ResourceWrapper i : ids) { id = chooseId(id, i); } if (id != null) { @@ -402,27 +322,26 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode td = tr.td(); td.colspan("3"); if (ids.size() == 1) { - render(r, td, ids.get(0)); + renderDataType(status, td, ids.get(0)); } else { XhtmlNode ul = td.ul(); - for (Identifier i : ids) { - render(r, ul.li(), i); + for (ResourceWrapper i : ids) { + renderDataType(status, ul.li(), i); } } } } - private void addLangs(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { - List langs = new ArrayList<>(); - PropertyWrapper pw = getProperty(r, "communication"); - CodeableConcept prefLang = null; - for (BaseWrapper t : pw.getValues()) { - PropertyWrapper l = getProperty(t, "language"); - if (l != null && l.hasValues()) { - CodeableConcept lang = (CodeableConcept) l.getValues().get(0).getBase(); + private void addLangs(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { + List langs = new ArrayList(); + List comms = r.children("communication"); + ResourceWrapper prefLang = null; + for (ResourceWrapper t : comms) { + ResourceWrapper lang = t.child("language"); + if (lang != null) { langs.add(lang); - l = getProperty(t, "preferred"); - if (l != null && l.hasValues() && "true".equals(l.getValues().get(0).getBase().primitiveValue())) { + ResourceWrapper l = t.child("preferred"); + if (l != null && "true".equals(l.primitiveValue())) { prefLang = lang; } } @@ -433,15 +352,15 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode td = tr.td(); td.colspan("3"); if (langs.size() == 1) { - render(r, td, langs.get(0)); + renderDataType(status, td, langs.get(0)); if (prefLang != null) { td.tx(" "+context.formatPhrase(RenderingContext.PAT_LANG_PREFERRED)); } } else if (langs.size() > 1) { XhtmlNode ul = td.ul(); - for (CodeableConcept i : langs) { + for (ResourceWrapper i : langs) { XhtmlNode li = ul.li(); - render(r, li, i); + renderDataType(status, li, i); if (i == prefLang) { li.tx(" "+context.formatPhrase(RenderingContext.PAT_LANG_PREFERRED));; } @@ -450,39 +369,48 @@ public class PatientRenderer extends ResourceRenderer { } } - private void addLinks(XhtmlNode tbl, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException { + + + public class NamedReferance { + + private String name; + private ResourceWrapper reference; + + public NamedReferance(String name, ResourceWrapper ref) { + this.name = name; + this.reference = ref; + } + + public String getName() { + return name; + } + + public ResourceWrapper getReference() { + return reference; + } + + } + + + private void addLinks(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException { List refs = new ArrayList<>(); - PropertyWrapper pw = getProperty(r, "generalPractitioner"); - if (pw != null) { - for (BaseWrapper t : pw.getValues()) { - refs.add(new NamedReferance(context.formatPhrase(RenderingContext.PAT_GP), (Reference) t.getBase(), t)); + List pw = r.children("generalPractitioner"); + for (ResourceWrapper t : pw) { + refs.add(new NamedReferance(context.formatPhrase(RenderingContext.PAT_GP), t)); + } + pw = r.children("managingOrganization"); + for (ResourceWrapper t : pw) { + refs.add(new NamedReferance(context.formatPhrase(RenderingContext.PAT_MO), t)); + } + pw = r.children("link"); + for (ResourceWrapper t : pw) { + ResourceWrapper o = t.firstChild("other"); + ResourceWrapper l = t.firstChild("type"); + if (l != null && o != null) { + refs.add(new NamedReferance(describeLinkedRecord(l.primitiveValue()), o)); } } - pw = getProperty(r, "managingOrganization"); - if (pw != null) { - for (BaseWrapper t : pw.getValues()) { - refs.add(new NamedReferance(context.formatPhrase(RenderingContext.PAT_MO), (Reference) t.getBase(), t)); - } - } - pw = getProperty(r, "link"); - for (BaseWrapper t : pw.getValues()) { - PropertyWrapper l = getProperty(t, "other"); - Reference ref = null; - BaseWrapper refw = null; - for (BaseWrapper v : l.getValues()) { - ref = (Reference) v.getBase(); - refw = v; - } - String type = null; - l = getProperty(t, "type"); - for (BaseWrapper v : l.getValues()) { - type = v.getBase().primitiveValue(); - } - if (type != null && ref != null) { - refs.add(new NamedReferance(describeLinkedRecord(type), ref, refw)); - } - } - + if (refs.size() > 0) { XhtmlNode tr = tbl.tr(); nameCell(tr, context.formatPhrase(RenderingContext.PAT_LINKS), context.formatPhrase(RenderingContext.PAT_LINKS_HINT)); @@ -493,7 +421,7 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode li = ul.li(); li.tx(ref.getName()); li.tx(": "); - renderReference(r, li, ref.getReference()); + renderReference(status, li, ref.getReference()); } } } @@ -508,64 +436,27 @@ public class PatientRenderer extends ResourceRenderer { return "Unknown"; } - private void addNOKs(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { - PropertyWrapper pw = getProperty(r, "contact"); - for (BaseWrapper t : pw.getValues()) { - addNOK(tbl,r, t); + private void addNOKs(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { + for (ResourceWrapper t : r.children("contact")) { + addNOK(status, tbl, r, t); } } - - private void addNOK(XhtmlNode tbl, ResourceWrapper r, BaseWrapper bw) throws FHIRFormatError, DefinitionException, IOException { - List rels = new ArrayList<>(); - HumanName name = null; - Address add = null; - String gender = null; - Period period = null; - Reference organization = null; - List tels = new ArrayList<>(); - PropertyWrapper pw = getProperty(bw, "relationship"); - for (BaseWrapper t : pw.getValues()) { - CodeableConcept v = (CodeableConcept) t.getBase(); - rels.add(v); - } - - pw = getProperty(bw, "name"); - if (pw.hasValues()) { - name = (HumanName) pw.getValues().get(0).getBase(); - } - pw = getProperty(bw, "telecom"); - for (BaseWrapper t : pw.getValues()) { - ContactPoint v = (ContactPoint) t.getBase(); - tels.add(v); - } - - pw = getProperty(bw, "address"); - if (pw.hasValues()) { - add = (Address) pw.getValues().get(0).getBase(); - } - - pw = getProperty(bw, "gender"); - if (pw.hasValues()) { - gender = context.getTranslatedCode(pw.getValues().get(0).getBase(), "http://hl7.org/fhir/administrative-gender"); - } + private void addNOK(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r, ResourceWrapper bw) throws FHIRFormatError, DefinitionException, IOException { + List rels = bw.children("relationship"); + ResourceWrapper name = bw.firstChild("name"); + ResourceWrapper add = bw.firstChild("address"); + String gender = context.getTranslatedCode(bw.primitiveValue("gender"), "http://hl7.org/fhir/administrative-gender"); + ResourceWrapper period = bw.firstChild("period"); + ResourceWrapper organization = bw.firstChild("organization"); + List tels = bw.children("telecom"); - pw = getProperty(bw, "organization"); - if (pw.hasValues()) { - organization = (Reference) pw.getValues().get(0).getBase(); - } - - pw = getProperty(bw, "period"); - if (pw.hasValues()) { - period = (Period) pw.getValues().get(0).getBase(); - } - if (rels.size() < 2 && name == null && add == null && gender == null && period == null && organization == null && tels.size() == 0) { return; // nothing to render } XhtmlNode tr = tbl.tr(); if (rels.size() == 1) { - nameCell(tr, (rels.get(0).getCodingFirstRep().hasDisplay() ? rels.get(0).getCodingFirstRep().getDisplay() : display(rels.get(0)))+":", context.formatPhrase(RenderingContext.PAT_NOM_CONTACT)+" "+display(rels.get(0))); + nameCell(tr, displayDataType(rels.get(0))+":", context.formatPhrase(RenderingContext.PAT_NOM_CONTACT)+" "+displayDataType(rels.get(0))); } else { nameCell(tr, context.formatPhrase(RenderingContext.GENERAL_CONTACT), context.formatPhrase(RenderingContext.PAT_NOK_CONTACT_HINT)); } @@ -575,7 +466,7 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode li; if (name != null) { li = ul.li(); - render(r, li, name); + renderDataType(status, li, name); if (gender != null) { li.tx(" "+"("+gender+")"); } @@ -587,37 +478,33 @@ public class PatientRenderer extends ResourceRenderer { li = ul.li(); li.tx(context.formatPhrase(RenderingContext.PAT_RELN)); boolean first = true; - for (CodeableConcept rel : rels) { + for (ResourceWrapper rel : rels) { if (first) first = false; else li.tx(", "); - render(r, li, rel); + renderDataType(status, li, rel); } } if (add != null) { - render(r, ul.li(), add); + renderDataType(status, ul.li(), add); } - for (ContactPoint cp : tels) { - render(r, ul.li(), cp); + for (ResourceWrapper cp : tels) { + renderDataType(status, ul.li(), cp); } if (organization != null) { li = ul.li(); li.tx(context.formatPhrase(RenderingContext.PAT_ORG)); - render(r, li, organization); + renderDataType(status, li, organization); } if (period != null) { li = ul.li(); li.tx(context.formatPhrase(RenderingContext.PAT_PERIOD)); - render(r, li, period); + renderDataType(status, li, period); } } - private void addNames(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { - List names = new ArrayList<>(); - PropertyWrapper pw = getProperty(r, "name"); - for (BaseWrapper t : pw.getValues()) { - names.add((HumanName) t.getBase()); - } - HumanName name = null; - for (HumanName n : names) { + private void addNames(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { + List names = r.children("name"); + ResourceWrapper name = null; + for (ResourceWrapper n : names) { name = chooseName(name, n); } if (name != null) { @@ -629,27 +516,19 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode td = tr.td(); td.colspan("3"); if (names.size() == 1) { - render(r, td, names.get(0)); + renderDataType(status, td, names.get(0)); } else { XhtmlNode ul = td.ul(); - for (HumanName n : names) { - render(r, ul.li(), n); + for (ResourceWrapper n : names) { + renderDataType(status, ul.li(), n); } } } } - - private void addComms(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { - List tels = new ArrayList<>(); - PropertyWrapper pw = getProperty(r, "telecom"); - for (BaseWrapper t : pw.getValues()) { - tels.add((ContactPoint) t.getBase()); - } - List
adds = new ArrayList<>(); - pw = getProperty(r, "address"); - for (BaseWrapper t : pw.getValues()) { - adds.add((Address) t.getBase()); - } + + private void addComms(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { + List tels = r.children("telecom"); + List adds = r.children("address"); if (tels.size() + adds.size() > 0) { XhtmlNode tr = tbl.tr(); nameCell(tr, context.formatPhrase(RenderingContext.PAT_CONTACT), context.formatPhrase(RenderingContext.PAT_CONTACT_HINT)); @@ -657,23 +536,23 @@ public class PatientRenderer extends ResourceRenderer { td.colspan("3"); if (tels.size() + adds.size() == 1) { if (adds.isEmpty()) { - render(r, td, tels.get(0)); + renderDataType(status, td, tels.get(0)); } else { - render(r, td, adds.get(0)); + renderDataType(status, td, adds.get(0)); } } else { XhtmlNode ul = td.ul(); - for (ContactPoint n : tels) { - render(r, ul.li(), n); + for (ResourceWrapper n : tels) { + renderDataType(status, ul.li(), n); } - for (Address n : adds) { - render(r, ul.li(), n); + for (ResourceWrapper n : adds) { + renderDataType(status, ul.li(), n); } } } } - - private void addStatus(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, UnsupportedEncodingException, FHIRException, IOException { + + private void addStatus(RenderingStatus status, XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, UnsupportedEncodingException, FHIRException, IOException { // TODO Auto-generated method stub int count = 0; if (r.has("active")) { @@ -692,32 +571,32 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode tr = tbl.tr(); int pos = 0; if (r.has("active")) { - PropertyWrapper a = r.getChildByName("active"); - if (a.hasValues()) { + List a = r.children("active"); + if (!a.isEmpty()) { pos++; nameCell(tr, context.formatPhrase(RenderingContext.PAT_ACTIVE), context.formatPhrase(RenderingContext.PAT_ACTIVE_HINT)); XhtmlNode td = tr.td(); if (pos == count) { td.colspan("3"); } - render(r, td, (DataType) a.value().getBase()); + renderDataType(status, td, a.get(0)); } } if (r.has("deceased[x]")) { - PropertyWrapper a = r.getChildByName("deceased[x]"); - if (a.hasValues()) { + List a = r.children("deceased[x]"); + if (!a.isEmpty()) { pos++; nameCell(tr, context.formatPhrase(RenderingContext.PAT_DECEASED), context.formatPhrase(RenderingContext.PAT_DECEASED_HINT)); XhtmlNode td = tr.td(); if (pos == count) { td.colspan("3"); } - render(r, td, (DataType) a.value().getBase()); + renderDataType(status, td, a.get(0)); } } if (r.has("maritalStatus")) { - PropertyWrapper a = r.getChildByName("maritalStatus"); - if (a.hasValues()) { + List a = r.children("maritalStatus"); + if (!a.isEmpty()) { pos++; if (pos == 3) { tr = tbl.tr(); @@ -727,12 +606,12 @@ public class PatientRenderer extends ResourceRenderer { if (pos == count) { td.colspan("3"); } - render(r, td, (DataType) a.value().getBase()); + renderDataType(status, td, a.get(0)); } } if (r.has("multipleBirth[x]")) { - PropertyWrapper a = r.getChildByName("multipleBirth[x]"); - if (a.hasValues()) { + List a = r.children("multipleBirth[x]"); + if (!a.isEmpty()) { pos++; if (pos == 3) { tr = tbl.tr(); @@ -742,7 +621,7 @@ public class PatientRenderer extends ResourceRenderer { if (pos == count) { td.colspan("3"); } - render(r, td, (DataType) a.value().getBase()); + renderDataType(status, td, a.get(0)); } } } @@ -759,7 +638,7 @@ public class PatientRenderer extends ResourceRenderer { XhtmlNode td = tr.td(); td.setAttribute("title", title); if (link != null) { - td.ah(link).tx(text); + td.ah(context.prefixLocalHref(link)).tx(text); } else { td.tx(text); } @@ -768,17 +647,18 @@ public class PatientRenderer extends ResourceRenderer { private void renderPhoto(XhtmlNode td, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException { if (r.has("photo")) { - PropertyWrapper a = r.getChildByName("photo"); - for (BaseWrapper v : a.getValues()) { - Attachment att = (Attachment) v.getBase(); - if (att.getContentType().startsWith("image/") && - att.getData() != null && (!context.isInlineGraphics() || (att.getData().length > 0 && att.getData().length < MAX_IMAGE_LENGTH))) { - String ext = extensionForType(att.getContentType()); + List a = r.children("photo"); + for (ResourceWrapper att : a) { + String ct = att.primitiveValue("contentType"); + byte[] cnt = att.has("data") ? Base64.getDecoder().decode(att.primitiveValue("data")) : null; + if (ct.startsWith("image/") && + cnt != null && (!context.isInlineGraphics() || (cnt.length > 0 && cnt.length < MAX_IMAGE_LENGTH))) { + String ext = extensionForType(ct); if (context.isInlineGraphics() || Utilities.noString(context.getDestDir()) || ext == null) { - td.img("data:"+att.getContentType()+";base64,"+att.getDataElement().asStringValue(), "patient photo"); + td.img("data:"+ct+";base64,"+att.primitiveValue("data"), "patient photo"); } else { String n = UUID.randomUUID().toString().toLowerCase()+ext; - TextFile.bytesToFile(att.getData(), ManagedFileAccess.file(Utilities.path(context.getDestDir(), n))); + TextFile.bytesToFile(cnt, ManagedFileAccess.file(Utilities.path(context.getDestDir(), n))); context.registerFile(n); td.img(n, context.formatPhrase(RenderingContext.PAT_PHOTO)); } @@ -804,8 +684,8 @@ public class PatientRenderer extends ResourceRenderer { private boolean hasRenderablePhoto(ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException { if (r.has("photo")) { - PropertyWrapper a = r.getChildByName("photo"); - for (BaseWrapper v : a.getValues()) { + List a = r.children("photo"); + for (ResourceWrapper v : a) { Attachment att = (Attachment) v.getBase(); if (att.hasContentType() && att.getContentType().startsWith("image/") && att.getData() != null && (!context.isInlineGraphics() || (att.getData().length > 0 && att.getData().length < MAX_IMAGE_LENGTH))) { 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 a17642743..ffb56e8a9 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 @@ -9,77 +9,25 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.NotImplementedException; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; +import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.SourcedChildDefinitions; import org.hl7.fhir.r5.context.ContextUtilities; -import org.hl7.fhir.r5.model.Address; -import org.hl7.fhir.r5.model.Annotation; -import org.hl7.fhir.r5.model.Attachment; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.Base64BinaryType; -import org.hl7.fhir.r5.model.BooleanType; -import org.hl7.fhir.r5.model.CodeType; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.CodeableReference; -import org.hl7.fhir.r5.model.Coding; -import org.hl7.fhir.r5.model.ContactDetail; -import org.hl7.fhir.r5.model.ContactPoint; -import org.hl7.fhir.r5.model.DataRequirement; -import org.hl7.fhir.r5.model.DataType; -import org.hl7.fhir.r5.model.DateTimeType; -import org.hl7.fhir.r5.model.DomainResource; -import org.hl7.fhir.r5.model.Dosage; import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.Enumeration; -import org.hl7.fhir.r5.model.Expression; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.HumanName; -import org.hl7.fhir.r5.model.IdType; -import org.hl7.fhir.r5.model.Identifier; -import org.hl7.fhir.r5.model.InstantType; -import org.hl7.fhir.r5.model.Meta; -import org.hl7.fhir.r5.model.Money; -import org.hl7.fhir.r5.model.Narrative; -import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; -import org.hl7.fhir.r5.model.Period; -import org.hl7.fhir.r5.model.PrimitiveType; -import org.hl7.fhir.r5.model.ProductShelfLife; -import org.hl7.fhir.r5.model.Property; -import org.hl7.fhir.r5.model.Quantity; -import org.hl7.fhir.r5.model.Range; -import org.hl7.fhir.r5.model.Ratio; -import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.RelatedArtifact; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.SampledData; -import org.hl7.fhir.r5.model.Signature; -import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; -import org.hl7.fhir.r5.model.Timing; -import org.hl7.fhir.r5.model.TriggerDefinition; -import org.hl7.fhir.r5.model.UriType; -import org.hl7.fhir.r5.model.UsageContext; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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; -import org.hl7.fhir.r5.renderers.utils.DirectWrappers.BaseWrapperDirect; -import org.hl7.fhir.r5.renderers.utils.DirectWrappers.PropertyWrapperDirect; -import org.hl7.fhir.r5.renderers.utils.DirectWrappers.ResourceWrapperDirect; -import org.hl7.fhir.r5.renderers.utils.ElementWrappers; 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; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper.NamedResourceWrapperList; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.DebugUtilities; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; @@ -87,253 +35,108 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class ProfileDrivenRenderer extends ResourceRenderer { private Set containedIds = new HashSet<>(); - private boolean hasExtensions; - public ProfileDrivenRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - public ProfileDrivenRenderer(RenderingContext context) { super(context); } @Override - public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException { - return render(x, new DirectWrappers.ResourceWrapperDirect(context, r)); - } - - @Override - public boolean render(XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { - boolean idDone = false; - XhtmlNode p = x.para(); - if (context.isAddGeneratedNarrativeHeader()) { - p.b().tx(context.formatPhrase(RenderingContext.PROF_DRIV_GEN_NARR, r.fhirType(), (context.isContained() ? " #"+r.getId() : ""))); - if (!Utilities.noString(r.getId())) { - p.an(r.getId()); - p.an("hc"+r.getId()); - } - idDone = true; - } - if (context.isTechnicalMode() && !context.isContained()) { - renderResourceHeader(r, x, !idDone); - idDone = true; - } - if (!Utilities.noString(r.getId()) && !idDone) { - x.para().an(r.getId()); - x.para().an("hc"+r.getId()); - } + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException { + renderResourceTechDetails(r, x); try { - StructureDefinition sd = r.getDefinition(); + StructureDefinition sd = context.getContext().fetchTypeDefinition(r.fhirType()); if (sd == null) { throw new FHIRException(context.formatPhrase(RenderingContext.PROF_DRIV_FEXCP, r.fhirType())+" "); } else { ElementDefinition ed = sd.getSnapshot().getElement().get(0); containedIds.clear(); - hasExtensions = false; - generateByProfile(r, sd, r.root(), sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), context.isTechnicalMode(), 0); + generateByProfile(status, r, sd, r, sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), context.isTechnicalMode(), 0); } } catch (Exception e) { System.out.println(context.formatPhrase(RenderingContext.PROF_DRIV_ERR_GEN_NARR) +r.fhirType()+"/"+r.getId()+": "+e.getMessage()); e.printStackTrace(); x.para().b().style("color: maroon").tx(context.formatPhrase(RenderingContext.PROF_DRIV_EXCP, e.getMessage())+" "); } - return hasExtensions; } - - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return "todo"; - } @Override - public String display(ResourceWrapper res) throws UnsupportedEncodingException, IOException { + public String buildSummary(ResourceWrapper res) throws UnsupportedEncodingException, IOException { StructureDefinition profile = getContext().getWorker().fetchTypeDefinition(res.fhirType()); if (profile == null) return "unknown resource type " +res.fhirType(); else { boolean firstElement = true; boolean last = false; - List children = res.children(); - ContextUtilities cu = new ContextUtilities(context.getWorker()); - for (PropertyWrapper p : children) { - if (p.getName().equals("title") && cu.isDatatype(p.fhirType()) && p.hasValues()) { - return res.fhirType()+" "+ display((DataType) p.getValues().get(0).getBase()); + List children = res.children(); + ContextUtilities cu = res.getContextUtilities(); + for (ResourceWrapper p : children) { + if (p.name().equals("title") && cu.isDatatype(p.fhirType()) && !p.isEmpty()) { + return res.fhirType()+" "+ displayDataType(p); } } - for (PropertyWrapper p : children) { - if (p.getName().equals("name") && cu.isDatatype(p.fhirType()) && p.hasValues()) { - CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - for (BaseWrapper v : p.getValues()) { - b.append((display((DataType) v.getBase()))); - } - return res.fhirType()+" "+ b.toString(); + for (ResourceWrapper p : children) { + if (p.name().equals("name") && cu.isDatatype(p.fhirType()) && !p.isEmpty()) { + return res.fhirType()+" "+ displayDataType(p); } } - for (PropertyWrapper p : children) { - if (p.getName().equals("code") && cu.isDatatype(p.fhirType()) && p.hasValues()) { - CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); - for (BaseWrapper v : p.getValues()) { - b.append((display((DataType) v.getBase()))); - } - return res.fhirType()+" "+ b.toString(); + for (ResourceWrapper p : children) { + if (p.name().equals("code") && cu.isDatatype(p.fhirType()) && !p.isEmpty()) { + return res.fhirType()+" "+ displayDataType(p); } } - for (PropertyWrapper p : children) { - StringBuilder b = new StringBuilder(); - if (!ignoreProperty(p) && !p.getElementDefinition().getBase().getPath().startsWith("Resource.")) { - ElementDefinition child = getElementDefinition(profile.getSnapshot().getElement(), res.fhirType()+"."+p.getName(), p); - if (p.getValues().size() > 0 && p.getValues().get(0) != null && child != null && isSimple(child) && includeInSummary(child, p.getValues())) { - if (firstElement) - firstElement = false; - else if (last) - b.append("; "); - boolean first = true; - last = false; - for (BaseWrapper v : p.getValues()) { - if (first) - first = false; - else if (last) - b.append(", "); - b.append((display((DataType) v.getBase()))); - } - } - } - return res.fhirType()+" "+ b.toString(); + switch (res.fhirType()) { + case "Binary" : return res.fhirType()+": "+ res.primitiveValue("data").length()+" chars (base64)"; } - return res.fhirType()+" ???"; + return generateResourceSummary(res, profile, profile.getSnapshot().getElementFirstRep(), false, false); } } -// -// public void inject(Element er, XhtmlNode x, NarrativeStatus status, boolean pretty) { -// if (!x.hasAttribute("xmlns")) -// x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); -// Element le = XMLUtil.getNamedChild(er, "language"); -// String l = le == null ? null : le.getAttribute("value"); -// if (!Utilities.noString(l)) { -// // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues -// x.setAttribute("lang", l); -// x.setAttribute("xml:lang", l); -// } -// Element txt = XMLUtil.getNamedChild(er, "text"); -// if (txt == null) { -// txt = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "text"); -// Element n = XMLUtil.getFirstChild(er); -// while (n != null && (n.getNodeName().equals("id") || n.getNodeName().equals("meta") || n.getNodeName().equals("implicitRules") || n.getNodeName().equals("language"))) -// n = XMLUtil.getNextSibling(n); -// if (n == null) -// er.appendChild(txt); -// else -// er.insertBefore(txt, n); -// } -// Element st = XMLUtil.getNamedChild(txt, "status"); -// if (st == null) { -// st = er.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "status"); -// Element n = XMLUtil.getFirstChild(txt); -// if (n == null) -// txt.appendChild(st); -// else -// txt.insertBefore(st, n); -// } -// st.setAttribute("value", status.toCode()); -// Element div = XMLUtil.getNamedChild(txt, "div"); -// if (div == null) { -// div = er.getOwnerDocument().createElementNS(FormatUtilities.XHTML_NS, "div"); -// div.setAttribute("xmlns", FormatUtilities.XHTML_NS); -// txt.appendChild(div); -// } -// if (div.hasChildNodes()) -// div.appendChild(er.getOwnerDocument().createElementNS(FormatUtilities.XHTML_NS, "hr")); -// new XhtmlComposer(XhtmlComposer.XML, pretty).compose(div, x); -// } -// -// public void inject(org.hl7.fhir.r5.elementmodel.Element er, XhtmlNode x, NarrativeStatus status, boolean pretty) throws IOException, FHIRException { -// if (!x.hasAttribute("xmlns")) -// x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); -// String l = er.getChildValue("language"); -// if (!Utilities.noString(l)) { -// // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues -// x.setAttribute("lang", l); -// x.setAttribute("xml:lang", l); -// } -// org.hl7.fhir.r5.elementmodel.Element txt = er.getNamedChild("text"); -// if (txt == null) { -// txt = new org.hl7.fhir.r5.elementmodel.Element("text", er.getProperty().getChild(null, "text")); -// int i = 0; -// while (i < er.getChildren().size() && (er.getChildren().get(i).getName().equals("id") || er.getChildren().get(i).getName().equals("meta") || er.getChildren().get(i).getName().equals("implicitRules") || er.getChildren().get(i).getName().equals("language"))) -// i++; -// if (i >= er.getChildren().size()) -// er.getChildren().add(txt); -// else -// er.getChildren().add(i, txt); -// } -// org.hl7.fhir.r5.elementmodel.Element st = txt.getNamedChild("status"); -// if (st == null) { -// st = new org.hl7.fhir.r5.elementmodel.Element("status", txt.getProperty().getChild(null, "status")); -// txt.getChildren().add(0, st); -// } -// st.setValue(status.toCode()); -// org.hl7.fhir.r5.elementmodel.Element div = txt.getNamedChild("div"); -// if (div == null) { -// div = new org.hl7.fhir.r5.elementmodel.Element("div", txt.getProperty().getChild(null, "div")); -// txt.getChildren().add(div); -// div.setValue(new XhtmlComposer(XhtmlComposer.XML, pretty).compose(x)); -// } -// div.setValue(x.toString()); -// div.setXhtml(x); -// } -// - - - public void generateResourceSummary(XhtmlNode x, ResourceWrapper res, boolean textAlready, boolean showCodeDetails, boolean canLink) throws FHIRException, UnsupportedEncodingException, IOException { - if (!textAlready) { - XhtmlNode div = res.getNarrative(); - if (div != null) { - if (div.allChildrenAreText()) - x.getChildNodes().addAll(div.getChildNodes()); - if (div.getChildNodes().size() == 1 && div.getChildNodes().get(0).allChildrenAreText()) - x.getChildNodes().addAll(div.getChildNodes().get(0).getChildNodes()); - } - x.tx("Generated Summary: "); - } - String path = res.fhirType(); - StructureDefinition profile = getContext().getWorker().fetchResource(StructureDefinition.class, path); - if (profile == null) - x.tx("unknown resource " +path); + public String generateResourceSummary(ResourceWrapper res, StructureDefinition sd, ElementDefinition ed, boolean showCodeDetails, boolean canLink) throws FHIRException, UnsupportedEncodingException, IOException { + if (sd == null) + return "unknown resource " +res.fhirType(); else { - boolean firstElement = true; - boolean last = false; - for (PropertyWrapper p : res.children()) { - if (!ignoreProperty(p) && !p.getElementDefinition().getBase().getPath().startsWith("Resource.")) { - ElementDefinition child = getElementDefinition(profile.getSnapshot().getElement(), path+"."+p.getName(), p); - if (p.getValues().size() > 0 && p.getValues().get(0) != null && child != null && isSimple(child) && includeInSummary(child, p.getValues())) { - if (firstElement) - firstElement = false; - else if (last) - x.tx("; "); - boolean first = true; - last = false; - for (BaseWrapper v : p.getValues()) { - if (first) - first = false; - else if (last) - x.tx(", "); - last = displayLeaf(res, v, child, x, p.getName(), showCodeDetails, canLink) || last; + SourcedChildDefinitions childDefs = context.getProfileUtilities().getChildMap(sd, ed); + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("; "); + for (NamedResourceWrapperList p : res.childrenInGroups()) { + ElementDefinition pDefn = getElementDefinition(childDefs, p); + if (pDefn != null && !ignoreProperty(p) && !pDefn.getBase().getPath().startsWith("Resource.")) { + if (p.getValues().size() > 0 && p.getValues().get(0) != null && pDefn != null && isSimple(pDefn) && includeInSummary(pDefn, p)) { + CommaSeparatedStringBuilder b2 = new CommaSeparatedStringBuilder(","); + for (ResourceWrapper v : p.getValues()) { + b2.append(displayDataType(v)); } + b.append(formatPhrase(RenderingContext.PROF_DRIV_SUMM_PROP, labelForElement(pDefn), b2.toString())); } } } + if (b.length() == 0) { + return formatPhrase(RenderingContext.PROF_DRIV_SUMM_NONE, res.fhirType()); + } else { + return formatPhrase(RenderingContext.PROF_DRIV_SUMM, res.fhirType(), b.toString()); + } } } + + private String labelForElement(ElementDefinition pDefn) { + return pDefn.getName(); + } + private ElementDefinition getElementDefinition(SourcedChildDefinitions childDefs, NamedResourceWrapperList p) { + for (ElementDefinition ed : childDefs.getList()) { + if (ed.getName().equals(p.getName())) { + return ed; + } + } + return null; + } - private boolean ignoreProperty(PropertyWrapper p) { + private boolean ignoreProperty(NamedResourceWrapperList p) { return Utilities.existsInList(p.getName(), "contained"); } - private boolean includeInSummary(ElementDefinition child, List list) throws UnsupportedEncodingException, FHIRException, IOException { - if (child.getName().endsWith("active") && list != null && list.size() > 0 && "true".equals(list.get(0).getBase().primitiveValue())) { + private boolean includeInSummary(ElementDefinition child, NamedResourceWrapperList list) throws UnsupportedEncodingException, FHIRException, IOException { + if (child.getName().endsWith("active") && list != null && list.getValues().size() > 0 && "true".equals(list.getValues().get(0).primitiveValue())) { return false; } if (child.getIsModifier()) @@ -348,361 +151,56 @@ public class ProfileDrivenRenderer extends ResourceRenderer { return true; } - private ElementDefinition getElementDefinition(List elements, String path, PropertyWrapper p) { + private ElementDefinition getElementDefinition(List elements, String path) { for (ElementDefinition element : elements) if (element.getPath().equals(path)) return element; - if (path.endsWith("\"]") && p.getStructure() != null) - return p.getStructure().getSnapshot().getElement().get(0); return null; } - private void renderLeaf(ResourceWrapper res, BaseWrapper ew, ElementDefinition defn, XhtmlNode parent, XhtmlNode x, boolean title, boolean showCodeDetails, Map displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { + private void renderLeaf(RenderingStatus status, ResourceWrapper res, ResourceWrapper ew, ElementDefinition defn, XhtmlNode parent, XhtmlNode x, boolean title, boolean showCodeDetails, Map displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { if (ew == null) return; - Base e = ew.getBase(); - if (e == null) { - return; - } if (context.isShowComments()) { - x = renderCommentsSpan(x, e); + x = renderCommentsSpan(x, ew); } - - if (e instanceof PrimitiveType) { - PrimitiveType p = (PrimitiveType) e; - if (!p.hasValue()) { - if (p.hasExtension(ToolingExtensions.EXT_DAR)) { - x.tx("Absent because : "); - x.code().tx(p.getExtensionString(ToolingExtensions.EXT_DAR)); - } else if (p.hasExtension(ToolingExtensions.EXT_NF)) { - x.tx("Null because: "); - x.code().tx(p.getExtensionString(ToolingExtensions.EXT_NF)); - } else if (p.hasExtension(ToolingExtensions.EXT_OT)) { - x.code().tx("Text: "); - x.tx(p.getExtensionString(ToolingExtensions.EXT_OT)); - } else if (p.hasExtension(ToolingExtensions.EXT_CQF_EXP)) { - x.code().tx("Value calculated by: "); - Expression exp = p.getExtensionByUrl(ToolingExtensions.EXT_CQF_EXP).getValueExpression(); - x.tx(p.getExtensionString(ToolingExtensions.EXT_OT)); - renderExpression(x, exp); - } else { - x.addText("??"); - } - } else if (e instanceof StringType) - x.addText(((StringType) e).getValue()); - else if (e instanceof CodeType) - x.addText(((CodeType) e).getValue()); - else if (e instanceof IdType) - x.addText(((IdType) e).getValue()); - else if (e instanceof InstantType) - x.addText(((InstantType) e).toHumanDisplay()); - else if (e instanceof DateTimeType) { - renderDateTime(x, e); - } else if (e instanceof Base64BinaryType) { - Base64BinaryType b64 = (Base64BinaryType) e; - x.addText("(base64 data - "+(b64.getValue() == null ? "0" : b64.getValue().length)+" bytes)"); - } else if (e instanceof org.hl7.fhir.r5.model.DateType) { - org.hl7.fhir.r5.model.DateType dt = ((org.hl7.fhir.r5.model.DateType) e); - renderDate(x, dt); - } else if (e instanceof Enumeration) { - Object ev = ((Enumeration) e).getValue(); - x.addText(ev == null ? "" : ev.toString()); // todo: look up a display name if there is one - } else if (e instanceof org.hl7.fhir.r5.model.IntegerType) { - if (((org.hl7.fhir.r5.model.IntegerType) e).hasValue()) { - x.addText(Integer.toString(((org.hl7.fhir.r5.model.IntegerType) e).getValue())); - } else { - x.addText("??"); - } - } else if (e instanceof org.hl7.fhir.r5.model.Integer64Type) { - if (((org.hl7.fhir.r5.model.Integer64Type) e).hasValue()) { - x.addText(Long.toString(((org.hl7.fhir.r5.model.Integer64Type) e).getValue())); - } else { - x.addText("??"); - } - } else if (e instanceof org.hl7.fhir.r5.model.DecimalType) { - x.addText(((org.hl7.fhir.r5.model.DecimalType) e).getValue().toString()); - } else if (e instanceof UriType) { - renderUri(x, (UriType) e, defn.getPath(), rcontext != null && rcontext.getResource() != null ? rcontext.getResource().getId() : null, res.getResource()); - } else if (e instanceof BooleanType) { - x.addText(((BooleanType) e).getValue().toString()); - } else { // e instanceof PrimitiveType - x.tx(((PrimitiveType) e).primitiveValue()); + if (Utilities.existsInList(ew.fhirType(), "Extension") || ew.isResource()) { + return; + } else if (ew.fhirType().equals("ElementDefinition")) { + x.tx("todo-bundle"); + } else if (!renderDataType(status, parent, x, ew)) { + if (Utilities.existsInList(ew.fhirType(), "Attachment", "Narrative", "Meta", "ProductShelfLife", "RelatedArtifact")) { + throw new NotImplementedException("type "+ew.fhirType()+" not handled. This may be due to unresolved inter-version compatibility issues"); } - } else { - if (e instanceof Extension) { - return; - } else if (e instanceof CodeableConcept) { - renderCodeableConcept(x, (CodeableConcept) e, showCodeDetails); - } else if (e instanceof Coding) { - renderCoding(x, (Coding) e, showCodeDetails); - } else if (e instanceof CodeableReference) { - renderCodeableReference(x, (CodeableReference) e, showCodeDetails); - } else if (e instanceof Annotation) { - renderAnnotation(x, (Annotation) e); - } else if (e instanceof Identifier) { - renderIdentifier(x, (Identifier) e); - } else if (e instanceof HumanName) { - renderHumanName(x, (HumanName) e); - } else if (e instanceof SampledData) { - renderSampledData(x, (SampledData) e); - } else if (e instanceof Address) { - renderAddress(x, (Address) e); - } else if (e instanceof ContactPoint) { - renderContactPoint(x, (ContactPoint) e); - } else if (e instanceof Expression) { - renderExpression(x, (Expression) e); - } else if (e instanceof Money) { - renderMoney(x, (Money) e); - } else if (e instanceof ContactDetail) { - ContactDetail cd = (ContactDetail) e; - if (cd.hasName()) { - x.tx(cd.getName()+": "); - } - boolean first = true; - for (ContactPoint c : cd.getTelecom()) { - if (first) first = false; else x.tx(","); - renderContactPoint(x, c); - } - } else if (e instanceof Timing) { - renderTiming(x, (Timing) e); - } else if (e instanceof Range) { - renderRange(x, (Range) e); - } else if (e instanceof Quantity) { - renderQuantity(x, (Quantity) e, showCodeDetails); - } else if (e instanceof Ratio) { - renderQuantity(x, ((Ratio) e).getNumerator(), showCodeDetails); - x.tx("/"); - renderQuantity(x, ((Ratio) e).getDenominator(), showCodeDetails); - } else if (e instanceof Period) { - Period p = (Period) e; - renderPeriod(x, p); - } else if (e instanceof Reference) { - Reference r = (Reference) e; - if (r.getReference() != null && r.getReference().contains("#")) { - if (containedIds.contains(r.getReference().substring(1))) { - x.ah("#hc"+r.getReference().substring(1)).tx("See "+r.getReference()); - } else { - // in this case, we render the resource in line - ResourceWrapper rw = null; - for (ResourceWrapper t : res.getContained()) { - if (r.getReference().substring(1).equals(t.getId())) { - rw = t; - } - } - if (rw == null) { - renderReference(res, x, r); - } else { - String ref = context.getResolver() != null ?context.getResolver().urlForContained(context, res.fhirType(), res.getId(), rw.fhirType(), rw.getId()) : null; - if (ref == null) { - x.an("hc"+rw.getId()); - RenderingContext ctxtc = context.copy(); - ctxtc.setAddGeneratedNarrativeHeader(false); - ctxtc.setContained(true); - ResourceRenderer rr = RendererFactory.factory(rw, ctxtc); - rr.setRcontext(new ResourceContext(rcontext, rw)); - rr.render(parent.blockquote(), rw); - } else { - x.ah(ref).tx("See "+rw.fhirType()); - } - } - } - } else { - renderReference(res, x, r); - } - } else if (e instanceof Resource) { - return; - } else if (e instanceof DataRequirement) { - DataRequirement p = (DataRequirement) e; - renderDataRequirement(x, p); - } else if (e instanceof TriggerDefinition) { - TriggerDefinition p = (TriggerDefinition) e; - renderTriggerDefinition(x, p); - } else if (e instanceof UsageContext) { - UsageContext p = (UsageContext) e; - renderUsageContext(x, p); - } else if (e instanceof ElementDefinition) { - x.tx("todo-bundle"); - } else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta) && !(e instanceof ProductShelfLife) && !(e instanceof RelatedArtifact)) { - throw new NotImplementedException("type "+e.fhirType()+" not handled. This may be due to unresolved inter-version compatibility issues"); - } - } + } } - private XhtmlNode renderCommentsSpan(XhtmlNode x, Base e) { + private XhtmlNode renderCommentsSpan(XhtmlNode x, ResourceWrapper e) { if (e.hasFormatComment()) { return x.span(null, CommaSeparatedStringBuilder.join(" ", e.getFormatCommentsPre())); } else { return x; } } - - private boolean displayLeaf(ResourceWrapper res, BaseWrapper ew, ElementDefinition defn, XhtmlNode x, String name, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException { - return displayLeaf(res, ew, defn, x, name, showCodeDetails, true); - } - private boolean displayLeaf(ResourceWrapper res, BaseWrapper ew, ElementDefinition defn, XhtmlNode x, String name, boolean showCodeDetails, boolean allowLinks) throws FHIRException, UnsupportedEncodingException, IOException { + private boolean displayLeaf(ResourceWrapper res, ResourceWrapper ew, ElementDefinition defn, XhtmlNode x, String name, boolean showCodeDetails, boolean allowLinks) throws FHIRException, UnsupportedEncodingException, IOException { if (ew == null) return false; - Base e = ew.getBase(); - if (e == null) - return false; Map displayHints = readDisplayHints(defn); if (name.endsWith("[x]")) name = name.substring(0, name.length() - 3); - if (!showCodeDetails && e instanceof PrimitiveType && isDefault(displayHints, ((PrimitiveType) e))) + if (!showCodeDetails && ew.isPrimitive() && isDefault(displayHints, ew)) { return false; - - if (e instanceof StringType) { - x.addText(name+": "+((StringType) e).getValue()); - return true; - } else if (e instanceof CodeType) { - x.addText(name+": "+((CodeType) e).getValue()); - return true; - } else if (e instanceof IdType) { - x.addText(name+": "+((IdType) e).getValue()); - return true; - } else if (e instanceof UriType) { - if (Utilities.isAbsoluteUrlLinkable(((UriType) e).getValue()) && allowLinks) { - x.tx(name+": "); - x.ah(((UriType) e).getValue()).addText(((UriType) e).getValue()); - } else { - x.addText(name+": "+((UriType) e).getValue()); - } - return true; - } else if (e instanceof DateTimeType) { - x.addText(name+": "+((DateTimeType) e).toHumanDisplay()); - return true; - } else if (e instanceof InstantType) { - x.addText(name+": "+((InstantType) e).toHumanDisplay()); - return true; - } else if (e instanceof Extension) { - // x.tx("Extensions: todo"); + } else if (Utilities.existsInList(ew.fhirType(), "Extension")) { return false; - } else if (e instanceof org.hl7.fhir.r5.model.DateType) { - x.addText(name+": "+((org.hl7.fhir.r5.model.DateType) e).toHumanDisplay()); + } else { + x.addText(name+": "+ displayDataType(ew)); return true; - } else if (e instanceof Enumeration) { - x.addText(((Enumeration) e).getValue().toString()); // todo: look up a display name if there is one - return true; - } else if (e instanceof BooleanType) { - if (((BooleanType) e).hasValue()) { - x.addText(name); - x.addText(": "); - x.addText(((BooleanType) e).getValueAsString()); - return true; - } - } else if (e instanceof CodeableReference) { - if (((CodeableReference) e).hasReference()) { - Reference r = ((CodeableReference) e).getReference(); - renderReference(res, x, r, allowLinks); - } else { - renderCodeableConcept(x, ((CodeableReference) e).getConcept(), showCodeDetails); - } - return true; - } else if (e instanceof CodeableConcept) { - renderCodeableConcept(x, (CodeableConcept) e, showCodeDetails); - return true; - } else if (e instanceof Coding) { - renderCoding(x, (Coding) e, showCodeDetails); - return true; - } else if (e instanceof Annotation) { - renderAnnotation(x, (Annotation) e, showCodeDetails); - return true; - } else if (e instanceof org.hl7.fhir.r5.model.IntegerType) { - x.addText(Integer.toString(((org.hl7.fhir.r5.model.IntegerType) e).getValue())); - return true; - } else if (e instanceof org.hl7.fhir.r5.model.DecimalType) { - x.addText(((org.hl7.fhir.r5.model.DecimalType) e).getValue().toString()); - return true; - } else if (e instanceof Identifier) { - renderIdentifier(x, (Identifier) e); - return true; - } else if (e instanceof HumanName) { - renderHumanName(x, (HumanName) e); - return true; - } else if (e instanceof SampledData) { - renderSampledData(x, (SampledData) e); - return true; - } else if (e instanceof Address) { - renderAddress(x, (Address) e); - return true; - } else if (e instanceof ContactPoint) { - if (allowLinks) { - renderContactPoint(x, (ContactPoint) e); - } else { - displayContactPoint(x, (ContactPoint) e); - } - return true; - } else if (e instanceof Timing) { - renderTiming(x, (Timing) e); - return true; - } else if (e instanceof Quantity) { - renderQuantity(x, (Quantity) e, showCodeDetails); - return true; - } else if (e instanceof Ratio) { - renderQuantity(x, ((Ratio) e).getNumerator(), showCodeDetails); - x.tx("/"); - renderQuantity(x, ((Ratio) e).getDenominator(), showCodeDetails); - return true; - } else if (e instanceof Period) { - Period p = (Period) e; - x.addText(name+": "); - x.addText(!p.hasStart() ? "?ngen-2?" : p.getStartElement().toHumanDisplay()); - x.tx(" --> "); - x.addText(!p.hasEnd() ? "(ongoing)" : p.getEndElement().toHumanDisplay()); - return true; - } else if (e instanceof Reference) { - Reference r = (Reference) e; - if (r.hasDisplayElement()) - x.addText(r.getDisplay()); - else if (r.hasReferenceElement()) { - ResourceWithReference tr = resolveReference(res, r.getReference()); - x.addText(tr == null ? r.getReference() : "?ngen-3"); // getDisplayForReference(tr.getReference())); - } else - x.tx("?ngen-4?"); - return true; - } else if (e instanceof Narrative) { - return false; - } else if (e instanceof Resource) { - return false; - } else if (e instanceof ContactDetail) { - ContactDetail cd = (ContactDetail) e; - if (cd.hasName()) { - x.tx(cd.getName()+": "); - } - boolean first = true; - for (ContactPoint c : cd.getTelecom()) { - if (first) first = false; else x.tx(","); - if (allowLinks) { - renderContactPoint(x, c); - } else { - displayContactPoint(x, c); - } - } - return true; - } else if (e instanceof Range) { - return false; - } else if (e instanceof Meta) { - return false; - } else if (e instanceof Dosage) { - return false; - } else if (e instanceof Signature) { - return false; - } else if (e instanceof UsageContext) { - return false; - } else if (e instanceof RelatedArtifact) { - return false; - } else if (e instanceof ElementDefinition) { - return false; - } else if (e instanceof Base64BinaryType) { - return false; - } else if (!(e instanceof Attachment)) - throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet"); - return false; + } } @@ -771,81 +269,56 @@ public class ProfileDrivenRenderer extends ResourceRenderer { return results; } - - private boolean generateByProfile(StructureDefinition profile, boolean showCodeDetails) { - XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - if(context.isAddGeneratedNarrativeHeader()) { - x.para().b().tx("Generated Narrative: "+profile.present()+(showCodeDetails ? " with Details" : "")); - } - try { - generateByProfile(rcontext.getResource(), profile, rcontext.getResource(), profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile, profile.getSnapshot().getElement(), rcontext.getResource().getResourceType().toString()), x, rcontext.getResource().getResourceType().toString(), showCodeDetails); - } catch (Exception e) { - e.printStackTrace(); - x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage()); - } - inject((DomainResource) rcontext.getResource(), x, NarrativeStatus.GENERATED); - return true; - } - - private void generateByProfile(Resource res, StructureDefinition profile, Base e, List allElements, ElementDefinition defn, List children, XhtmlNode x, String path, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { - generateByProfile(new ResourceWrapperDirect(this.context, res), profile, new BaseWrapperDirect(this.context, e), allElements, defn, children, x, path, showCodeDetails, 0); - } - - private void generateByProfile(ResourceWrapper res, StructureDefinition profile, BaseWrapper e, List allElements, ElementDefinition defn, List children, XhtmlNode x, String path, boolean showCodeDetails, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { + private void generateByProfile(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, ResourceWrapper e, List allElements, ElementDefinition defn, List children, XhtmlNode x, String path, boolean showCodeDetails, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { if (children.isEmpty()) { StructureDefinition sdt = context.getWorker().fetchTypeDefinition(e.fhirType()); if (sdt != null && (sdt.getKind() == StructureDefinitionKind.COMPLEXTYPE || sdt.getKind() == StructureDefinitionKind.PRIMITIVETYPE)) { - renderLeaf(res, e, defn, x, x, false, showCodeDetails, readDisplayHints(defn), path, indent); + renderLeaf(status, res, e, defn, x, x, false, showCodeDetails, readDisplayHints(defn), path, indent); } else { // we don't have anything to render? } } else { - List pl = splitExtensions(profile, e.children()); - for (PropertyWrapper p : pl) { - generateForProperty(res, profile, allElements, children, x, path, showCodeDetails, indent, false, p); + List pl = splitExtensions(profile, e.childrenInGroups()); + for (NamedResourceWrapperList p : pl) { + generateForProperty(status, res, profile, allElements, children, x, path, showCodeDetails, indent, false, p); } - for (PropertyWrapper p : pl) { - generateForProperty(res, profile, allElements, children, x, path, showCodeDetails, indent, true, p); + for (NamedResourceWrapperList p : pl) { + generateForProperty(status, res, profile, allElements, children, x, path, showCodeDetails, indent, true, p); } } } - private void generateForProperty(ResourceWrapper res, StructureDefinition profile, + private void generateForProperty(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, List allElements, List children, XhtmlNode x, String path, - boolean showCodeDetails, int indent, boolean round2, PropertyWrapper p) + boolean showCodeDetails, int indent, boolean round2, NamedResourceWrapperList p) throws UnsupportedEncodingException, IOException, EOperationOutcome { - if (p.hasValues()) { - ElementDefinition child = getElementDefinition(children, path+"."+p.getName(), p); - if (child == null) { - child = p.getElementDefinition(); - } + if (!p.getValues().isEmpty()) { + ElementDefinition child = getElementDefinition(children, path+"."+p.getName()); if (child != null) { if (!child.getBase().hasPath() || !child.getBase().getPath().startsWith("Resource.")) { - generateElementByProfile(res, profile, allElements, x, path, showCodeDetails, indent, p, child, round2); + generateElementByProfile(status, res, profile, allElements, x, path, showCodeDetails, indent, p, child, round2); } } } } - public void generateElementByProfile(ResourceWrapper res, StructureDefinition profile, List allElements, XhtmlNode x, String path, - boolean showCodeDetails, int indent, PropertyWrapper p, ElementDefinition child, boolean round2) throws UnsupportedEncodingException, IOException, EOperationOutcome { + public void generateElementByProfile(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, List allElements, XhtmlNode x, String path, + boolean showCodeDetails, int indent, NamedResourceWrapperList p, ElementDefinition child, boolean round2) throws UnsupportedEncodingException, IOException, EOperationOutcome { Map displayHints = readDisplayHints(child); if ("DomainResource.contained".equals(child.getBase().getPath())) { if (round2) { - for (BaseWrapper v : p.getValues()) { - if (v.getResource() != null && !RendererFactory.hasSpecificRenderer(v.fhirType())) { + for (ResourceWrapper v : p.getValues()) { + RenderingContext ctxt = context.forContained(); + if (v.getResourceWrapper() != null && !RendererFactory.hasSpecificRenderer(v.fhirType())) { x.hr(); - RenderingContext ctxt = context.copy(); - ctxt.setContained(true); ResourceRenderer rnd = RendererFactory.factory(v.fhirType(), ctxt); - ResourceWrapper rw = v.getResource(); - rnd.render(x.blockquote(), rw); + rnd.buildNarrative(status, x.blockquote(), v); } } } } else if (!round2 && !exemptFromRendering(child)) { if (isExtension(p)) { - hasExtensions = true; + status.setExtensions(true); } List grandChildren = getChildrenForPath(profile, allElements, path+"."+p.getName()); filterGrandChildren(grandChildren, path+"."+p.getName(), p); @@ -856,21 +329,24 @@ public class ProfileDrivenRenderer extends ResourceRenderer { if (name.endsWith("[x]")) name = name.substring(0, name.length() - 3); if (showCodeDetails || !isDefaultValue(displayHints, p.getValues())) { + if ("library".equals(name)) { + DebugUtilities.breakpoint(); + } para.b().addText(name); para.tx(": "); if (renderAsList(child) && p.getValues().size() > 1) { XhtmlNode list = x.ul(); - for (BaseWrapper v : p.getValues()) - renderLeaf(res, v, child, x, list.li(), false, showCodeDetails, displayHints, path, indent); + for (ResourceWrapper v : p.getValues()) + renderLeaf(status, res, v, child, x, list.li(), false, showCodeDetails, displayHints, path, indent); } else { boolean first = true; - for (BaseWrapper v : p.getValues()) { + for (ResourceWrapper v : p.getValues()) { if (first) { first = false; } else { para.tx(", "); } - renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent); + renderLeaf(status, res, v, child, x, para, false, showCodeDetails, displayHints, path, indent); } } } @@ -882,11 +358,11 @@ public class ProfileDrivenRenderer extends ResourceRenderer { XhtmlNode tr = tbl.tr(); tr.td().style("display: none").tx("-"); // work around problem with empty table rows boolean add = addColumnHeadings(tr, grandChildren); - for (BaseWrapper v : p.getValues()) { + for (ResourceWrapper v : p.getValues()) { if (v != null) { tr = tbl.tr(); tr.td().style("display: none").tx("*"); // work around problem with empty table rows - add = addColumnValues(res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent) || add; + add = addColumnValues(status, res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent) || add; } } if (add) { @@ -894,33 +370,32 @@ public class ProfileDrivenRenderer extends ResourceRenderer { x.add(tbl); } } else if (isExtension(p)) { - for (BaseWrapper v : p.getValues()) { + for (ResourceWrapper v : p.getValues()) { if (v != null) { - PropertyWrapper vp = v.getChildByName("value"); - PropertyWrapper ev = v.getChildByName("extension"); - if (vp.hasValues()) { - BaseWrapper vv = vp.value(); + ResourceWrapper vp = v.child("value"); + List ev = v.children("extension"); + if (vp != null) { XhtmlNode para = x.para(); - para.b().addText(p.getStructure().present()); + para.b().addText(labelforExtension(p.getName())); para.tx(": "); - renderLeaf(res, vv, child, x, para, false, showCodeDetails, displayHints, path, indent); - } else if (ev.hasValues()) { + renderLeaf(status, res, vp, child, x, para, false, showCodeDetails, displayHints, path, indent); + } else if (!ev.isEmpty()) { XhtmlNode bq = x.addTag("blockquote"); - bq.para().b().addText(isExtension(p) ? p.getStructure().present() : p.getName()); - for (BaseWrapper vv : ev.getValues()) { + bq.para().b().addText(labelforExtension(p.getName())); + for (ResourceWrapper vv : ev) { StructureDefinition ex = context.getWorker().fetchTypeDefinition("Extension"); List children = getChildrenForPath(profile, ex.getSnapshot().getElement(), "Extension"); - generateByProfile(res, ex, vv, allElements, child, children, bq, "Extension", showCodeDetails, indent+1); + generateByProfile(status, res, ex, vv, allElements, child, children, bq, "Extension", showCodeDetails, indent+1); } } } } } else { - for (BaseWrapper v : p.getValues()) { + for (ResourceWrapper v : p.getValues()) { if (v != null) { XhtmlNode bq = x.addTag("blockquote"); - bq.para().b().addText(isExtension(p) ? p.getStructure().present() : p.getName()); - generateByProfile(res, profile, v, allElements, child, grandChildren, bq, path+"."+p.getName(), showCodeDetails, indent+1); + bq.para().b().addText(p.getName()); + generateByProfile(status, res, profile, v, allElements, child, grandChildren, bq, path+"."+p.getName(), showCodeDetails, indent+1); } } } @@ -929,6 +404,15 @@ public class ProfileDrivenRenderer extends ResourceRenderer { } + private String labelforExtension(String url) { + StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, url); + if (sd == null) { + return tail(url); + } else { + return sd.present(); + } + } + private String getHeader() { int i = 3; while (i <= context.getHeaderLevelContext()) @@ -938,18 +422,18 @@ public class ProfileDrivenRenderer extends ResourceRenderer { return "h"+Integer.toString(i); } - private List getValues(String path, PropertyWrapper p, ElementDefinition e) { - List res = new ArrayList(); - for (BaseWrapper v : p.getValues()) { - for (PropertyWrapper g : v.children()) { - if ((path+"."+p.getName()+"."+g.getName()).equals(e.getPath())) - res.add(p); + private List getValues(String path, NamedResourceWrapperList p, ElementDefinition e) { + List res = new ArrayList(); + for (ResourceWrapper v : p.getValues()) { + for (ResourceWrapper g : v.children()) { + if ((path+"."+p.getName()+"."+g.name()).equals(e.getPath())) + res.add(v); } } return res; } - private boolean canDoTable(String path, PropertyWrapper p, List grandChildren, XhtmlNode x) { + private boolean canDoTable(String path, NamedResourceWrapperList p, List grandChildren, XhtmlNode x) { if (isExtension(p)) { return false; } @@ -962,14 +446,14 @@ public class ProfileDrivenRenderer extends ResourceRenderer { } for (ElementDefinition e : grandChildren) { - List values = getValues(path, p, e); + List values = getValues(path, p, e); if (values.size() > 1 || !isSimple(e) || !canCollapse(e)) return false; } return true; } - public boolean isExtension(PropertyWrapper p) { + public boolean isExtension(NamedResourceWrapperList p) { return p.getName().contains("extension["); } @@ -1011,33 +495,33 @@ public class ProfileDrivenRenderer extends ResourceRenderer { return b; } - private boolean addColumnValues(ResourceWrapper res, XhtmlNode tr, List grandChildren, BaseWrapper v, boolean showCodeDetails, Map displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { + private boolean addColumnValues(RenderingStatus status, ResourceWrapper res, XhtmlNode tr, List grandChildren, ResourceWrapper v, boolean showCodeDetails, Map displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome { boolean b = false; for (ElementDefinition e : grandChildren) { - PropertyWrapper p = v.getChildByName(e.getPath().substring(e.getPath().lastIndexOf(".")+1)); + List p = v.children(e.getPath().substring(e.getPath().lastIndexOf(".")+1)); XhtmlNode td = tr.td(); - if (p == null || p.getValues().size() == 0 || p.getValues().get(0) == null) { + if (p == null || p.size() == 0) { b = true; td.tx(" "); } else { - for (BaseWrapper vv : p.getValues()) { + for (ResourceWrapper vv : p) { b = true; td.sep(", "); - renderLeaf(res, vv, e, td, td, false, showCodeDetails, displayHints, path, indent); + renderLeaf(status, res, vv, e, td, td, false, showCodeDetails, displayHints, path, indent); } } } return b; } - private void filterGrandChildren(List grandChildren, String string, PropertyWrapper prop) { + private void filterGrandChildren(List grandChildren, String string, NamedResourceWrapperList prop) { List toRemove = new ArrayList(); toRemove.addAll(grandChildren); - for (BaseWrapper b : prop.getValues()) { + for (ResourceWrapper b : prop.getValues()) { List list = new ArrayList(); for (ElementDefinition ed : toRemove) { - PropertyWrapper p = b.getChildByName(tail(ed.getPath())); - if (p != null && p.hasValues()) + List p = b.children(tail(ed.getPath())); + if (p != null && !p.isEmpty()) list.add(ed); } toRemove.removeAll(list); @@ -1045,20 +529,15 @@ public class ProfileDrivenRenderer extends ResourceRenderer { grandChildren.removeAll(toRemove); } - private List splitExtensions(StructureDefinition profile, List children) throws UnsupportedEncodingException, IOException, FHIRException { - List results = new ArrayList(); - Map map = new HashMap(); - for (PropertyWrapper p : children) + private List splitExtensions(StructureDefinition profile, List children) throws UnsupportedEncodingException, IOException, FHIRException { + List results = new ArrayList(); + for (NamedResourceWrapperList p : children) { if (p.getName().equals("extension") || p.getName().equals("modifierExtension")) { // we're going to split these up, and create a property for each url - if (p.hasValues()) { - for (BaseWrapper v : p.getValues()) { - Base b = v.getBase(); - if (!(b instanceof Extension)) { - throw new FHIRException("huh?"); - } - Extension ex = (Extension) b; - String url = ex.getUrl(); + for (ResourceWrapper v : p.getValues()) { + String url = v.primitiveValue("url"); + if (url != null) { + // 1. check extension is valid StructureDefinition ed = getContext().getWorker().fetchResource(StructureDefinition.class, url); if (ed == null) { if (xverManager == null) { @@ -1072,24 +551,28 @@ public class ProfileDrivenRenderer extends ResourceRenderer { } if (p.getName().equals("modifierExtension") && ed == null) { throw new DefinitionException("Unknown modifier extension "+url); + } else { + // nothing } - PropertyWrapper pe = map.get(p.getName()+"["+url+"]"); - if (pe == null) { - if (ed == null) { - // System.out.println("unknown extension "+url); - pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex), null); - } else { - ElementDefinition def = ed.getSnapshot().getElement().get(0); - pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", "Extension", def.getDefinition(), def.getMin(), def.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(def.getMax()), ex), ed.getSnapshot().getElementFirstRep()); - ((PropertyWrapperDirect) pe).getWrapped().setStructure(ed); + + // 2. Park it + NamedResourceWrapperList nl = null; + for (NamedResourceWrapperList t : results) { + if (t.getName().equals(url)) { + nl = t; } - results.add(pe); - } else - pe.getValues().add(v); + } + if (nl == null) { + nl = new NamedResourceWrapperList(url); + results.add(nl); + } + nl.getValues().add(v); } - } - } else + } + } else { results.add(p); + } + } return results; } @@ -1117,17 +600,17 @@ public class ProfileDrivenRenderer extends ResourceRenderer { } @SuppressWarnings("rawtypes") - private boolean isDefaultValue(Map displayHints, List list) throws UnsupportedEncodingException, IOException, FHIRException { + private boolean isDefaultValue(Map displayHints, List list) throws UnsupportedEncodingException, IOException, FHIRException { if (list.size() != 1) return false; - if (list.get(0).getBase() instanceof PrimitiveType) - return isDefault(displayHints, (PrimitiveType) list.get(0).getBase()); + if (list.get(0).isPrimitive()) + return isDefault(displayHints, list.get(0)); else return false; } - private boolean isDefault(Map displayHints, PrimitiveType primitiveType) { - String v = primitiveType.asStringValue(); + private boolean isDefault(Map displayHints, ResourceWrapper primitiveType) { + String v = primitiveType.primitiveValue(); if (!Utilities.noString(v) && displayHints.containsKey("default") && v.equals(displayHints.get("default"))) return true; return false; diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProvenanceRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProvenanceRenderer.java index 3f79e7b43..57b007404 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProvenanceRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ProvenanceRenderer.java @@ -2,40 +2,42 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.List; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.Provenance; -import org.hl7.fhir.r5.model.Provenance.ProvenanceAgentComponent; -import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.UriType; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class ProvenanceRenderer extends ResourceRenderer { - - public ProvenanceRenderer(RenderingContext context) { - super(context); + + public ProvenanceRenderer(RenderingContext context) { + super(context); + } + + @Override + public String buildSummary(ResourceWrapper prv) throws UnsupportedEncodingException, IOException { + return (context.formatPhrase(RenderingContext.PROV_FOR, displayReference(prv.firstChild("target")))+" "); } - public boolean render(XhtmlNode x, Resource prv) throws UnsupportedEncodingException, IOException { - return render(x, (Provenance) prv); - } - - public boolean render(XhtmlNode x, Provenance prv) throws UnsupportedEncodingException, IOException { - boolean hasExtensions = false; + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper prv) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(prv, x); - if (!prv.getTarget().isEmpty()) { - if (prv.getTarget().size() == 1) { + if (prv.has("target")) { + List tl = prv.children("target"); + if (tl.size() == 1) { XhtmlNode p = x.para(); p.tx(context.formatPhrase(RenderingContext.PROV_PROV)+" "); - renderReference(prv, p, prv.getTargetFirstRep()); + renderReference(status, p, tl.get(0)); } else { x.para().tx(context.formatPhrase(RenderingContext.PROV_PROVE)+" "); XhtmlNode ul = x.ul(); - for (Reference ref : prv.getTarget()) { - renderReference(prv, ul.li(), ref); + for (ResourceWrapper ref : tl) { + renderReference(status, ul.li(), ref); } } } @@ -43,50 +45,47 @@ public class ProvenanceRenderer extends ResourceRenderer { x.para().tx(context.formatPhrase(RenderingContext.GENERAL_SUMM)); XhtmlNode t = x.table("grid"); XhtmlNode tr; - if (prv.hasOccurred()) { + if (prv.has("occurred")) { tr = t.tr(); tr.td().tx(context.formatPhrase(RenderingContext.PROV_OCC)); - if (prv.hasOccurredPeriod()) { - renderPeriod(tr.td(), prv.getOccurredPeriod()); - } else { - renderDateTime(tr.td(), prv.getOccurredDateTimeType()); - } + renderDataType(status, tr.td(), prv.child("occurred")); } - if (prv.hasRecorded()) { + if (prv.has("recorded")) { tr = t.tr(); tr.td().tx(context.formatPhrase(RenderingContext.PROV_REC)); - tr.td().addText(displayDateTime(prv.getRecordedElement())); + renderDataType(status, tr.td(), prv.child("recorded")); } - if (prv.hasPolicy()) { + if (prv.has("policy")) { + List tl = prv.children("policy"); tr = t.tr(); tr.td().tx(context.formatPhrase(RenderingContext.PROV_POL)); - if (prv.getPolicy().size() == 1) { - renderUri(tr.td(), prv.getPolicy().get(0)); + if (tl.size() == 1) { + renderDataType(status, tr.td(), tl.get(0)); } else { XhtmlNode ul = tr.td().ul(); - for (UriType u : prv.getPolicy()) { - renderUri(ul.li(), u); + for (ResourceWrapper u : tl) { + renderDataType(status, ul.li(), u); } } } - if (prv.hasLocation()) { + if (prv.has("location")) { tr = t.tr(); tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_LOCATION)); - renderReference(prv, tr.td(), prv.getLocation()); + renderDataType(status, tr.td(), prv.child("location")); } - if (prv.hasActivity()) { + if (prv.has("activity")) { tr = t.tr(); tr.td().tx(context.formatPhrase(RenderingContext.PROV_ACT)); - renderCodeableConcept(tr.td(), prv.getActivity(), false); + renderDataType(status, tr.td(), prv.child("activity")); } boolean hasType = false; boolean hasRole = false; boolean hasOnBehalfOf = false; - for (ProvenanceAgentComponent a : prv.getAgent()) { - hasType = hasType || a.hasType(); - hasRole = hasRole || a.hasRole(); - hasOnBehalfOf = hasOnBehalfOf || a.hasOnBehalfOf(); + for (ResourceWrapper a : prv.children("agent")) { + hasType = hasType || a.has("type"); + hasRole = hasRole || a.has("role"); + hasOnBehalfOf = hasOnBehalfOf || a.has("onBehalfOf"); } x.para().b().tx(context.formatPhrase(RenderingContext.PROV_AGE)); t = x.table("grid"); @@ -101,37 +100,36 @@ public class ProvenanceRenderer extends ResourceRenderer { if (hasOnBehalfOf) { tr.td().b().tx(context.formatPhrase(RenderingContext.PROV_BEHALF)); } - for (ProvenanceAgentComponent a : prv.getAgent()) { + for (ResourceWrapper a : prv.children("agent")) { tr = t.tr(); if (hasType) { - if (a.hasType()) { - renderCodeableConcept(tr.td(), a.getType(), false); + if (a.has("type")) { + renderDataType(status, tr.td(), a.child("type")); } else { tr.td(); } } if (hasRole) { - if (a.hasRole()) { - if (a.getRole().size() == 1) { - renderCodeableConcept(tr.td(), a.getType(), false); - } else { - XhtmlNode ul = tr.td().ul(); - for (CodeableConcept cc : a.getRole()) { - renderCodeableConcept(ul.li(), cc, false); - } - } - } else { + List tl = prv.children("role"); + if (tl.size() == 0) { tr.td(); + } else if (tl.size() == 1) { + renderCodeableConcept(status, tr.td(), tl.get(0)); + } else { + XhtmlNode ul = tr.td().ul(); + for (ResourceWrapper cc : tl) { + renderCodeableConcept(status, ul.li(), cc); + } } } - if (a.hasWho()) { - renderReference(prv, tr.td(), a.getWho()); + if (a.has("who")) { + renderReference(status, tr.td(), a.child("who")); } else { tr.td(); } if (hasOnBehalfOf) { - if (a.hasOnBehalfOf()) { - renderReference(prv, tr.td(), a.getOnBehalfOf()); + if (a.has("onBehalfOf")) { + renderReference(status, tr.td(), a.child("onBehalfOf")); } else { tr.td(); } @@ -139,20 +137,7 @@ public class ProvenanceRenderer extends ResourceRenderer { } // agent table - return hasExtensions; } - public String display(Resource dr) throws UnsupportedEncodingException, IOException { - return display((Provenance) dr); - } - - public String display(Provenance prv) throws UnsupportedEncodingException, IOException { - return (context.formatPhrase(RenderingContext.PROV_FOR, displayReference(prv, prv.getTargetFirstRep()))+" "); - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - return (context.formatPhrase(RenderingContext.GENERAL_TODO)); - } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java index fcb88b8ba..7a409505d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireRenderer.java @@ -1,72 +1,88 @@ package org.hl7.fhir.r5.renderers; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r5.context.ContextUtilities; -import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.CanonicalType; -import org.hl7.fhir.r5.model.CodeType; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.Coding; -import org.hl7.fhir.r5.model.Expression; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.Questionnaire; -import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemAnswerOptionComponent; -import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent; -import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemEnableWhenComponent; -import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemInitialComponent; -import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.ValueSet; -import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; -import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; -import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; -import org.hl7.fhir.r5.utils.ToolingExtensions; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; -import org.hl7.fhir.utilities.xhtml.NodeType; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nonnull; + +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.context.ContextUtilities; +import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; +import org.hl7.fhir.r5.utils.EOperationOutcome; +import org.hl7.fhir.r5.utils.ToolingExtensions; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; +import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; - -import javax.annotation.Nonnull; - + public class QuestionnaireRenderer extends TerminologyRenderer { - public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = "http://hl7.org/fhir/4.0/StructureDefinition/extension-Questionnaire.item.type"; - + public static final String EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL = "http://hl7.org/fhir/4.0/StructureDefinition/extension-questionnaire.item.type"; + public QuestionnaireRenderer(RenderingContext context) { super(context); } - - public boolean render(XhtmlNode x, Resource q) throws UnsupportedEncodingException, IOException { - return render(x, (Questionnaire) q); - } - - public boolean render(XhtmlNode x, Questionnaire q) throws UnsupportedEncodingException, IOException { + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(q, x); + genSummaryTable(status, x, (CanonicalResource) q.getResourceNative()); switch (context.getQuestionnaireMode()) { - case FORM: return renderForm(x, q); - case LINKS: return renderLinks(x, q); - case LOGIC: return renderLogic(x, q); - case DEFNS: return renderDefns(x, q); - case TREE: return renderTree(x, q); + case FORM: + renderForm(status, x, q); + break; + case LINKS: + renderLinks(status, x, q); + break; + case LOGIC: + renderLogic(status, x, q); + break; + case DEFNS: + renderDefns(status, x, q); + break; + case TREE: + renderTree(status, x, q); + break; default: - throw new Error("Unknown Questionnaire Renderer Mode"); + throw new Error("Unknown questionnaire Renderer Mode"); } + + boolean first = true; + for (ResourceWrapper cont : q.children("contained")) { + if (first) { + x.h2().tx("Contained Resources"); + first = false; + } + x.hr(); + RendererFactory.factory(cont, context.forContained()).buildNarrative(status, x, cont); + } } - - public boolean renderTree(XhtmlNode x, Questionnaire q) throws UnsupportedEncodingException, IOException { - boolean hasFlags = checkForFlags(q.getItem()); - boolean doOpts = context.getDefinitionsTarget() == null && hasAnyOptions(q.getItem()); - + + public void renderTree(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws UnsupportedEncodingException, IOException { + boolean hasFlags = checkForFlags(q.children("item")); + boolean doOpts = context.getDefinitionsTarget() == null && hasAnyOptions(q.children("item")); + if (doOpts) { x.b().tx(context.formatPhrase(RenderingContext.QUEST_STRUCT)); } @@ -88,67 +104,65 @@ public class QuestionnaireRenderer extends TerminologyRenderer { } model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.GENERAL_DESC_CONST)), (context.formatPhrase(RenderingContext.QUEST_ADD_INFO)), null, 0)); - boolean hasExt = false; // first we add a root for the questionaire itself Row row = addTreeRoot(gen, model.getRows(), q, hasFlags); - for (QuestionnaireItemComponent i : q.getItem()) { - hasExt = renderTreeItem(gen, row.getSubRows(), q, i, hasFlags) || hasExt; + for (ResourceWrapper i : q.children("item")) { + renderTreeItem(status, gen, row.getSubRows(), q, i, hasFlags); } XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); x.getChildNodes().add(xn); if (doOpts) { renderOptions(q, x); } - return hasExt; } - - private void renderOptions(Questionnaire q, XhtmlNode x) { - if (hasAnyOptions(q.getItem())) { + + private void renderOptions(ResourceWrapper q, XhtmlNode x) { + if (hasAnyOptions(q.children("item"))) { x.hr(); x.para().b().tx(context.formatPhrase(RenderingContext.QUEST_OPT)); - renderOptions(q.getItem(), x); + renderOptions(q.children("item"), x); } } - - private void renderOptions(List items, XhtmlNode x) { - for (QuestionnaireItemComponent i : items) { + + private void renderOptions(List items, XhtmlNode x) { + for (ResourceWrapper i : items) { renderItemOptions(x, i); - renderOptions(i.getItem(), x); + renderOptions(i.children("item"), x); } } - - public void renderItemOptions(XhtmlNode x, QuestionnaireItemComponent i) { - if (i.hasAnswerOption()) { + + public void renderItemOptions(XhtmlNode x, ResourceWrapper i) { + if (i.has("answerOption")) { boolean useSelect = false; - for (QuestionnaireItemAnswerOptionComponent opt : i.getAnswerOption()) { - useSelect = useSelect || opt.getInitialSelected(); + for (ResourceWrapper opt : i.children("answerOption")) { + useSelect = useSelect || "true".equals(opt.primitiveValue("initialSelected")); } - x.an("opt-item."+i.getLinkId()); - x.para().b().tx(context.formatPhrase(RenderingContext.QUEST_ANSW, i.getLinkId())+" "); + x.an(context.prefixAnchor("opt-item."+i.primitiveValue("linkId"))); + x.para().b().tx(context.formatPhrase(RenderingContext.QUEST_ANSW, i.primitiveValue("linkId"))+" "); XhtmlNode ul = x.ul(); - for (QuestionnaireItemAnswerOptionComponent opt : i.getAnswerOption()) { + for (ResourceWrapper opt : i.children("answerOption")) { XhtmlNode li = ul.li(); li.style("font-size: 11px"); if (useSelect) { - if (opt.getInitialSelected()) { + if ("true".equals(opt.primitiveValue("initialSelected"))) { li.img("icon-selected.png", "icon"); } else { li.img("icon-not-selected.png", "icon"); } } - if (opt.getValue().isPrimitive()) { - li.tx(opt.getValue().primitiveValue()); - } else if (opt.getValue() instanceof Coding) { - Coding c = (Coding) opt.getValue(); - String link = c.hasSystem() ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), c.getSystem()) : null; + ResourceWrapper v = opt.child("value"); + if (v.isPrimitive()) { + li.tx(v.primitiveValue()); + } else if (v.fhirType().equals("Coding")) { + String link = v.has("system") ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), v.primitiveValue("system")) : null; if (link == null) { - li.tx(c.getSystem()+"#"+c.getCode()); + li.tx(v.primitiveValue("system")+"#"+v.primitiveValue("code")); } else { - li.ah(link).tx(displaySystem(c.getSystem())); - li.tx(": "+c.getCode()); + li.ah(link).tx(displaySystem(v.primitiveValue("system"))); + li.tx(": "+v.primitiveValue("code")); } - if (c.hasDisplay()) { - li.tx(" (\""+c.getDisplay()+"\")"); + if (v.has("display")) { + li.tx(" (\""+v.primitiveValue("display")+"\")"); } } else { li.tx("??"); @@ -156,39 +170,39 @@ public class QuestionnaireRenderer extends TerminologyRenderer { } } } - - private boolean hasAnyOptions(List items) { - for (QuestionnaireItemComponent i : items) { - if (i.hasAnswerOption()) { + + private boolean hasAnyOptions(List items) { + for (ResourceWrapper i : items) { + if (i.has("answerOption")) { return true; } - if (hasAnyOptions(i.getItem())) { + if (hasAnyOptions(i.children("item"))) { return true; } } return false; } - - private boolean checkForFlags(List items) { - for (QuestionnaireItemComponent i : items) { + + private boolean checkForFlags(List items) { + for (ResourceWrapper i : items) { if (checkForFlags(i)) { return true; } } return false; } - - private boolean checkForFlags(QuestionnaireItemComponent i) { - if (i.getReadOnly()) { + + private boolean checkForFlags(ResourceWrapper i) { + if (i.has("readOnly")) { return true; } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_IS_SUBJ)) { + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_IS_SUBJ))) { return true; } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_HIDDEN)) { + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) { return true; } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_OTP_DISP)) { + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) { return true; } if (i.hasExtension(ToolingExtensions.EXT_O_LINK_PERIOD)) { @@ -200,31 +214,31 @@ public class QuestionnaireRenderer extends TerminologyRenderer { if (i.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) { return true; } - return checkForFlags(i.getItem()); + return checkForFlags(i.children("item")); } - - - - private Row addTreeRoot(HierarchicalTableGenerator gen, List rows, Questionnaire q, boolean hasFlags) throws IOException { + + + + private Row addTreeRoot(HierarchicalTableGenerator gen, List rows, ResourceWrapper q, boolean hasFlags) throws IOException { Row r = gen.new Row(); rows.add(r); - + r.setIcon("icon_q_root.gif", context.formatPhrase(RenderingContext.QUEST_ROOT)); - r.getCells().add(gen.new Cell(null, null, q.getName(), null, null)); - r.getCells().add(gen.new Cell(null, null, q.getDescription(), null, null)); + r.getCells().add(gen.new Cell(null, null, q.primitiveValue("name"), null, null)); + r.getCells().add(gen.new Cell(null, null, q.primitiveValue("description"), null, null)); r.getCells().add(gen.new Cell(null, null, "", null, null)); r.getCells().add(gen.new Cell(null, null, context.formatPhrase(RenderingContext.QUEST_QUEST), null, null)); if (hasFlags) { r.getCells().add(gen.new Cell(null, null, "", null, null)); } - r.getCells().add(gen.new Cell(null, null, q.hasUrl() ? q.hasVersion() ? q.getUrl()+"#"+q.getVersion() : q.getUrl() : "", null, null)); + r.getCells().add(gen.new Cell(null, null, q.has("url") ? q.has("version") ? q.primitiveValue("url")+"#"+q.primitiveValue("version") : q.primitiveValue("url") : "", null, null)); return r; } - + private String getSpecLink(String path) { return Utilities.pathURL(context.getLink(KnownLinkType.SPEC), path); } - + private String getSDCLink(String url, String path) { StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, url); if (sd == null) { @@ -234,219 +248,238 @@ public class QuestionnaireRenderer extends TerminologyRenderer { return sd.getWebPath(); } else if (Utilities.isAbsoluteUrl(path)) { return path.replace("StructureDefinition/", "StructureDefinition-")+".html"; - } else { + } else if ("http://hl7.org/fhir/uv/sdc".equals(context.getPkp().getCanonicalForDefaultContext())) { + return Utilities.pathURL(path); // for now? + } else { return Utilities.pathURL("http://hl7.org/fhir/uv/sdc", path); // for now? } } - - private boolean renderTreeItem(HierarchicalTableGenerator gen, List rows, Questionnaire q, QuestionnaireItemComponent i, boolean hasFlags) throws IOException { + + private void renderTreeItem(RenderingStatus status, HierarchicalTableGenerator gen, List rows, ResourceWrapper q, ResourceWrapper i, boolean hasFlags) throws IOException { Row r = gen.new Row(); rows.add(r); - boolean hasExt = false; - - r.setIcon("icon-q-"+i.getType().toCode().toLowerCase()+".png", i.getType().getDisplay()); - Cell c1 = gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.getLinkId(), i.getLinkId(), null, null); - c1.setId("item."+i.getLinkId()); + String type = i.primitiveValue("type"); + + r.setIcon("icon-q-"+type.toLowerCase()+".png", type); + Cell c1 = gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), i.primitiveValue("linkId"), null, null); + c1.setId("item."+i.primitiveValue("linkId")); r.getCells().add(c1); - String txt = (i.hasPrefix() ? i.getPrefix() + ". " : "") + i.getText(); + String txt = (i.has("prefix") ? i.primitiveValue("prefix") + ". " : "") + i.primitiveValue("text"); r.getCells().add(gen.new Cell(null, null, txt, null, null)); - r.getCells().add(gen.new Cell(null, null, (i.getRequired() ? "1" : "0")+".."+(i.getRepeats() ? "*" : "1"), null, null)); - if (i.getTypeElement().hasExtension(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) { - String t = i.getTypeElement().getExtensionString(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL); + r.getCells().add(gen.new Cell(null, null, ("true".equals(i.primitiveValue("required")) ? "1" : "0")+".."+("true".equals(i.primitiveValue("repeats")) ? "*" : "1"), null, null)); + if (i.child("type").hasExtension(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) { + status.setExtensions(true); + String t = i.child("type").extensionString(EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL); r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+t, t, null, null)); } else { - r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+i.getType().toCode(), i.getType().toCode(), null, null)); + r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+type, type, null, null)); } - + if (hasFlags) { // flags: Cell flags = gen.new Cell(); r.getCells().add(flags); - if (i.getReadOnly()) { + if ("true".equals(i.primitiveValue("readOnly"))) { flags.addPiece(gen.new Piece(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "questionnaire-definitions.html#Questionnaire.item.readOnly"), null, context.formatPhrase(RenderingContext.QUEST_READONLY)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-readonly.png")))); } - if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) { - flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "StructureDefinition-sdc-questionnaire-isSubject.html"), null, context.formatPhrase(RenderingContext.QUEST_SUBJECT)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-subject.png")))); + if ("true".equals(i.extensionString("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject"))) { + status.setExtensions(true); + flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject", "StructureDefinition-sdc-questionnaire-isSubject.html"), null, context.formatPhrase(RenderingContext.QUEST_SUBJECT)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-subject.png")))); } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_HIDDEN)) { + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) { + status.setExtensions(true); flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-hidden.html"), null, context.formatPhrase(RenderingContext.QUEST_HIDDEN)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-hidden.png")))); } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_OTP_DISP)) { - flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay", "StructureDefinition-sdc-questionnaire-optionalDisplay.html"), null, context.formatPhrase(RenderingContext.QUEST_DISPLAY)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-optional.png")))); + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) { + status.setExtensions(true); + flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-optionalDisplay", "StructureDefinition-sdc-questionnaire-optionalDisplay.html"), null, context.formatPhrase(RenderingContext.QUEST_DISPLAY)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-optional.png")))); } - if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod")) { - flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", "StructureDefinition-sdc-questionnaire-observationLinkPeriod.html"), null, context.formatPhrase(RenderingContext.QUEST_LINKED)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-observation.png")))); + if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod")) { + status.setExtensions(true); + flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod", "StructureDefinition-sdc-questionnaire-observationLinkPeriod.html"), null, context.formatPhrase(RenderingContext.QUEST_LINKED)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-observation.png")))); } if (i.hasExtension(ToolingExtensions.EXT_Q_CHOICE_ORIENT)) { - String code = ToolingExtensions.readStringExtension(i, ToolingExtensions.EXT_Q_CHOICE_ORIENT); + status.setExtensions(true); + String code = i.extensionString(ToolingExtensions.EXT_Q_CHOICE_ORIENT); flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-choiceorientation.html"), null, context.formatPhrase(RenderingContext.QUEST_ORIENTATION, code)+" ").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-" + code + ".png")))); } if (i.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) { - CodeableConcept cc = i.getExtensionByUrl(ToolingExtensions.EXT_Q_DISPLAY_CAT).getValueCodeableConcept(); - String code = cc.getCode("http://hl7.org/fhir/questionnaire-display-category"); + status.setExtensions(true); + ResourceWrapper cc = i.extensionValue(ToolingExtensions.EXT_Q_DISPLAY_CAT); + String code = getCodeFromCC(cc, "http://hl7.org/fhir/questionnaire-display-category"); flags.addPiece(gen.new Piece("https://hl7.org/fhir/R4/extension-questionnaire-displayCategory.html", null, context.formatPhrase(RenderingContext.QUEST_CAT, code)+" ").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-" + code + ".png")))); } } Cell defn = gen.new Cell(); r.getCells().add(defn); - - if (i.hasMaxLength()) { + + if (i.has("maxLength")) { defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH)+" "), null)); - defn.getPieces().add(gen.new Piece(null, Integer.toString(i.getMaxLength()), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("maxLength"), null)); } - if (i.hasDefinition()) { + if (i.has("definition")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_DEFINITION_COLON)+" "), null)); genDefinitionLink(gen, i, defn, q); } - if (i.hasEnableWhen()) { + if (i.has("enableWhen")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); Piece p = gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_ENABLE)+" "), null); defn.getPieces().add(p); - if (i.getEnableWhen().size() == 1) { + if (i.children("enableWhen").size() == 1) { XhtmlNode x = new XhtmlNode(NodeType.Element, "span"); p.getChildren().add(x); - renderEnableWhen(x, i.getEnableWhenFirstRep()); + renderEnableWhen(x, i.firstChild("enableWhen")); } else { XhtmlNode x = new XhtmlNode(NodeType.Element, "ul"); p.getChildren().add(x); - for (QuestionnaireItemEnableWhenComponent qi : i.getEnableWhen()) { + for (ResourceWrapper qi : i.children("enableWhen")) { renderEnableWhen(x.li(), qi); } } } - if (i.hasAnswerValueSet()) { + if (i.has("answerValueSet")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_VALUE)+" "), null)); - if (!Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) { - ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)); + if (i.hasPrimitiveValue("answerValueSet") && i.primitiveValue("answerValueSet").startsWith("#")) { + ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1)); if (vs == null) { - defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null)); } else { - defn.getPieces().add(gen.new Piece(vs.getWebPath(), vs.present(), null)); + defn.getPieces().add(gen.new Piece(vs.getWebPath(), RendererFactory.factory(vs, context.forContained()).buildSummary(vs), null)); } } else { - ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.getAnswerValueSet(), q); + ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet")); if (vs == null || !vs.hasWebPath()) { - defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null)); } else { defn.getPieces().add(gen.new Piece(vs.getWebPath(), vs.present(), null)); } } } - if (i.hasAnswerOption()) { + if (i.has("answerOption")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_OPTIONS)+" "), null)); if (context.getDefinitionsTarget() == null) { // if we don't have a definitions target, we'll add them below. - defn.getPieces().add(gen.new Piece("#opt-item."+i.getLinkId(), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), null)); + defn.getPieces().add(gen.new Piece("#opt-item."+i.primitiveValue("linkId"), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), null)); } else { - defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.getLinkId(), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), null)); + defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), null)); } } - if (i.hasInitial()) { - for (QuestionnaireItemInitialComponent v : i.getInitial()) { + if (i.has("initial")) { + for (ResourceWrapper v : i.children("initial")) { + ResourceWrapper vv = v.child("value"); if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_INITIAL)+" "), null)); - defn.getPieces().add(gen.new Piece(null, v.getValue().fhirType(), null)); - defn.getPieces().add(gen.new Piece(null, " = ", null)); - if (v.getValue().isPrimitive()) { - defn.getPieces().add(gen.new Piece(null, v.getValue().primitiveValue(), null)); - } else if (v.hasValueCoding()) { - renderCoding(gen, defn.getPieces(), v.getValueCoding()); - } else if (v.hasValueQuantity()) { - renderQuantity(gen, defn.getPieces(), v.getValueQuantity(), false); - } else if (v.hasValueReference()) { - renderReference(q, gen, defn.getPieces(), v.getValueReference(), true); - } else if (v.hasValueAttachment()) { - // renderAttachment(gen, defn.getPieces(), v.getValueAttachment()); + defn.getPieces().add(gen.new Piece(null, vv.fhirType(), null)); + defn.getPieces().add(gen.new Piece(null, " = ", null)); + if (vv.isPrimitive()) { + defn.getPieces().add(gen.new Piece(null, vv.primitiveValue(), null)); + } else if (vv.fhirType().equals("Coding")) { + renderCoding(gen, defn.getPieces(), vv); + } else if (vv.fhirType().equals("Quantity")) { + renderQuantity(gen, defn.getPieces(), vv, false); + } else if (vv.fhirType().equals("Reference")) { + renderReference(q, gen, defn.getPieces(), vv, true); + } else if (vv.fhirType().equals("Attachment")) { + // renderAttachment(gen, defn.getPieces(), vv); } } } // still todo - -// -//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-choiceColumn -// -//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-width -//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod -//http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl -//http://hl7.org/fhir/StructureDefinition/questionnaire-sliderStepValue - - if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression")) { + + // + //http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-choiceColumn + // + //http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-width + //http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod + //http://hl7.org/fhir/StructureDefinition/Questionnaire-itemControl + //http://hl7.org/fhir/StructureDefinition/Questionnaire-sliderStepValue + + if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_EXP)+" "), null)); Piece p = gen.new Piece("ul"); defn.getPieces().add(p); - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_INT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_INT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_ITEM_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_ITEM_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_EN), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_EN), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_CALC), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CALC), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_CAND), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CAND), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression"); } } - - for (QuestionnaireItemComponent c : i.getItem()) { - hasExt = renderTreeItem(gen, r.getSubRows(), q, c, hasFlags) || hasExt; - } - return hasExt; + + for (ResourceWrapper c : i.children("item")) { + renderTreeItem(status, gen, r.getSubRows(), q, c, hasFlags); + } } - - public void genDefinitionLink(HierarchicalTableGenerator gen, QuestionnaireItemComponent i, Cell defn, Questionnaire q) { + + private String getCodeFromCC(ResourceWrapper cc, String system) { + for (ResourceWrapper coding : cc.children("coding")) { + if (system.equals(coding.primitiveValue("system"))) { + return coding.primitiveValue("code"); + } + } + return null; + + } + + public void genDefinitionLink(HierarchicalTableGenerator gen, ResourceWrapper i, Cell defn, ResourceWrapper q) { // can we resolve the definition? String path = null; - String d = i.getDefinition(); + String d = i.primitiveValue("definition"); if (d.contains("#")) { path = d.substring(d.indexOf("#")+1); d = d.substring(0, d.indexOf("#")); } - StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q); + StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q.getResourceNative()); if (sd != null) { String url = sd.getWebPath(); if (url != null) { defn.getPieces().add(gen.new Piece(url+"#"+path, path, null)); } else { - defn.getPieces().add(gen.new Piece(null, i.getDefinition(), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("definition"), null)); } } else { - defn.getPieces().add(gen.new Piece(null, i.getDefinition(), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("definition"), null)); } } - - public void genDefinitionLink(XhtmlNode x, QuestionnaireItemComponent i, Questionnaire q) { + + public void genDefinitionLink(XhtmlNode x, ResourceWrapper i, ResourceWrapper q) { // can we resolve the definition? String path = null; - String d = i.getDefinition(); + String d = i.primitiveValue("definition"); if (d.contains("#")) { path = d.substring(d.indexOf("#")+1); d = d.substring(0, d.indexOf("#")); } - StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q); + StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q.getResourceNative()); if (sd != null) { String url = sd.getWebPath(); if (url != null) { x.ah(url+"#"+path).tx(path); } else { - x.tx(i.getDefinition()); + x.tx(i.primitiveValue("definition")); } } else { - x.tx(i.getDefinition()); + x.tx(i.primitiveValue("definition")); } } - - private void addExpression(Piece p, Expression exp, String label, String url) { + + private void addExpression(Piece p, ResourceWrapper exp, String label, String url) { XhtmlNode x = new XhtmlNode(NodeType.Element, "li").style("font-size: 11px"); p.addHtml(x); CanonicalResource cr = (CanonicalResource) context.getContext().fetchResource(Resource.class, url); @@ -456,10 +489,10 @@ public class QuestionnaireRenderer extends TerminologyRenderer { x.ah(url).tx(label); } x.tx(": "); - x.code(exp.getExpression()); + x.code(exp.primitiveValue("expression")); } - - private boolean renderLogic(XhtmlNode x, Questionnaire q) throws FHIRException, IOException { + + private void renderLogic(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRException, IOException { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true); TableModel model = gen.new TableModel("qtree="+q.getId(), true); model.setAlternating(true); @@ -471,158 +504,154 @@ public class QuestionnaireRenderer extends TerminologyRenderer { model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_LINKID), context.formatPhrase(RenderingContext.QUEST_LINK), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_DESC_CONST), context.formatPhrase(RenderingContext.QUEST_ADD_INFO), null, 0)); - - boolean hasExt = false; - if (!q.hasItem()) { + + if (!q.has("item")) { gen.emptyRow(model, 2); } else { - for (QuestionnaireItemComponent i : q.getItem()) { - hasExt = renderLogicItem(gen, model.getRows(), q, i) || hasExt; + for (ResourceWrapper i : q.children("item")) { + renderLogicItem(status, gen, model.getRows(), q, i); } } XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); x.getChildNodes().add(xn); - return hasExt; } - - private boolean renderLogicItem(HierarchicalTableGenerator gen, List rows, Questionnaire q, QuestionnaireItemComponent i) throws IOException { + + private void renderLogicItem(RenderingStatus status, HierarchicalTableGenerator gen, List rows, ResourceWrapper q, ResourceWrapper i) throws IOException { Row r = gen.new Row(); rows.add(r); - boolean hasExt = false; - - r.setIcon("icon-q-"+i.getType().toCode().toLowerCase()+".png", i.getType().getDisplay()); - r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.getLinkId(), i.getLinkId(), null, null)); + String type = i.primitiveValue("type"); + + r.setIcon("icon-q-"+type.toLowerCase()+".png", type); + r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), i.primitiveValue("linkId"), null, null)); Cell defn = gen.new Cell(); r.getCells().add(defn); - - if (i.hasMaxLength()) { + + if (i.has("maxLength")) { defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH)+" "), null)); - defn.getPieces().add(gen.new Piece(null, Integer.toString(i.getMaxLength()), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("maxLength"), null)); } - if (i.hasDefinition()) { + if (i.has("definition")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_DEFINITION_COLON)+" "), null)); genDefinitionLink(gen, i, defn, q); } - if (i.hasEnableWhen()) { + if (i.has("enableWhen")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_ENABLE)+" "), null)); defn.getPieces().add(gen.new Piece(null, context.formatPhrase(RenderingContext.GENERAL_TODO), null)); } - if (i.hasAnswerValueSet()) { + if (i.has("answerValueSet")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_VALUE)+" "), null)); - if (Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) { - ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)); + if (Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) { + ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1)); if (vs == null) { - defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null)); } else { - defn.getPieces().add(gen.new Piece(vs.getWebPath(), vs.present(), null)); + defn.getPieces().add(gen.new Piece(vs.getWebPath(), RendererFactory.factory(vs, context.forContained()).buildSummary(vs), null)); } } else { - ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.getAnswerValueSet(), q); + ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"), q.getResourceNative()); if (vs == null || !vs.hasWebPath()) { - defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null)); + defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null)); } else { defn.getPieces().add(gen.new Piece(vs.getWebPath(), vs.present(), null)); } } } - if (i.hasAnswerOption()) { + if (i.has("answerOption")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_OPTIONS)+" "), null)); - defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.getLinkId(), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), null)); + defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), null)); } - if (i.hasInitial()) { - for (QuestionnaireItemInitialComponent v : i.getInitial()) { - if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); + if (i.has("initial")) { + for (ResourceWrapper v : i.children("initial")) { + if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); + ResourceWrapper vv = v.child("value"); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_INITIAL)+" "), null)); - defn.getPieces().add(gen.new Piece(null, v.getValue().fhirType(), null)); + defn.getPieces().add(gen.new Piece(null, vv.fhirType(), null)); defn.getPieces().add(gen.new Piece(null, " = ", null)); - if (v.getValue().isPrimitive()) { - defn.getPieces().add(gen.new Piece(null, v.getValue().primitiveValue(), null)); - } else if (v.hasValueCoding()) { - renderCoding(gen, defn.getPieces(), v.getValueCoding()); - } else if (v.hasValueQuantity()) { - renderQuantity(gen, defn.getPieces(), v.getValueQuantity(), false); - } else if (v.hasValueReference()) { - renderReference(q, gen, defn.getPieces(), v.getValueReference(), false); -// } else if (v.hasValueAttachment()) { -// renderAttachment(gen, defn.getPieces(), v.getValueAttachment()); + if (vv.isPrimitive()) { + defn.getPieces().add(gen.new Piece(null, vv.primitiveValue(), null)); + } else if (vv.fhirType().equals("Coding")) { + renderCoding(gen, defn.getPieces(), vv); + } else if (vv.fhirType().equals("Coding")) { + renderQuantity(gen, defn.getPieces(), vv, false); + } else if (vv.fhirType().equals("Coding")) { + renderReference(q, gen, defn.getPieces(), vv, false); + // } else if (v.hasValueAttachment()) { + // renderAttachment(gen, defn.getPieces(), v.getValueAttachment()); } } } // still todo - -// -//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-choiceColumn -// -//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-width -//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod -//http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl -//http://hl7.org/fhir/StructureDefinition/questionnaire-sliderStepValue - - if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression")) { + + // + //http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-choiceColumn + // + //http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-width + //http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod + //http://hl7.org/fhir/StructureDefinition/Questionnaire-itemControl + //http://hl7.org/fhir/StructureDefinition/Questionnaire-sliderStepValue + + if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) { if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_EXP)+" "), null)); Piece p = gen.new Piece("ul"); defn.getPieces().add(p); - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_INT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_INT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_ITEM_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_ITEM_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_EN), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_EN), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_CALC), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CALC), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression"); } - for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression")) { - addExpression(p, e.getValueExpression(), context.formatPhrase(RenderingContext.QUEST_CAND), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression"); + for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression")) { + addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CAND), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression"); } } - - for (QuestionnaireItemComponent c : i.getItem()) { - hasExt = renderLogicItem(gen, r.getSubRows(), q, c) || hasExt; - } - return hasExt; - + + for (ResourceWrapper c : i.children("item")) { + renderLogicItem(status, gen, r.getSubRows(), q, c); + } + } - - - public boolean renderForm(XhtmlNode x, Questionnaire q) throws UnsupportedEncodingException, IOException { - boolean hasExt = false; + + + public void renderForm(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws UnsupportedEncodingException, IOException { XhtmlNode d = x.div(); boolean hasPrefix = false; - for (QuestionnaireItemComponent c : q.getItem()) { + for (ResourceWrapper c : q.children("item")) { hasPrefix = hasPrefix || doesItemHavePrefix(c); } int i = 1; - for (QuestionnaireItemComponent c : q.getItem()) { - hasExt = renderFormItem(d, q, c, hasPrefix ? null : Integer.toString(i), 0) || hasExt; + for (ResourceWrapper c : q.children("item")) { + renderFormItem(status, d, q, c, hasPrefix ? null : Integer.toString(i), 0); i++; - } - return hasExt; + } } - - private boolean doesItemHavePrefix(QuestionnaireItemComponent i) { - if (i.hasPrefix()) { + + private boolean doesItemHavePrefix(ResourceWrapper i) { + if (i.has("prefix")) { return true; } - for (QuestionnaireItemComponent c : i.getItem()) { + for (ResourceWrapper c : i.children("item")) { if (doesItemHavePrefix(c)) { return true; } } return false; } - - private boolean renderFormItem(XhtmlNode x, Questionnaire q, QuestionnaireItemComponent i, String pfx, int indent) throws IOException { + + private void renderFormItem(RenderingStatus status, XhtmlNode x, ResourceWrapper q, ResourceWrapper i, String pfx, int indent) throws IOException { boolean hasExt = false; XhtmlNode d = x.div().style("width: "+Integer.toString(900-indent*10)+"px; border-top: 1px #eeeeee solid"); if (indent > 0) { @@ -631,214 +660,218 @@ public class QuestionnaireRenderer extends TerminologyRenderer { XhtmlNode display = d.div().style("display: inline-block; width: "+Integer.toString(500-indent*10)+"px"); XhtmlNode details = d.div().style("border: 1px #ccccff solid; padding: 2px; display: inline-block; background-color: #fefce7; width: 380px"); XhtmlNode p = display.para(); - if (i.getType() == QuestionnaireItemType.GROUP) { + + String type = i.primitiveValue("type"); + String typeT = getTranslatedCode(i.child("type")); + if ("group".equals(type)) { p = p.b(); } - if (i.hasPrefix()) { - p.tx(i.getPrefix()); + if (i.has("prefix")) { + p.tx(i.primitiveValue("prefix")); p.tx(": "); } - p.span(null, "linkId: "+i.getLinkId()).tx(i.getText()); - if (i.getRequired()) { + p.span(null, "linkId: "+i.primitiveValue("linkId")).tx(i.primitiveValue("text")); + if ("true".equals(i.primitiveValue("required"))) { p.span("color: red", context.formatPhrase(RenderingContext.QUEST_MAND)).tx("*"); } - + XhtmlNode input = null; - switch (i.getType()) { - case STRING: + switch (type) { + case "string": p.tx(" "); - input = p.input(i.getLinkId(), "text", i.getType().getDisplay(), 60); + input = p.input(i.primitiveValue("linkId"), "text", typeT, 60); break; - case ATTACHMENT: + case "attachment": break; - case BOOLEAN: + case "boolean": p.tx(" "); - input = p.input(i.getLinkId(), "checkbox", i.getType().getDisplay(), 1); + input = p.input(i.primitiveValue("linkId"), "checkbox", typeT, 1); break; - case CODING: - input = p.select(i.getLinkId()); + case "coding": + input = p.select(i.primitiveValue("linkId")); listOptions(q, i, input); break; - case DATE: + case "date": p.tx(" "); - input = p.input(i.getLinkId(), "date", i.getType().getDisplay(), 10); + input = p.input(i.primitiveValue("linkId"), "date", typeT, 10); break; - case DATETIME: + case "dateTime": p.tx(" "); - input = p.input(i.getLinkId(), "datetime-local", i.getType().getDisplay(), 25); + input = p.input(i.primitiveValue("linkId"), "datetime-local", typeT, 25); break; - case DECIMAL: + case "decimal": p.tx(" "); - input = p.input(i.getLinkId(), "number", i.getType().getDisplay(), 15); + input = p.input(i.primitiveValue("linkId"), "number", typeT, 15); break; - case DISPLAY: + case "display": break; - case GROUP: - + case "group": break; - case INTEGER: + case "integer": p.tx(" "); - input = p.input(i.getLinkId(), "number", i.getType().getDisplay(), 10); + input = p.input(i.primitiveValue("linkId"), "number", typeT, 10); break; - case QUANTITY: + case "qantity": p.tx(" "); - input = p.input(i.getLinkId(), "number", "value", 15); + input = p.input(i.primitiveValue("linkId"), "number", "value", 15); p.tx(" "); - input = p.input(i.getLinkId(), "unit", "unit", 10); + input = p.input(i.primitiveValue("linkId"), "unit", "unit", 10); break; - case QUESTION: + case "question": break; - case REFERENCE: + case "reference": break; - case TEXT: + case "text": break; - case TIME: + case "time": break; - case URL: + case "url": break; default: break; } if (input != null) { - if (i.getReadOnly()) { + if ("true".equals(i.primitiveValue("readOnly"))) { input.attribute("readonly", "1"); input.style("background-color: #eeeeee"); } } - -// if (i.hasExtension(ToolingExtensions.EXT_Q_CHOICE_ORIENT)) { -// String code = ToolingExtensions.readStringExtension(i, ToolingExtensions.EXT_Q_CHOICE_ORIENT); -// flags.addPiece(gen.new Piece("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png")))); -//} - - + + // if (i.hasExtension(ToolingExtensions.EXT_Q_CHOICE_ORIENT)) { + // String code = ToolingExtensions.readStringExtension(i, ToolingExtensions.EXT_Q_CHOICE_ORIENT); + // flags.addPiece(gen.new Piece("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod", null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png")))); + //} + + XhtmlNode ul = details.ul(); boolean hasFlag = false; XhtmlNode flags = item(ul, "Flags"); - item(ul, "linkId", i.getLinkId()); - - if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) { + item(ul, "linkId", i.primitiveValue("linkId")); + + if ("true".equals(i.extensionString("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject"))) { hasFlag = true; - flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "StructureDefinition-sdc-questionnaire-isSubject.html"), context.formatPhrase(RenderingContext.QUEST_SUBJECT)).img(getImgPath("icon-qi-subject.png"), "icon"); + flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject", "StructureDefinition-sdc-questionnaire-isSubject.html"), context.formatPhrase(RenderingContext.QUEST_SUBJECT)).img(getImgPath("icon-qi-subject.png"), "icon"); } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_HIDDEN)) { + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) { hasFlag = true; flags.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "extension-questionnaire-hidden.html"), context.formatPhrase(RenderingContext.QUEST_HIDDEN)).img(getImgPath("icon-qi-hidden.png"), "icon"); d.style("background-color: #eeeeee"); } - if (ToolingExtensions.readBoolExtension(i, ToolingExtensions.EXT_Q_OTP_DISP)) { + if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) { hasFlag = true; - flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay", "StructureDefinition-sdc-questionnaire-optionalDisplay.html"), context.formatPhrase(RenderingContext.QUEST_DISPLAY)).img(getImgPath("icon-qi-optional.png"), "icon"); + flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-optionalDisplay", "StructureDefinition-sdc-questionnaire-optionalDisplay.html"), context.formatPhrase(RenderingContext.QUEST_DISPLAY)).img(getImgPath("icon-qi-optional.png"), "icon"); } - if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod")) { + if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod")) { hasFlag = true; - flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", "StructureDefinition-sdc-questionnaire-observationLinkPeriod.html"), context.formatPhrase(RenderingContext.QUEST_LINKED)).img(getImgPath("icon-qi-observation.png"), "icon"); + flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod", "StructureDefinition-sdc-questionnaire-observationLinkPeriod.html"), context.formatPhrase(RenderingContext.QUEST_LINKED)).img(getImgPath("icon-qi-observation.png"), "icon"); } if (i.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) { - CodeableConcept cc = i.getExtensionByUrl(ToolingExtensions.EXT_Q_DISPLAY_CAT).getValueCodeableConcept(); - String code = cc.getCode("http://hl7.org/fhir/questionnaire-display-category"); + ResourceWrapper cc = i.extension(ToolingExtensions.EXT_Q_DISPLAY_CAT).child("value"); + String code = getCodeFromCC(cc, "http://hl7.org/fhir/questionnaire-display-category"); hasFlag = true; flags.ah("https://hl7.org/fhir/R4/extension-questionnaire-displayCategory.html", (context.formatPhrase(RenderingContext.QUEST_CAT, code)+" ")).img(getImgPath("icon-qi-" + code + ".png"), "icon"); } - - if (i.hasMaxLength()) { - item(ul, context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH), Integer.toString(i.getMaxLength())); + + if (i.has("maxLength")) { + item(ul, context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH), i.primitiveValue("maxLength")); } - if (i.hasDefinition()) { + if (i.has("definition")) { genDefinitionLink(item(ul, context.formatPhrase(RenderingContext.GENERAL_DEFINITION_COLON)), i, q); } - if (i.hasEnableWhen()) { + if (i.has("enableWhen")) { item(ul, context.formatPhrase(RenderingContext.QUEST_EN), "todo"); } - if (i.hasAnswerValueSet()) { + if (i.has("answerValueSet")) { XhtmlNode ans = item(ul, context.formatPhrase(RenderingContext.QUEST_ANSWERS)); - if (!Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) { - ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)); - if (vs == null || !vs.hasWebPath()) { - ans.tx(i.getAnswerValueSet()); + if (!Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) { + ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1)); + if (vs == null) { + ans.tx(i.primitiveValue("answerValueSet")); + } else if (vs.getWebPath() == null) { + ans.ah(context.prefixLocalHref("#hc"+vs.getScopedId())).tx(RendererFactory.factory(vs, context.forContained()).buildSummary(vs)); } else { - ans.ah(vs.getWebPath()).tx(vs.present()); + ans.ah(context.prefixLocalHref(vs.getWebPath())).tx(RendererFactory.factory(vs, context.forContained()).buildSummary(vs)); } } else { - ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.getAnswerValueSet(), q); + ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"), q.getResourceNative()); if (vs == null || !vs.hasWebPath()) { - ans.tx(i.getAnswerValueSet()); + ans.tx(i.primitiveValue("answerValueSet")); } else { ans.ah(vs.getWebPath()).tx(vs.present()); } } } - if (i.hasAnswerOption()) { - item(ul, context.formatPhrase(RenderingContext.QUEST_ANSWERS), Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), context.getDefinitionsTarget()+"#item."+i.getLinkId()); + if (i.has("answerOption")) { + item(ul, context.formatPhrase(RenderingContext.QUEST_ANSWERS), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId")); } - if (i.hasInitial()) { + if (i.has("initial")) { XhtmlNode vi = item(ul, context.formatPhrase(RenderingContext.QUEST_INT)); boolean first = true; - for (QuestionnaireItemInitialComponent v : i.getInitial()) { + for (ResourceWrapper v : i.children("initial")) { if (first) first = false; else vi.tx(", "); - if (v.getValue().isPrimitive()) { - vi.tx(v.getValue().primitiveValue()); - } else if (v.hasValueCoding()) { - renderCoding(vi, v.getValueCoding(), true); - } else if (v.hasValueReference()) { - renderReference(vi, v.getValueReference()); - } else if (v.hasValueQuantity()) { - renderQuantity(vi, v.getValueQuantity()); -// } else if (v.hasValueAttachment()) { -// renderAttachment(vi, v.getValueAttachment()); + ResourceWrapper vv = v.child("value"); + if (vv.isPrimitive()) { + vi.tx(vv.primitiveValue()); + } else if (vv.fhirType().equals("Coding")) { + renderCoding(status, vi, vv); + } else if (vv.fhirType().equals("Reference")) { + renderReference(status, vi, vv); + } else if (vv.fhirType().equals("Quantity")) { + renderQuantity(status, vi, vv); + // } else if (v.hasValueAttachment()) { + // renderAttachment(vi, v.getValueAttachment()); } } } if (!hasFlag) { ul.remove(flags); } -// if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression")) { -// if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); -// defn.getPieces().add(gen.new Piece(null, "Expressions: ", null)); -// Piece p = gen.new Piece("ul"); -// defn.getPieces().add(p); -// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression")) { -// addExpression(p, e.getValueExpression(), "Initial Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression"); -// } -// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression")) { -// addExpression(p, e.getValueExpression(), "Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-contextExpression"); -// } -// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext")) { -// addExpression(p, e.getValueExpression(), "Item Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemContext"); -// } -// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression")) { -// addExpression(p, e.getValueExpression(), "Enable When", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression"); -// } -// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression")) { -// addExpression(p, e.getValueExpression(), "Calculated Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression"); -// } -// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression")) { -// addExpression(p, e.getValueExpression(), "Candidates", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-candidateExpression"); -// } -// } -// - + // if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) { + // if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); + // defn.getPieces().add(gen.new Piece(null, "Expressions: ", null)); + // Piece p = gen.new Piece("ul"); + // defn.getPieces().add(p); + // for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) { + // addExpression(p, e.getValueExpression(), "Initial Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression"); + // } + // for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression")) { + // addExpression(p, e.getValueExpression(), "Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression"); + // } + // for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext")) { + // addExpression(p, e.getValueExpression(), "Item Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext"); + // } + // for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression")) { + // addExpression(p, e.getValueExpression(), "Enable When", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression"); + // } + // for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression")) { + // addExpression(p, e.getValueExpression(), "Calculated Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression"); + // } + // for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression")) { + // addExpression(p, e.getValueExpression(), "Candidates", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression"); + // } + // } + // + int t = 1; - for (QuestionnaireItemComponent c : i.getItem()) { - hasExt = renderFormItem(x, q, c, pfx == null ? null : pfx+"."+Integer.toString(t), indent+1) || hasExt; + for (ResourceWrapper c : i.children("item")) { + renderFormItem(status, x, q, c, pfx == null ? null : pfx+"."+Integer.toString(t), indent+1); t++; - } - return hasExt; + } } - + @Nonnull private String getImgPath(String code) throws IOException { - return context.getLocalPrefix().length() > 0 + return context.getLocalPrefix().length() > 0 ? Utilities.path(context.getLocalPrefix(), code) - : Utilities.path(code); + : Utilities.path(code); } - + private void item(XhtmlNode ul, String name, String value, String valueLink) { if (!Utilities.noString(value)) { - ul.li().style("font-size: 10px").ah(valueLink).tx(name+": "+value); + ul.li().style("font-size: 10px").ah(context.prefixLocalHref(valueLink)).tx(name+": "+value); } } - + private void item(XhtmlNode ul, String name, String value) { if (!Utilities.noString(value)) { ul.li().style("font-size: 10px").tx(name+": "+value); @@ -849,19 +882,20 @@ public class QuestionnaireRenderer extends TerminologyRenderer { li.style("font-size: 10px").tx(name+": "); return li; } - - - private void listOptions(Questionnaire q, QuestionnaireItemComponent i, XhtmlNode select) { - if (i.hasAnswerValueSet()) { + + + private void listOptions(ResourceWrapper q, ResourceWrapper i, XhtmlNode select) { + if (i.has("answerValueSet")) { ValueSet vs = null; - if (!Utilities.noString(i.getAnswerValueSet()) && i.getAnswerValueSet().startsWith("#")) { - vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)); + if (!Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) { + ResourceWrapper contained = q.getContained(i.primitiveValue("answerValueSet").substring(1)); + vs = contained == null ? null : (ValueSet) contained.getResourceNative(); if (vs != null && !vs.hasUrl()) { vs = vs.copy(); - vs.setUrl(q.getUrl()+"--"+q.getContained(i.getAnswerValueSet().substring(1))); + vs.setUrl(q.primitiveValue("url")+"--"+contained); } } else { - vs = context.getContext().findTxResource(ValueSet.class, i.getAnswerValueSet(), q); + vs = context.getContext().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"), q.getResourceNative()); } if (vs != null) { ValueSetExpansionOutcome exp = context.getContext().expandVS(vs, true, false); @@ -872,240 +906,227 @@ public class QuestionnaireRenderer extends TerminologyRenderer { return; } } - } else if (i.hasAnswerOption()) { + } else if (i.has("answerOption")) { renderItemOptions(select, i); } select.option("a", "??", false); } - - public String display(Resource dr) throws UnsupportedEncodingException, IOException { - return display((Questionnaire) dr); - } - - public String display(Questionnaire q) throws UnsupportedEncodingException, IOException { - return context.formatPhrase(RenderingContext.QUEST_QUESTIONNAIRE, q.present())+" "; - } - - private boolean renderLinks(XhtmlNode x, Questionnaire q) { + + private void renderLinks(RenderingStatus status, XhtmlNode x, ResourceWrapper q) { x.para().tx(context.formatPhrase(RenderingContext.QUEST_TRY)); XhtmlNode ul = x.ul(); ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(context.formatPhrase(RenderingContext.QUEST_NLM)); - return false; } - - private boolean renderDefns(XhtmlNode x, Questionnaire q) throws IOException { + + private void renderDefns(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws IOException { XhtmlNode tbl = x.table("dict"); - boolean ext = false; - ext = renderRootDefinition(tbl, q, new ArrayList<>()) || ext; - for (QuestionnaireItemComponent qi : q.getItem()) { - ext = renderDefinition(tbl, q, qi, new ArrayList<>()) || ext; + renderRootDefinition(status, tbl, q, new ArrayList<>()); + for (ResourceWrapper qi : q.children("item")) { + renderDefinition(status, tbl, q, qi, new ArrayList<>()); } - return ext; } - - private boolean renderRootDefinition(XhtmlNode tbl, Questionnaire q, List parents) throws IOException { + + private void renderRootDefinition(RenderingStatus status, XhtmlNode tbl, ResourceWrapper q, List parents) throws IOException { boolean ext = false; XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent"); - td.an(q.getId()); + td.an(context.prefixAnchor(q.getId())); td.img(getImgPath("icon_q_root.gif"), "icon"); td.tx(" "+(context.formatPhrase(RenderingContext.QUEST_QUEST)+" ")); td.b().tx(q.getId()); - + // general information - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_URL), q.getUrl()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_VER), q.getVersion()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_NAME), q.getName()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_TITLE), q.getTitle()); - if (q.hasDerivedFrom()) { + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_URL), q.primitiveValue("url")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_VER), q.primitiveValue("version")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_NAME), q.primitiveValue("name")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_TITLE), q.primitiveValue("title")); + if (q.has("derivedFrom")) { td = defn(tbl, context.formatPhrase(RenderingContext.QUEST_DERIVED)); boolean first = true; - for (CanonicalType c : q.getDerivedFrom()) { + for (ResourceWrapper c : q.children("derivedFrom")) { if (first) first = false; else td.tx(", "); - td.tx(c.asStringValue()); // todo: make these a reference + td.tx(c.primitiveValue()); // todo: make these a reference } } - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_STATUS), q.getStatus().getDisplay()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_EXPER), q.getExperimental()); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_PUB), q.getDateElement().primitiveValue()); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_APP), q.getApprovalDateElement().primitiveValue()); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_REV_DATE), q.getLastReviewDateElement().primitiveValue()); - if (q.hasEffectivePeriod()) { - renderPeriod(defn(tbl, context.formatPhrase(RenderingContext.QUEST_EFF_PERIOD)), q.getEffectivePeriod()); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_STATUS), q.primitiveValue("status")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_EXPER), q.primitiveValue("experimental")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_PUB), q.primitiveValue("date")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_APP), q.primitiveValue("approvalDate")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_REV_DATE), q.primitiveValue("lastReviewDate")); + if (q.has("effectivePeriod")) { + renderPeriod(status, defn(tbl, context.formatPhrase(RenderingContext.QUEST_EFF_PERIOD)), q.child("effectivePeriod")); } - - if (q.hasSubjectType()) { + + if (q.has("subjectType")) { td = defn(tbl, context.formatPhrase(RenderingContext.QUEST_SUB_TYPE)); boolean first = true; - for (CodeType c : q.getSubjectType()) { + for (ResourceWrapper c : q.children("subjectType")) { if (first) first = false; else td.tx(", "); - td.tx(c.asStringValue()); + td.tx(c.primitiveValue()); } } - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DESC), q.getDescription()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_PURPOSE), q.getPurpose()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_COPYRIGHT), q.getCopyright()); - if (q.hasCode()) { - td = defn(tbl, Utilities.pluralize("Code", q.getCode().size())); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DESC), q.primitiveValue("description")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_PURPOSE), q.primitiveValue("purpose")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_COPYRIGHT), q.primitiveValue("copyright")); + if (q.has("code")) { + td = defn(tbl, Utilities.pluralize("Code", q.children("code").size())); boolean first = true; - for (Coding c : q.getCode()) { + for (ResourceWrapper c : q.children("code")) { if (first) first = false; else td.tx(", "); - renderCodingWithDetails(td, c); + renderCodingWithDetails(status, td, c); } } - return false; } - - private boolean renderDefinition(XhtmlNode tbl, Questionnaire q, QuestionnaireItemComponent qi, List parents) throws IOException { - boolean ext = false; + + private void renderDefinition(RenderingStatus status, XhtmlNode tbl, ResourceWrapper q, ResourceWrapper qi, List parents) throws IOException { XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent"); - td.an("item."+qi.getLinkId()); - for (QuestionnaireItemComponent p : parents) { - td.ah("#item."+p.getLinkId()).img(getImgPath("icon_q_item.png"), "icon"); + td.an(context.prefixAnchor("item."+qi.primitiveValue("linkId"))); + for (ResourceWrapper p : parents) { + td.ah(context.prefixLocalHref("#item."+p.primitiveValue("linkId"))).img(getImgPath("icon_q_item.png"), "icon"); td.tx(" > "); } td.img(getImgPath("icon_q_item.png"), "icon"); td.tx(" Item "); - td.b().tx(qi.getLinkId()); - + td.b().tx(qi.primitiveValue("linkId")); + String type = qi.primitiveValue("type"); + // general information - defn(tbl, context.formatPhrase(RenderingContext.QUEST_ID), qi.getLinkId()); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_PREFIX), qi.getPrefix()); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_TEXT), qi.getText()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_TYPE), qi.getType().getDisplay()); - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_REQUIRED), qi.getRequired(), true); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_REP), qi.getRepeats(), true); - defn(tbl, context.formatPhrase(RenderingContext.QUEST_READ_ONLY), qi.getReadOnly(), false); - if (ToolingExtensions.readBoolExtension(qi, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) { - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_SUBJ), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "This element changes who the subject of the question is", null); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_ID), qi.primitiveValue("linkId")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_PREFIX), qi.primitiveValue("prefix")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_TEXT), qi.primitiveValue("text")); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_TYPE), type); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_REQUIRED), qi.primitiveValue("required")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_REP), qi.primitiveValue("repeats")); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_READ_ONLY), qi.primitiveValue("readOnly")); + if ("true".equals(qi.extensionString("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject"))) { + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_SUBJ), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject", "This element changes who the subject of the question is", null); } - + // content control - defn(tbl, context.formatPhrase(RenderingContext.QUEST_MAX_LENGTH), qi.getMaxLength()); - if (qi.hasAnswerValueSet()) { - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_VALUESET), qi.getDefinition(), context.getWorker().findTxResource(ValueSet.class, qi.getAnswerValueSet(), q)); + defn(tbl, context.formatPhrase(RenderingContext.QUEST_MAX_LENGTH), qi.primitiveValue("maxLength")); + if (qi.has("answerValueSet")) { + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_VALUESET), qi.primitiveValue("definition"), context.getWorker().findTxResource(ValueSet.class, qi.primitiveValue("answerValueSet"), q.getResourceNative())); } - if (qi.hasAnswerOption()) { + if (qi.has("answerOption")) { XhtmlNode tr = tbl.tr(); tr.td().tx(context.formatPhrase(RenderingContext.QUEST_ALLOWED)); XhtmlNode ul = tr.td().ul(); - for (QuestionnaireItemAnswerOptionComponent ans : qi.getAnswerOption()) { + for (ResourceWrapper ans : qi.children("answerOption")) { XhtmlNode li = ul.li(); - render(li, ans.getValue()); - if (ans.getInitialSelected()) { + renderDataType(status, li, ans.child("value")); + if ("true".equals(ans.primitiveValue("initialSelected"))) { li.tx(" "+(context.formatPhrase(RenderingContext.QUEST_INITIALLY))); } } } - if (qi.hasInitial()) { + if (qi.has("initial")) { XhtmlNode tr = tbl.tr(); - tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.QUEST_INITIAL_ANSWER)), qi.getInitial().size())); - if (qi.getInitial().size() == 1) { - render(tr.td(), qi.getInitialFirstRep().getValue()); + tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.QUEST_INITIAL_ANSWER)), qi.children("initial").size())); + if (qi.children("initial").size() == 1) { + renderDataType(status, tr.td(), qi.firstChild("initial").child("value")); } else { XhtmlNode ul = tr.td().ul(); - for (QuestionnaireItemInitialComponent ans : qi.getInitial()) { + for (ResourceWrapper ans : qi.children("initial")) { XhtmlNode li = ul.li(); - render(li, ans.getValue()); + renderDataType(status, li, ans.child("value")); } } } - + // appearance if (qi.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) { XhtmlNode tr = tbl.tr(); tr.td().ah(ToolingExtensions.EXT_Q_DISPLAY_CAT).tx("Display Category"); - render(tr.td(), qi.getExtensionByUrl(ToolingExtensions.EXT_Q_DISPLAY_CAT).getValue()); + renderDataType(status, tr.td(), qi.extension(ToolingExtensions.EXT_Q_DISPLAY_CAT).child("value")); } - if (ToolingExtensions.readBoolExtension(qi, ToolingExtensions.EXT_Q_HIDDEN)) { + if ("true".equals(qi.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) { defn(tbl, context.formatPhrase(RenderingContext.QUEST_HIDDEN_ITEM), ToolingExtensions.EXT_Q_DISPLAY_CAT, "This item is a hidden question", null); } - if (ToolingExtensions.readBoolExtension(qi, ToolingExtensions.EXT_Q_OTP_DISP)) { + if ("true".equals(qi.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) { defn(tbl, context.formatPhrase(RenderingContext.QUEST_HIDDEN_ITEM), ToolingExtensions.EXT_Q_OTP_DISP, "This item is optional to display", null); } - + // formal definitions - if (qi.hasDefinition()) { + if (qi.has("definition")) { genDefinitionLink(defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION)), qi, q); } - - if (qi.hasCode()) { + + if (qi.has("code")) { XhtmlNode tr = tbl.tr(); - tr.td().tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_CODE), qi.getCode().size())); + tr.td().tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_CODE), qi.children("code").size())); XhtmlNode ul = tr.td().ul(); - for (Coding c : qi.getCode()) { - renderCodingWithDetails(ul.li(), c); + for (ResourceWrapper c : qi.children("code")) { + renderCodingWithDetails(status, ul.li(), c); } } - if (qi.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod")) { + if (qi.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod")) { XhtmlNode tr = tbl.tr(); StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, ToolingExtensions.EXT_O_LINK_PERIOD); if (sd != null && sd.hasWebPath()) { tr.td().ah(sd.getWebPath()).tx(context.formatPhrase(RenderingContext.QUEST_OBSERVATION)); } else { - tr.td().ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod").tx(context.formatPhrase(RenderingContext.QUEST_OBSERVATION)); + tr.td().ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod").tx(context.formatPhrase(RenderingContext.QUEST_OBSERVATION)); } - render(tr.td(), qi.getExtensionByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod").getValue()); + renderDataType(status, tr.td(), qi.extension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod").child("value")); } - + // dynamic management - if (qi.hasEnableWhen()) { + if (qi.has("enableWhen")) { XhtmlNode tr = tbl.tr(); tr.td().tx(context.formatPhrase(RenderingContext.QUEST_EN)); td = tr.td(); - if (qi.getEnableWhen().size() == 1) { - renderEnableWhen(td, qi.getEnableWhen().get(0)); + if (qi.children("enableWhen").size() == 1) { + renderEnableWhen(td, qi.children("enableWhen").get(0)); } else { - if (qi.hasEnableBehavior()) { - td.tx(qi.getEnableBehavior().getDisplay()+" "+(context.formatPhrase(RenderingContext.QUEST_TRUE))); + if (qi.has("enableBehavior")) { + td.tx(qi.primitiveValue("enableBehavior")+" "+(context.formatPhrase(RenderingContext.QUEST_TRUE))); } else { td.tx(context.formatPhrase(RenderingContext.QUEST_ARE_TRUE)); } XhtmlNode ul = td.ul(); - for (QuestionnaireItemEnableWhenComponent ew : qi.getEnableWhen()) { + for (ResourceWrapper ew : qi.children("enableWhen")) { renderEnableWhen(ul.li(), ew); } } } - - + + // other stuff - - - - List curr = new ArrayList<>(); + + + + List curr = new ArrayList<>(); curr.addAll(parents); curr.add(qi); - for (QuestionnaireItemComponent qic : qi.getItem()) { - ext = renderDefinition(tbl, q, qic, curr) || ext; - } - return ext; + for (ResourceWrapper qic : qi.children("item")) { + renderDefinition(status, tbl, q, qic, curr); + } } - + private void defn(XhtmlNode tbl, String name, String url, Resource res) throws UnsupportedEncodingException, IOException { if (res != null && res.hasWebPath()) { - defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), RendererFactory.factory(res, context).display(res), res.getWebPath()); + defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), RendererFactory.factory(res, context.forContained()).buildSummary(wrap(res)), res.getWebPath()); } else if (Utilities.isAbsoluteUrlLinkable(url)) { defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), url, url); } { defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), url); } - + } - - private void renderEnableWhen(XhtmlNode x, QuestionnaireItemEnableWhenComponent ew) { - x.ah("#item."+ew.getQuestion()).tx(ew.getQuestion()); + + private void renderEnableWhen(XhtmlNode x, ResourceWrapper ew) { + x.ah(context.prefixLocalHref("#item."+ew.primitiveValue("question"))).tx(ew.primitiveValue("question")); x.tx(" "); - x.tx(ew.getOperator().toCode()); + x.tx(ew.primitiveValue("operator")); x.tx(" "); - x.tx(display(ew.getAnswer())); + x.tx(displayDataType(ew.child("Answer"))); } - + private XhtmlNode defn(XhtmlNode tbl, String name) { XhtmlNode tr = tbl.tr(); tr.td().tx(name); return tr.td(); } - + private void defn(XhtmlNode tbl, String name, int value) { if (value > 0) { XhtmlNode tr = tbl.tr(); @@ -1113,14 +1134,14 @@ public class QuestionnaireRenderer extends TerminologyRenderer { tr.td().tx(value); } } - - + + private void defn(XhtmlNode tbl, String name, boolean value) { XhtmlNode tr = tbl.tr(); tr.td().tx(name); tr.td().tx(Boolean.toString(value)); } - + private void defn(XhtmlNode tbl, String name, String value) { if (!Utilities.noString(value)) { XhtmlNode tr = tbl.tr(); @@ -1128,27 +1149,27 @@ public class QuestionnaireRenderer extends TerminologyRenderer { tr.td().tx(value); } } - + private void defn(XhtmlNode tbl, String name, String value, String url) { if (!Utilities.noString(value)) { XhtmlNode tr = tbl.tr(); tr.td().tx(name); - tr.td().ah(url).tx(value); + tr.td().ah(context.prefixLocalHref(url)).tx(value); } } - + private void defn(XhtmlNode tbl, String name, String nurl, String value, String url) { if (!Utilities.noString(value)) { XhtmlNode tr = tbl.tr(); - tr.td().ah(nurl).tx(name); + tr.td().ah(context.prefixLocalHref(nurl)).tx(name); if (url != null) { - tr.td().ah(url).tx(value); + tr.td().ah(context.prefixLocalHref(url)).tx(value); } else { tr.td().tx(value); } } } - + private void defn(XhtmlNode tbl, String name, boolean value, boolean ifFalse) { if (ifFalse || value) { XhtmlNode tr = tbl.tr(); @@ -1156,5 +1177,5 @@ public class QuestionnaireRenderer extends TerminologyRenderer { tr.td().tx(Boolean.toString(value)); } } - + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java index 1eacf6dff..c63b4c6b8 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/QuestionnaireResponseRenderer.java @@ -4,8 +4,9 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.DataType; +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.model.Expression; import org.hl7.fhir.r5.model.Questionnaire; import org.hl7.fhir.r5.model.QuestionnaireResponse; @@ -13,11 +14,11 @@ import org.hl7.fhir.r5.model.QuestionnaireResponse.QuestionnaireResponseItemAnsw import org.hl7.fhir.r5.model.QuestionnaireResponse.QuestionnaireResponseItemComponent; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; @@ -29,39 +30,41 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class QuestionnaireResponseRenderer extends ResourceRenderer { - public QuestionnaireResponseRenderer(RenderingContext context) { - super(context); - } + public QuestionnaireResponseRenderer(RenderingContext context) { + super(context); + } - public boolean render(XhtmlNode x, Resource q) throws UnsupportedEncodingException, IOException { - return render(x, (QuestionnaireResponse) q); + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + ResourceWrapper q = r.child("questionnaire"); + String qd = q == null ? context.formatPhrase(RenderingContext.QUEST_UNSPECIFIED_QUESTIONNAIRE) : displayCanonical(q); + ResourceWrapper s = r.child("subject"); + String sd = s == null ? context.formatPhrase(RenderingContext.QUEST_UNSPECIFIED_SUBJECT) : displayReference(s); + return context.formatPhrase(RenderingContext.QUEST_SUMMARY, qd, sd); } - - public boolean render(XhtmlNode x, QuestionnaireResponse q) throws UnsupportedEncodingException, IOException { + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper qr) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(qr, x); + switch (context.getQuestionnaireMode()) { - case FORM: return renderForm(x, q); - case LINKS: return renderLinks(x, q); + case FORM: + renderTree(status, x, qr); + break; + case LINKS: + renderLinks(status, x, qr); + break; // case LOGIC: return renderLogic(x, q); // case DEFNS: return renderDefns(x, q); - case TREE: return renderTree(x, q); + case TREE: + renderTree(status, x, qr); + break; default: throw new Error(context.formatPhrase(RenderingContext.QUEST_UNKNOWN_MODE)); } } - public boolean render(XhtmlNode x, ResourceWrapper qr) throws UnsupportedEncodingException, IOException { - switch (context.getQuestionnaireMode()) { - case FORM: return renderTree(x, qr); - case LINKS: return renderLinks(x, qr); -// case LOGIC: return renderLogic(x, q); -// case DEFNS: return renderDefns(x, q); - case TREE: return renderTree(x, qr); - default: - throw new Error(context.formatPhrase(RenderingContext.QUEST_UNKNOWN_MODE)); - } - } - - public boolean renderTree(XhtmlNode x, ResourceWrapper qr) throws UnsupportedEncodingException, IOException { + public void renderTree(RenderingStatus status, XhtmlNode x, ResourceWrapper qr) throws UnsupportedEncodingException, IOException { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true); TableModel model = gen.new TableModel("qtree="+qr.getId(), false); model.setAlternating(true); @@ -76,63 +79,21 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_DEFINITION), context.formatPhrase(RenderingContext.QUEST_TIMES), null, 0)); model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_ANSWER), context.formatPhrase(RenderingContext.QUEST_TYPE_ITEM), null, 0)); - boolean hasExt = false; // first we add a root for the questionaire itself Row row = addTreeRoot(gen, model.getRows(), qr); - List items = qr.children("item"); - for (BaseWrapper i : items) { - hasExt = renderTreeItem(gen, row.getSubRows(), qr, i) || hasExt; + List items = qr.children("item"); + for (ResourceWrapper i : items) { + renderTreeItem(status, gen, row.getSubRows(), qr, i); } XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); x.getChildNodes().add(xn); - return hasExt; - } - - public boolean renderTree(XhtmlNode x, QuestionnaireResponse q) throws UnsupportedEncodingException, IOException { - HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true); - TableModel model = gen.new TableModel("qtree="+q.getId(), true); - model.setAlternating(true); - if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) { - model.setDocoImg(HierarchicalTableGenerator.help16AsData()); - } else { - model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png")); - } - model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); - model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_LINKID), context.formatPhrase(RenderingContext.QUEST_LINK), null, 0)); - model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_TEXT), context.formatPhrase(RenderingContext.QUEST_TEXTFOR), null, 0)); - model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_DEFINITION), context.formatPhrase(RenderingContext.QUEST_TIMES), null, 0)); - model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_ANSWER), context.formatPhrase(RenderingContext.QUEST_TYPE_ITEM), null, 0)); - - boolean hasExt = false; - // first we add a root for the questionaire itself - Row row = addTreeRoot(gen, model.getRows(), q); - for (QuestionnaireResponseItemComponent i : q.getItem()) { - hasExt = renderTreeItem(gen, row.getSubRows(), q, i) || hasExt; - } - XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); - x.getChildNodes().add(xn); - return hasExt; - } - - - - private Row addTreeRoot(HierarchicalTableGenerator gen, List rows, QuestionnaireResponse q) throws IOException { - Row r = gen.new Row(); - rows.add(r); - - r.setIcon("icon_q_root.gif", context.formatPhrase(RenderingContext.QUEST_RESP_ROOT)); - r.getCells().add(gen.new Cell(null, null, q.getId(), null, null)); - r.getCells().add(gen.new Cell(null, null, "", null, null)); - r.getCells().add(gen.new Cell(null, null, context.formatPhrase(RenderingContext.QUEST_RESP), null, null)); - r.getCells().add(gen.new Cell(null, null, "", null, null)); - return r; } private Row addTreeRoot(HierarchicalTableGenerator gen, List rows, ResourceWrapper qr) throws IOException { Row r = gen.new Row(); rows.add(r); - Base b = qr.get("questionnaire"); + ResourceWrapper b = qr.child("questionnaire"); String ref = b == null ? null : b.primitiveValue(); Questionnaire q = context.getContext().fetchResource(Questionnaire.class, ref); @@ -152,18 +113,16 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { return r; } - - - private boolean renderTreeItem(HierarchicalTableGenerator gen, List rows, ResourceWrapper q, BaseWrapper i) throws IOException { + private boolean renderTreeItem(RenderingStatus status, HierarchicalTableGenerator gen, List rows, ResourceWrapper qr, ResourceWrapper i) throws IOException { Row r = gen.new Row(); rows.add(r); boolean hasExt = false; - List items = i.children("item"); - List answers = i.children("answer"); + List items = i.children("item"); + List answers = i.children("answer"); boolean hasItem = items != null && !items.isEmpty(); if (answers != null) { - for (BaseWrapper a : answers) { + for (ResourceWrapper a : answers) { hasItem = a.has("item"); } } @@ -172,40 +131,39 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { } else { r.setIcon("icon-q-string.png", context.formatPhrase(RenderingContext.QUEST_ITEM)); } - String linkId = i.has("linkId") ? i.get("linkId").primitiveValue() : "??"; - String text = i.has("text") ? i.get("text").primitiveValue() : ""; + String linkId = i.has("linkId") ? i.primitiveValue("linkId") : "??"; + String text = i.has("text") ? i.primitiveValue("text") : ""; r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+linkId, linkId, null, null)); r.getCells().add(gen.new Cell(null, null, text, null, null)); r.getCells().add(gen.new Cell(null, null, null, null, null)); if (answers == null || answers.size() == 0) { r.getCells().add(gen.new Cell(null, null, null, null, null)); if (items != null) { - for (BaseWrapper si : items) { - renderTreeItem(gen, r.getSubRows(), q, si); + for (ResourceWrapper si : items) { + renderTreeItem(status, gen, r.getSubRows(), qr, si); } } } else if (answers.size() == 1) { - BaseWrapper ans = answers.get(0); - renderAnswer(gen, q, r, ans); + ResourceWrapper ans = answers.get(0); + renderAnswer(status, gen, qr, r, ans); } else { r.getCells().add(gen.new Cell(null, null, null, null, null)); - for (BaseWrapper ans : answers) { + for (ResourceWrapper ans : answers) { Row ar = gen.new Row(); ar.setIcon("icon-q-string.png", "Item"); ar.getSubRows().add(ar); ar.getCells().add(gen.new Cell(null, null, null, null, null)); ar.getCells().add(gen.new Cell(null, null, text, null, null)); ar.getCells().add(gen.new Cell(null, null, null, null, null)); - renderAnswer(gen, q, ar, ans); + renderAnswer(status, gen, qr, ar, ans); } } return hasExt; } - public void renderAnswer(HierarchicalTableGenerator gen, ResourceWrapper q, Row r, BaseWrapper ans) throws UnsupportedEncodingException, IOException { - List items; - Base b = ans.get("value[x]"); + public void renderAnswer(RenderingStatus status, HierarchicalTableGenerator gen, ResourceWrapper qr, Row r, ResourceWrapper ans) throws UnsupportedEncodingException, IOException { + ResourceWrapper b = ans.child("value[x]"); if (b == null) { r.getCells().add(gen.new Cell(null, null, "null!", null, null)); } else if (b.isPrimitive()) { @@ -216,12 +174,11 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { Piece p = gen.new Piece("span"); p.getChildren().add(x); cell.addPiece(p); - render(x, (DataType) b); + renderDataType(status, x, b); r.getCells().add(cell); } - items = ans.children("item"); - for (BaseWrapper si : items) { - renderTreeItem(gen, r.getSubRows(), q, si); + for (ResourceWrapper si : ans.children("item")) { + renderTreeItem(status, gen, r.getSubRows(), qr, si); } } @@ -280,7 +237,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { if (sd != null) { String url = sd.getWebPath(); if (url != null) { - x.ah(url+"#"+path).tx(path); + x.ah(context.prefixLocalHref(url+"#"+path)).tx(path); } else { x.tx(i.getDefinition()); } @@ -292,7 +249,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { private void addExpression(Piece p, Expression exp, String label, String url) { XhtmlNode x = new XhtmlNode(NodeType.Element, "li").style("font-size: 11px"); p.addHtml(x); - x.ah(url).tx(label); + x.ah(context.prefixLocalHref(url)).tx(label); x.tx(": "); x.code(exp.getExpression()); } @@ -604,14 +561,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { // return "QuestionnaireResponse "+q.present(); // } // - private boolean renderLinks(XhtmlNode x, QuestionnaireResponse q) { - x.para().tx(context.formatPhrase(RenderingContext.QUEST_TRY_QUEST)); - XhtmlNode ul = x.ul(); - ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(context.formatPhrase(RenderingContext.QUEST_NLM)); - return false; - } - - private boolean renderLinks(XhtmlNode x, ResourceWrapper q) { + private boolean renderLinks(RenderingStatus status, XhtmlNode x, ResourceWrapper q) { x.para().tx(context.formatPhrase(RenderingContext.QUEST_TRY_QUEST)); XhtmlNode ul = x.ul(); ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(context.formatPhrase(RenderingContext.QUEST_NLM)); @@ -874,14 +824,4 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer { // } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return context.formatPhrase(RenderingContext.GENERAL_TODO); - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - return context.formatPhrase(RenderingContext.GENERAL_TODO); - } - } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java index 4b91febe1..9b885e533 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java @@ -5,15 +5,18 @@ import java.util.Date; import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation; import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.Enumeration; +import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.utilities.MarkDownProcessor; +import org.hl7.fhir.utilities.MarkDownProcessor.Dialect; import org.hl7.fhir.utilities.StandardsStatus; import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.MarkDownProcessor.Dialect; import org.hl7.fhir.utilities.validation.ValidationOptions; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; @@ -37,6 +40,23 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; */ public class Renderer { + public static class RenderingStatus { + private boolean extensions; + + public void setExtensions(boolean b) { + extensions = b; + } + + public boolean getExtensions() { + return extensions; + } + + public boolean isShowCodeDetails() { + // TODO Auto-generated method stub + return false; + } + + } protected RenderingContext context; public Renderer(RenderingContext context) { @@ -218,4 +238,20 @@ public class Renderer { public String toStr(Date value) { return value.toString(); } + + protected ResourceWrapper wrapNC(DataType type) { + return ResourceWrapper.forType(context.getContextUtilities(), type); + } + + protected ResourceWrapper wrap(Resource resource) { + return ResourceWrapper.forResource(context.getContextUtilities(), resource); + } + protected ResourceWrapper wrapWC(ResourceWrapper resource, DataType type) { + return ResourceWrapper.forType(context.getContextUtilities(), resource, type); + } + + protected String getTranslatedCode(ResourceWrapper child) { + return context.getTranslatedCode(child.primitiveValue(), child.getCodeSystemUri()); + } + } 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 8991a5cda..14cd5ca70 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 @@ -2,9 +2,8 @@ package org.hl7.fhir.r5.renderers; import org.hl7.fhir.r5.model.DomainResource; 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.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.utilities.Utilities; public class RendererFactory { @@ -62,30 +61,53 @@ public class RendererFactory { } - public static ResourceRenderer factory(ResourceWrapper resource, RenderingContext context, ResourceContext resourceContext) { + public static ResourceRenderer factory(ResourceWrapper resource, RenderingContext context) { if (context.getTemplateProvider() != null) { - String liquidTemplate = context.getTemplateProvider().findTemplate(context, resource.getName()); + String liquidTemplate = context.getTemplateProvider().findTemplate(context, resource.fhirType()); if (liquidTemplate != null) { return new LiquidRenderer(context, liquidTemplate); } } - switch (resource.getName()) { + switch (resource.fhirType()) { case "DiagnosticReport": return new DiagnosticReportRenderer(context); case "Library": return new LibraryRenderer(context); + case "Questionnaire": return new LibraryRenderer(context); case "List": return new ListRenderer(context); case "Patient": return new PatientRenderer(context); + case "Provenance": return new ProvenanceRenderer(context); + case "Parameters": return new ParametersRenderer(context); case "QuestionnaireResponse": return new QuestionnaireResponseRenderer(context); } + if (resource.isDirect()) { + switch (resource.fhirType()) { - return new ProfileDrivenRenderer(context, resourceContext); - } + case "ActorDefinition": return new ActorDefinitionRenderer(context); + case "Bundle": return new BundleRenderer(context); + case "CapabilityStatement": return new CapabilityStatementRenderer(context); + case "CodeSystem": return new CodeSystemRenderer(context); + case "CompartmentDefinition": return new CompartmentDefinitionRenderer(context); + case "ConceptMap": return new ConceptMapRenderer(context); + case "Encounter": return new EncounterRenderer(context); + case "ExampleScenario": return new ExampleScenarioRenderer(context); + case "ImplementationGuide": return new ImplementationGuideRenderer(context); + case "NamingSystem": return new NamingSystemRenderer(context); + case "OperationDefinition": return new OperationDefinitionRenderer(context); + case "OperationOutcome": return new OperationOutcomeRenderer(context); + case "Requirements": return new RequirementsRenderer(context); + case "SearchParameter": return new SearchParameterRenderer(context); + case "StructureDefinition": return new StructureDefinitionRenderer(context); + case "StructureMap": return new StructureMapRenderer(context); + case "SubscriptionTopic": return new SubscriptionTopicRenderer(context); + case "TestPlan": return new TestPlanRenderer(context); + case "ValueSet": return new ValueSetRenderer(context); + } + } - public static ResourceRenderer factory(ResourceWrapper rw, RenderingContext lrc) { - return factory(rw, lrc, null); + return new ProfileDrivenRenderer(context); } public static boolean hasSpecificRenderer(String rt) { - + return Utilities.existsInList(rt, "CodeSystem", "ValueSet", "ConceptMap", "CapabilityStatement", "CompartmentDefinition", "ImplementationGuide", "Library", "NamingSystem", "OperationDefinition", @@ -99,9 +121,9 @@ public class RendererFactory { * @return */ public static boolean hasIGSpecificRenderer(String rt) { - + return Utilities.existsInList(rt, "ValueSet", "CapabilityStatement", "Questionnaire"); } - + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RequirementsRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RequirementsRenderer.java index cd99ee241..0dfed74f5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RequirementsRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/RequirementsRenderer.java @@ -2,205 +2,186 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.List; import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.model.ActorDefinition; import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CodeSystem; -import org.hl7.fhir.r5.model.Enumeration; import org.hl7.fhir.r5.model.Library; -import org.hl7.fhir.r5.model.Reference; import org.hl7.fhir.r5.model.Requirements; -import org.hl7.fhir.r5.model.Requirements.ConformanceExpectation; import org.hl7.fhir.r5.model.Requirements.RequirementsStatementComponent; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.UrlType; -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.r5.renderers.utils.Resolver.ResourceWithReference; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class RequirementsRenderer extends ResourceRenderer { - public RequirementsRenderer(RenderingContext context) { - super(context); + public RequirementsRenderer(RenderingContext context) { + super(context); + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public RequirementsRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (Requirements) dr); - } + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper req) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(req, x); + genSummaryTable(status, x, (CanonicalResource) req.getResourceNative()); - public boolean render(XhtmlNode x, Requirements req) throws FHIRFormatError, DefinitionException, IOException { - if (req.hasActor()) { - if (req.getActor().size() == 1) { - ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, req.getActor().get(0).getValue(), req); + if (req.has("actor")) { + List actors = req.children("actor"); + if (actors.size() == 1) { + ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, actors.get(0).primitiveValue(), req.getResourceNative()); XhtmlNode p = x.para(); p.tx(context.formatPhrase(RenderingContext.REQ_ACTOR)+" "); - if (acd == null) { - p.code(req.getActor().get(0).getValue()); - } else { - p.ah(acd.getWebPath()).tx(acd.present()); - } + renderCanonical(status, p, ActorDefinition.class, actors.get(0)); } else { x.para().tx(context.formatPhrase(RenderingContext.REQ_FOLLOWING_ACTOR)+" "); XhtmlNode ul = x.ul(); - for (CanonicalType a : req.getActor()) { - ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, a.getValue(), req); - if (acd == null) { - ul.li().code(a.getValue()); - } else { - ul.li().ah(acd.getWebPath()).tx(acd.present()); - } + for (ResourceWrapper a : actors) { + renderCanonical(status, ul.li(), ActorDefinition.class, a); } } } - if (req.hasDerivedFrom()) { - if (req.getDerivedFrom().size() == 1) { - Requirements reqd = context.getWorker().fetchResource(Requirements.class, req.getDerivedFrom().get(0).getValue(), req); + if (req.has("derivedFrom")) { + List list = req.children("derivedFrom"); + if (list.size() == 1) { XhtmlNode p = x.para(); p.tx(context.formatPhrase(RenderingContext.REQ_DERIVE)+" "); - if (reqd == null) { - p.code(req.getDerivedFrom().get(0).getValue()); - } else { - p.ah(reqd.getWebPath()).tx(reqd.present()); - } + renderCanonical(status, p, Requirements.class, list.get(0)); } else { x.para().tx(context.formatPhrase(RenderingContext.REQ_FOLLOWING_REQ)+" "); XhtmlNode ul = x.ul(); - for (CanonicalType a : req.getDerivedFrom()) { - Requirements reqd = context.getWorker().fetchResource(Requirements.class, a.getValue(), req); - if (reqd == null) { - ul.li().code(a.getValue()); - } else { - ul.li().ah(reqd.getWebPath()).tx(reqd.present()); - } + for (ResourceWrapper a : list) { + renderCanonical(status, ul.li(), Requirements.class, a); } } } - if (req.hasReference()) { + if (req.has("reference")) { XhtmlNode p = x.para(); p.tx(context.formatPhrase(RenderingContext.GENERAL_REFS)+" "); int i = 0; - for (UrlType c : req.getReference()) { + for (ResourceWrapper c : req.children("reference")) { i++; if (i>1) p.tx(", "); - String url = c.getValue(); + String url = c.primitiveValue(); if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); } - p.ah(c.getValue()).tx(url); + p.ah(context.prefixLocalHref(c.primitiveValue())).tx(url); } } XhtmlNode tbl = x.table("grid"); - - for (RequirementsStatementComponent stmt : req.getStatement()) { + + for (ResourceWrapper stmt : req.children("statement")) { XhtmlNode tr = tbl.tr(); - String lbl = stmt.hasLabel() ? stmt.getLabel() : stmt.getKey(); + String lbl = stmt.has("label") ? stmt.primitiveValue("label") : stmt.primitiveValue("key"); XhtmlNode td = tr.td(); - td.b().an(stmt.getKey()); + td.b().an(context.prefixAnchor(stmt.primitiveValue("key"))); td.tx(lbl); td = tr.td(); boolean first = true; CodeSystem cs = context.getWorker().fetchCodeSystem("http://hl7.org/fhir/conformance-expectation"); - for (Enumeration t : stmt.getConformance()) { + for (ResourceWrapper t : stmt.children("conformance")) { if (first) first = false; else td.tx(", "); if (cs != null) { - td.ah(cs.getWebPath()+"#conformance-expectation-"+t.asStringValue()).tx(t.asStringValue().toUpperCase()); + td.ah(context.prefixLocalHref(cs.getWebPath()+"#conformance-expectation-"+t.primitiveValue())).tx(t.primitiveValue().toUpperCase()); } else { - td.tx(t.asStringValue().toUpperCase()); + td.tx(t.primitiveValue().toUpperCase()); } } td = tr.td(); - addMarkdown(td, stmt.getRequirement()); - if (stmt.hasDerivedFrom() || stmt.hasSatisfiedBy() || stmt.hasReference() || stmt.hasSource()) { + addMarkdown(td, stmt.primitiveValue("requirement")); + if (stmt.has("derivedFrom") || stmt.has("satisfiedBy") || stmt.has("reference") || stmt.has("source")) { td.para().tx(context.formatPhrase(RenderingContext.REQ_LINKS)+" "); XhtmlNode ul = td.ul(); - if (stmt.hasDerivedFrom()) { + if (stmt.has("derivedFrom")) { XhtmlNode li = ul.li(); li.tx(context.formatPhrase(RenderingContext.REQ_DERIVED)+" "); - String url = stmt.getDerivedFrom(); + String url = stmt.primitiveValue("derivedFrom"); String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : ""; if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); }; - Requirements reqr = context.getWorker().fetchResource(Requirements.class, url, req); + Requirements reqr = context.getWorker().fetchResource(Requirements.class, url, req.getResourceNative()); if (reqr != null) { RequirementsStatementComponent stmtr = reqr.findStatement(key); if (stmtr != null) { - li.ah(reqr.getWebPath()+"#"+key).tx(reqr.present() + " # " +(stmt.hasLabel() ? stmt.getLabel() : stmt.getKey())); + li.ah(context.prefixLocalHref(reqr.getWebPath()+"#"+key)).tx(reqr.present() + " # " +(stmt.has("label") ? stmt.primitiveValue("label") : stmt.primitiveValue("key"))); } else { - li.ah(reqr.getWebPath()+"#"+key).tx(reqr.present()+" # "+key); + li.ah(context.prefixLocalHref(reqr.getWebPath()+"#"+key)).tx(reqr.present()+" # "+key); } } else { - li.code(stmt.getDerivedFrom()); + li.code(stmt.primitiveValue("derivedFrom")); } } - if (stmt.hasSatisfiedBy()) { + if (stmt.has("satisfiedBy")) { XhtmlNode li = ul.li(); li.tx(context.formatPhrase(RenderingContext.REQ_SATISFIED)+" "); first = true; - for (UrlType c : stmt.getSatisfiedBy()) { + for (ResourceWrapper c : stmt.children("satisfiedBy")) { if (first) first = false; else li.tx(", "); - String url = c.getValue(); + String url = c.primitiveValue(); if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); } - Resource r = context.getWorker().fetchResource(Resource.class, url, req); + Resource r = context.getWorker().fetchResource(Resource.class, url, req.getResourceNative()); if (r != null) { String desc = getResourceDescription(r, null); - li.ah(c.getValue()).tx(desc); + li.ah(context.prefixLocalHref(c.primitiveValue())).tx(desc); } else { - li.ah(c.getValue()).tx(url); + li.ah(context.prefixLocalHref(c.primitiveValue())).tx(url); } } } - if (stmt.hasReference()) { + if (stmt.has("reference")) { XhtmlNode li = ul.li(); li.tx(context.formatPhrase(RenderingContext.GENERAL_REFS)+" "); int i = 0; - for (UrlType c : stmt.getReference()) { + for (ResourceWrapper c : stmt.children("reference")) { i++; if (i>1) li.tx(", "); - String url = c.getValue(); + String url = c.primitiveValue(); if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); } - li.ah(c.getValue()).tx(url); + li.ah(context.prefixLocalHref(c.primitiveValue())).tx(url); } } - if (stmt.hasSource()) { + if (stmt.has("source")) { XhtmlNode li = ul.li(); li.tx(context.formatPhrase(RenderingContext.GENERAL_SRC)+" "); first = true; - for (Reference c : stmt.getSource()) { + for (ResourceWrapper c : stmt.children("source")) { if (first) first = false; else li.tx(", "); - if (c.hasReference()) { - String url = c.getReference(); + if (c.has("reference")) { + String url = c.primitiveValue("reference"); if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); } - Resource r = context.getWorker().fetchResource(Resource.class, url, req); + Resource r = context.getWorker().fetchResource(Resource.class, url, req.getResourceNative()); ResourceWithReference t = null; if (r == null && context.getResolver() != null) { - t = context.getResolver().resolve(context, url); + t = context.getResolver().resolve(context, url, null); } if (r != null) { - String desc = getResourceDescription(r, c.getDisplay()); - li.ah(c.getReference()).tx(desc); + String desc = getResourceDescription(r, c.primitiveValue("display")); + li.ah(context.prefixLocalHref(c.primitiveValue("reference"))).tx(desc); } else if (t != null) { - String desc = getResourceDescription(t, c.getDisplay()); - li.ah(t.getReference()).tx(desc); + String desc = getResourceDescription(t, c.primitiveValue("display")); + li.ah(context.prefixLocalHref(t.getWebPath())).tx(desc); } else { - li.ah(c.getReference()).tx(url); + li.ah(context.prefixLocalHref(c.primitiveValue("reference"))).tx(url); } - } else if (c.hasDisplay()) { - li.tx(c.getDisplay()); + } else if (c.has("display")) { + li.tx(c.primitiveValue("display")); } else { li.tx("??"); } @@ -208,14 +189,13 @@ public class RequirementsRenderer extends ResourceRenderer { } } } - return false; } - + private String getResourceDescription(ResourceWithReference res, String display) throws UnsupportedEncodingException, IOException { if (!Utilities.noString(display)) { return display; } - return RendererFactory.factory(res.getResource(), context).display(res.getResource()); + return RendererFactory.factory(res.getResource(), context.forContained()).buildSummary(res.getResource()); } private String getResourceDescription(Resource res, String display) throws UnsupportedEncodingException, IOException { @@ -225,7 +205,7 @@ public class RequirementsRenderer extends ResourceRenderer { if (res instanceof CanonicalResource) { return ((CanonicalResource) res).present(); } - return RendererFactory.factory(res, context).display(res); + return RendererFactory.factory(res, context.forContained()).buildSummary(wrap(res)); } public void describe(XhtmlNode x, Library lib) { @@ -236,17 +216,4 @@ public class RequirementsRenderer extends ResourceRenderer { return lib.present(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((Library) r).present(); - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - return "??"; - } - } 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 cf4ceda5b..886474c0a 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 @@ -1,51 +1,47 @@ package org.hl7.fhir.r5.renderers; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; 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.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; -import org.hl7.fhir.r5.model.CodeableReference; -import org.hl7.fhir.r5.model.Coding; -import org.hl7.fhir.r5.model.DataType; -import org.hl7.fhir.r5.model.DomainResource; +import org.hl7.fhir.r5.model.ContactDetail; +import org.hl7.fhir.r5.model.ContactPoint; +import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r5.model.DateTimeType; import org.hl7.fhir.r5.model.Enumerations.PublicationStatus; import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.Narrative; -import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; import org.hl7.fhir.r5.model.Reference; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -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.model.StructureDefinition; +import org.hl7.fhir.r5.model.UriType; import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceReferenceKind; import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper.ElementKind; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.XVerExtensionManager; +import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; +import org.hl7.fhir.utilities.DebugUtilities; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; import org.hl7.fhir.utilities.xhtml.NodeType; import org.hl7.fhir.utilities.xhtml.XhtmlNode; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; public abstract class ResourceRenderer extends DataRenderer { @@ -54,7 +50,6 @@ public abstract class ResourceRenderer extends DataRenderer { } - protected ResourceContext rcontext; protected XVerExtensionManager xverManager; protected boolean multiLangMode; @@ -62,21 +57,6 @@ public abstract class ResourceRenderer extends DataRenderer { public ResourceRenderer(RenderingContext context) { super(context); } - - public ResourceRenderer(RenderingContext context, ResourceContext rcontext) { - super(context); - this.rcontext = rcontext; - } - - public ResourceContext getRcontext() { - return rcontext; - } - - public ResourceRenderer setRcontext(ResourceContext rcontext) { - this.rcontext = rcontext; - return this; - } - public boolean isMultiLangMode() { return multiLangMode; @@ -87,53 +67,53 @@ public abstract class ResourceRenderer extends DataRenderer { return this; } - public XhtmlNode build(Resource dr) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { + /** + * Just build the narrative that would go in the resource (per @renderResource()), but don't put it in the resource + * @param dr + * @return + * @throws FHIRFormatError + * @throws DefinitionException + * @throws FHIRException + * @throws IOException + * @throws EOperationOutcome + */ + public XhtmlNode buildNarrative(ResourceWrapper dr) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - render(x, dr); + buildNarrative(new RenderingStatus(), x, dr); return x; } + /** - * given a resource, update it's narrative with the best rendering available + * given a resource, update it's narrative with the best rendering available. * + * ResourceWrapper is a facade to either a org.hl7.fhir.r5.model Resource, or + * to a org.hl7.fhir.r5.elementModel (which might a resource of any version). + * + * Note that some resource renderers - only canonical ones - only render native + * resources, and not element model ones. These may be migrated in the future + * (only reason not to is the sheer size of the task, though performance might + * be a factor) + * * @param r - the domain resource in question * * @throws IOException * @throws EOperationOutcome * @throws FHIRException */ - - public void render(DomainResource r) throws IOException, FHIRException, EOperationOutcome { + public void renderResource(ResourceWrapper r) throws IOException, FHIRException, EOperationOutcome { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - boolean hasExtensions; - hasExtensions = render(x, r); + RenderingStatus status = new RenderingStatus(); + buildNarrative(status, x, r); String an = r.fhirType()+"_"+r.getId(); if (context.isAddName()) { if (!hasAnchorName(x, an)) { injectAnchorName(x, an); } } - inject(r, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED); - } - - public XhtmlNode render(ResourceWrapper r) throws IOException, FHIRException, EOperationOutcome { - assert r.getContext() == context; - XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - boolean hasExtensions = render(x, r); - - String an = r.fhirType()+"_"+r.getId(); - if (context.isAddName()) { - if (!hasAnchorName(x, an)) { - injectAnchorName(x, an); - } - } - if (r.hasNarrative()) { - r.injectNarrative(this, x, hasExtensions ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED); - } - return x; + inject(r, x, status.getExtensions() ? NarrativeStatus.EXTENSIONS : NarrativeStatus.GENERATED); } public XhtmlNode checkNarrative(ResourceWrapper r) throws IOException, FHIRException, EOperationOutcome { - assert r.getContext() == context; XhtmlNode x = r.getNarrative(); String an = r.fhirType()+"_"+r.getId(); if (context.isAddName()) { @@ -166,143 +146,229 @@ public abstract class ResourceRenderer extends DataRenderer { return false; } - public abstract boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome; - - public boolean render(XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - ProfileDrivenRenderer pr = new ProfileDrivenRenderer(context); - return pr.render(x, r); - } - - public void describe(XhtmlNode x, Resource r) throws UnsupportedEncodingException, IOException { - x.tx(display(r)); - } + // these three are what the descendants of this class override + public abstract void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome; + public abstract String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException; + + public String canonicalTitle(ResourceWrapper r) { + if (r.has("title")) { + return r.primitiveValue("title"); + } + if (r.has("name")) { + return r.primitiveValue("name"); + } + if (r.has("id")) { + return r.primitiveValue("id"); + } + return "??"; + } + public void describe(XhtmlNode x, ResourceWrapper r) throws UnsupportedEncodingException, IOException { - x.tx(display(r)); + x.tx(displayDataType(r)); + } + + public void inject(ResourceWrapper r, XhtmlNode x, NarrativeStatus status) throws IOException { + r.setNarrative(x, status.toCode(), multiLangMode, context.getLocale(), context.isPretty()); } - public abstract String display(Resource r) throws UnsupportedEncodingException, IOException; - public abstract String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException; + public void markLanguage(XhtmlNode x) { + x.setAttribute("lang", context.getLocale().toString()); + x.setAttribute("xml:lang", context.getLocale().toString()); + x.addTag(0, "hr"); + x.addTag(0, "p").b().tx(context.getLocale().getDisplayName()); + x.addTag(0, "hr"); + } - public void inject(DomainResource r, XhtmlNode x, NarrativeStatus status) { - r.getText().setUserData("renderer.generated", true); - if (!r.hasText() || !r.getText().hasDiv()) { - r.setText(new Narrative()); - r.getText().setStatus(status); - } - if (multiLangMode) { - if (!r.getText().hasDiv()) { - XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); - div.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); - r.getText().setDiv(div); + @Override + protected void renderCanonical(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + renderCanonical(status, x, Resource.class, type); + } + + public void renderCanonical(RenderingStatus status, XhtmlNode x, Class class_, ResourceWrapper canonical) throws UnsupportedEncodingException, IOException { + if (!renderPrimitiveWithNoValue(status, x, canonical)) { + CanonicalResource target = (CanonicalResource) context.getWorker().fetchResource(class_, canonical.primitiveValue(), canonical.getResourceNative()); + if (target != null && target.hasWebPath()) { + if (canonical.primitiveValue().contains("|")) { + x.ah(context.prefixLocalHref(target.getWebPath())).tx(target.present()+ context.formatPhrase(RenderingContext.RES_REND_VER) +target.getVersion()+")"); + } else { + x.ah(context.prefixLocalHref(target.getWebPath())).tx(target.present()); + } + return; + } + // we can't resolve it as a canonical in the context. We'll try to do a local resolution instead + ResourceWithReference rr = resolveReference(canonical); + if (rr == null) { + x.code(canonical.primitiveValue()); + } else if (rr.getResource() == null) { + x.ah(context.prefixLocalHref(rr.getWebPath())).tx(canonical.primitiveValue()); } else { - r.getText().getDiv().getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang")); + x.ah(context.prefixLocalHref(rr.getWebPath())).tx(RendererFactory.factory(rr.getResource(), context.forContained()).buildSummary(rr.getResource())); } - markLanguage(x); - r.getText().getDiv().getChildNodes().add(x); - } else { - if (!x.hasAttribute("xmlns")) - x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); - if (r.hasLanguage()) { - // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues - x.setAttribute("lang", r.getLanguage()); - x.setAttribute("xml:lang", r.getLanguage()); - } - r.getText().setDiv(x); } } - - public void renderCanonical(Resource res, XhtmlNode x, String url) throws UnsupportedEncodingException, IOException { - ResourceWrapper rw = new ResourceWrapperDirect(this.context, res); - renderCanonical(rw, x, url); - } - - public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url) throws UnsupportedEncodingException, IOException { - renderCanonical(rw, x, url, true, rw.getResource()); - } - public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url, boolean allowLinks, Resource src) throws UnsupportedEncodingException, IOException { - if (url == null) { - return; + + protected String displayCanonical(ResourceWrapper canonical) { + if (canonical == null || !canonical.hasPrimitiveValue()) { + return ""; } - Resource target = context.getWorker().fetchResource(Resource.class, url, src); + String url = canonical.primitiveValue(); + Resource target = context.getWorker().fetchResource(Resource.class, url, canonical.getResourceNative()); if (target == null || !(target instanceof CanonicalResource)) { - x.code().tx(url); + return url; } else { CanonicalResource cr = (CanonicalResource) target; - if (url.contains("|")) { - if (target.hasWebPath()) { - x.ah(target.getWebPath()).tx(cr.present()+ context.formatPhrase(RenderingContext.RES_REND_VER) +cr.getVersion()+")"); - } else { - url = url.substring(0, url.indexOf("|")); - x.code().tx(url); - x.tx(": "+cr.present()+ " " + context.formatPhrase(RenderingContext.RES_REND_VER) + " " + cr.getVersion()+")"); - } + return "->"+cr.present(); + } + } + + protected String displayReference(ResourceWrapper type) { + if (type == null) { + return ""; + } + ResourceWrapper display = null; + ResourceWrapper actual = null; + ResourceWrapper id = null; + if (type.fhirType().equals("CodeableReference")) { + if (type.has("reference")) { + type = type.child("reference"); } else { - if (target.hasWebPath()) { - x.ah(target.getWebPath()).tx(cr.present()); - } else { - x.code().tx(url); - x.tx(" ("+cr.present()+")"); - } + return displayCodeableConcept(type.child("concept")); } } - } - - public void render(Resource res, XhtmlNode x, DataType type) throws FHIRFormatError, DefinitionException, IOException { - if (type instanceof Reference) { - renderReference(res, x, (Reference) type); - } else if (type instanceof CodeableReference) { - CodeableReference cr = (CodeableReference) type; - if (cr.hasReference()) { - renderReference(res, x, cr.getReference()); + if (type.fhirType().equals("Reference")) { + display = type.child("display"); + actual = type.child("reference"); + id = type.child("identifier"); + } else { + actual = type; + } + if (actual != null && actual.hasPrimitiveValue()) { + ResourceWithReference rr = resolveReference(actual); + if (rr == null) { + String disp = display != null && display.hasPrimitiveValue() ? displayDataType(display) : actual.primitiveValue(); + return "->"+disp; } else { - render(x, type); - } - } else { - render(x, type); + String disp; + try { + disp = display != null && display.hasPrimitiveValue() ? displayDataType(display) : RendererFactory.factory(rr.getResource(), context.forContained()).buildSummary(rr.getResource()); + } catch (IOException e) { + disp = e.getMessage(); + } + return "->"+disp; + } + } else if (display != null) { + return "->"+display; + } else if (id != null) { + return "id: "+displayIdentifier(id); + } else { + return "??"; } } - public void render(ResourceWrapper res, XhtmlNode x, DataType type) throws FHIRFormatError, DefinitionException, IOException { - if (type instanceof Reference) { - renderReference(res, x, (Reference) type); - } else if (type instanceof CodeableReference) { - CodeableReference cr = (CodeableReference) type; - if (cr.hasReference()) { - renderReference(res, x, cr.getReference()); + + /** + * @param + * @param status + * @param res + * @param x + * @param class_ - makes resolution faster, but can just be Resource.class + * @param canonical + * @throws UnsupportedEncodingException + * @throws IOException + */ + public void renderCanonical(RenderingStatus status, ResourceWrapper res, XhtmlNode x, Class class_, CanonicalType canonical) throws UnsupportedEncodingException, IOException { + if (canonical == null || !canonical.hasPrimitiveValue()) { + return; + } + String url = canonical.asStringValue(); + Resource target = context.getWorker().fetchResource(Resource.class, url, res.getResourceNative()); + if (target == null || !(target instanceof CanonicalResource)) { + x.code().tx(url); + } else { + CanonicalResource cr = (CanonicalResource) target; + if (!target.hasWebPath()) { + if (url.contains("|")) { + x.code().tx(cr.getUrl()); + x.tx(context.formatPhrase(RenderingContext.RES_REND_VER, cr.getVersion())); + x.tx(" ("+cr.present()+")"); + } else { + x.code().tx(url); + x.tx(" ("+cr.present()+")"); + } } else { - render(x, type); - } - } else { - render(x, type); + if (url.contains("|")) { + x.ah(context.prefixLocalHref(target.getWebPath())).tx(cr.present()+ context.formatPhrase(RenderingContext.RES_REND_VER) +cr.getVersion()+")"); + } else { + x.ah(context.prefixLocalHref(target.getWebPath())).tx(cr.present()); + } + } + } + } + + // todo: if (r.hasExtension(ToolingExtensions.EXT_TARGET_ID) || r.hasExtension(ToolingExtensions.EXT_TARGET_PATH)) { + @Override + public void renderReference(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { + if (type == null) { + return; + } + ResourceWrapper display = null; + ResourceWrapper actual = null; + ResourceWrapper id = null; + if (type.fhirType().equals("CodeableReference")) { + if (type.has("reference")) { + type = type.child("reference"); + } else { + renderCodeableConcept(status, x, type.child("concept")); + return; + } + } + if (type.fhirType().equals("Reference")) { + display = type.child("display"); + actual = type.child("reference"); + id = type.child("identifier"); + } else { + actual = type; + } + if (actual != null && actual.hasPrimitiveValue()) { + ResourceWithReference rr = resolveReference(actual); + if (rr == null) { + String disp = display != null && display.hasPrimitiveValue() ? displayDataType(display) : actual.primitiveValue(); + x.ah(context.prefixLocalHref(actual.primitiveValue())).tx(disp); + } else { + String disp = display != null && display.hasPrimitiveValue() ? displayDataType(display) : RendererFactory.factory(rr.getResource(), context.forContained()).buildSummary(rr.getResource()); + x.ah(context.prefixLocalHref(rr.getWebPath())).tx(disp); + } + } else if (display != null && id != null) { + renderDataType(status, x, display); + x.tx(" (Identifier: "); + renderIdentifier(status, x, id); + x.tx(")"); + } else if (display != null) { + renderDataType(status, x, display); + } else if (id != null) { + x.tx("Identifier: "); + renderIdentifier(status, x, id); + } else { + x.tx("??"); } } - - public void renderReference(Resource res, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException { - ResourceWrapper rw = new ResourceWrapperDirect(this.context, res); - renderReference(rw, x, r); - } - - public void renderReference(ResourceWrapper rw, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException { - renderReference(rw, x, r, true); - } - - public void renderReference(Resource res, HierarchicalTableGenerator gen, List pieces, Reference r, boolean allowLinks) throws UnsupportedEncodingException, IOException { + + public void renderReference(ResourceWrapper res, HierarchicalTableGenerator gen, List pieces, Reference r, boolean allowLinks) throws UnsupportedEncodingException, IOException { if (r == null) { pieces.add(gen.new Piece(null, "null!", null)); return; } - ResourceWrapper rw = new ResourceWrapperDirect(this.context, res); ResourceWithReference tr = null; String link = null; StringBuilder text = new StringBuilder(); if (r.hasReferenceElement() && allowLinks) { - tr = resolveReference(rw, r.getReference()); + tr = resolveReference(res, r.getReference(), true); if (!r.getReference().startsWith("#")) { - if (tr != null && tr.getReference() != null) { - link = tr.getReference(); + if (tr != null && tr.getWebPath() != null) { + link = tr.getWebPath(); } else if (r.getReference().contains("?")) { text.append(context.formatPhrase(RenderingContext.RES_REND_COND_REF)+" "); } else { @@ -310,18 +376,18 @@ public abstract class ResourceRenderer extends DataRenderer { } } } - if (tr != null && tr.getReference() != null && tr.getReference().startsWith("#")) { + if (tr != null && tr.getWebPath() != null && tr.getWebPath().startsWith("#")) { text.append(context.formatPhrase(RenderingContext.RES_REND_SEE_ON_THIS_PAGE)+" "); } // what to display: if text is provided, then that. if the reference was resolved, then show the name, or the generated narrative String display = r.hasDisplayElement() ? r.getDisplay() : null; - String name = tr != null && tr.getResource() != null ? tr.getResource().getNameFromResource() : null; + String name = tr != null && tr.getResource() != null ? getNameForResource(tr.getResource()) : null; if (display == null && (tr == null || tr.getResource() == null)) { if (!Utilities.noString(r.getReference())) { text.append(r.getReference()); } else if (r.hasIdentifier()) { - text.append(displayIdentifier(r.getIdentifier())); + text.append(displayIdentifier(wrapWC(res, r.getIdentifier()))); } else { text.append("??"); } @@ -330,7 +396,7 @@ public abstract class ResourceRenderer extends DataRenderer { if (display != null) { text.append(": "+display); } - if ((tr == null || (tr.getReference() != null && !tr.getReference().startsWith("#"))) && name != null) { + if ((tr == null || (tr.getWebPath() != null && !tr.getWebPath().startsWith("#"))) && name != null) { text.append(" \""+name+"\""); } if (r.hasExtension(ToolingExtensions.EXT_TARGET_ID) || r.hasExtension(ToolingExtensions.EXT_TARGET_PATH)) { @@ -358,186 +424,312 @@ public abstract class ResourceRenderer extends DataRenderer { text.append(context.formatPhrase(RenderingContext.RES_REND_DESC)); } } - if (tr != null && tr.getReference() != null && tr.getReference().startsWith("#")) { + if (tr != null && tr.getWebPath() != null && tr.getWebPath().startsWith("#")) { text.append(")"); } pieces.add(gen.new Piece(link,text.toString(), null)); } - public void renderReference(ResourceWrapper rw, XhtmlNode x, Reference r, boolean allowLinks) throws UnsupportedEncodingException, IOException { - if (r == null) { - x.tx("null!"); + public void renderReference(ResourceWrapper res, HierarchicalTableGenerator gen, List pieces, ResourceWrapper r, boolean allowLinks) throws UnsupportedEncodingException, IOException { + if (r == null) { + pieces.add(gen.new Piece(null, "null!", null)); return; } - XhtmlNode c = null; - ResourceWithReference tr = null; - boolean onPage = false; - if (r.hasReferenceElement() && allowLinks) { - tr = resolveReference(rw, r.getReference()); + ResourceWithReference trt = null; + String link = null; + StringBuilder text = new StringBuilder(); + if (r.has("reference") && allowLinks) { + trt = resolveReference(res, r.primitiveValue("reference"), true); - if (!r.getReference().startsWith("#")) { - if (tr != null && tr.getReference() != null) { - if (tr.getReference().startsWith("#")) { - onPage = true; - if (context.getRules() == GenerationRules.IG_PUBLISHER || (tr != null && tr.getKind() != ResourceReferenceKind.BUNDLE)) { - c = x.ah("#hc"+tr.getReference().substring(1)); - } else { - c = x; - } - } else { - c = x.ah(tr.getReference()); - } - } else if (r.getReference().contains("?")) { - x.tx(context.formatPhrase(RenderingContext.RES_REND_COND_REF)+" "); - c = x.code(""); + if (!r.primitiveValue("reference").startsWith("#")) { + if (trt != null && trt.getWebPath() != null) { + link = trt.getWebPath(); + } else if (r.primitiveValue("reference").contains("?")) { + text.append(context.formatPhrase(RenderingContext.RES_REND_COND_REF)+" "); } else { - c = x.ah(r.getReference()); + link = r.primitiveValue("reference"); } - } else if ("#".equals(r.getReference())) { - c = x.ah("#"); - } else if (context.getRules() == GenerationRules.IG_PUBLISHER || (tr != null && tr.getKind() != ResourceReferenceKind.BUNDLE)) { - c = x.ah("#hc"+r.getReference().substring(1)); - onPage = true; - } else { - c = x; - } - } else { - c = x.span(null, null); + } } - if (onPage) { - c.tx(context.formatPhrase(RenderingContext.RES_REND_SEE_ON_THIS_PAGE)+" "); + if (trt != null && trt.getWebPath() != null && trt.getWebPath().startsWith("#")) { + text.append(context.formatPhrase(RenderingContext.RES_REND_SEE_ON_THIS_PAGE)+" "); } // what to display: if text is provided, then that. if the reference was resolved, then show the name, or the generated narrative - String display = r.hasDisplayElement() ? r.getDisplay() : null; - String name = tr != null && tr.getResource() != null ? tr.getResource().getNameFromResource() : null; + String display = r.has("display") ? r.primitiveValue("display") : null; + String name = trt != null && trt.getResource() != null ? getNameForResource(trt.getResource()) : null; - if (display == null && (tr == null || tr.getResource() == null)) { - if (!Utilities.noString(r.getReference())) { - c.addText(r.getReference()); - } else if (r.hasIdentifier()) { - renderIdentifier(c, r.getIdentifier()); + if (display == null && (trt == null || trt.getResource() == null)) { + if (!Utilities.noString(r.primitiveValue("reference"))) { + text.append(r.primitiveValue("reference")); + } else if (r.has("identifier")) { + text.append(displayIdentifier(r.child("identifier"))); } else { - c.addText("??"); + text.append("??"); } } else if (context.isTechnicalMode()) { - c.addText(r.getReference()); + text.append(r.primitiveValue("reference")); if (display != null) { - c.addText(": "+display); + text.append(": "+display); } - if ((tr == null || (tr.getReference() != null && !tr.getReference().startsWith("#"))) && name != null) { - x.addText(" \""+name+"\""); + if ((trt == null || (trt.getWebPath() != null && !trt.getWebPath().startsWith("#"))) && name != null) { + text.append(" \""+name+"\""); } if (r.hasExtension(ToolingExtensions.EXT_TARGET_ID) || r.hasExtension(ToolingExtensions.EXT_TARGET_PATH)) { - x.addText("("); - for (Extension ex : r.getExtensionsByUrl(ToolingExtensions.EXT_TARGET_ID)) { - if (ex.hasValue()) { - x.sep(", "); - x.addText("#"+ex.getValue().primitiveValue()); + text.append("("); + for (ResourceWrapper ex : r.extensions(ToolingExtensions.EXT_TARGET_ID)) { + if (ex.has("value")) { + text.append(", "); + text.append("#"+ex.primitiveValue("value")); } } - for (Extension ex : r.getExtensionsByUrl(ToolingExtensions.EXT_TARGET_PATH)) { - if (ex.hasValue()) { - x.sep(", "); - x.addText("/#"+ex.getValue().primitiveValue()); + for (ResourceWrapper ex : r.extensions(ToolingExtensions.EXT_TARGET_PATH)) { + if (ex.has("value")) { + text.append(", "); + text.append("#"+ex.primitiveValue("value")); } } - x.addText(")"); + text.append(")"); } } else { if (display != null) { - c.addText(display); + text.append(display); } else if (name != null) { - c.addText(name); + text.append(name); } else { - c.tx(context.formatPhrase(RenderingContext.RES_REND_GEN_SUM)+" "); - if (tr != null) { - new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, r.getReference().startsWith("#"), true); - } + text.append(context.formatPhrase(RenderingContext.RES_REND_DESC)); } } - } - - public void renderReference(ResourceWrapper rw, XhtmlNode x, BaseWrapper r) throws UnsupportedEncodingException, IOException { - XhtmlNode c = x; - ResourceWithReference tr = null; - String v; - if (r.has("reference")) { - v = r.get("reference").primitiveValue(); - tr = resolveReference(rw, v); - - if (!v.startsWith("#")) { - if (tr != null && tr.getReference() != null) - c = x.ah(tr.getReference()); - else - c = x.ah(v); - } - } else { - v = ""; - } - // what to display: if text is provided, then that. if the reference was resolved, then show the generated narrative - if (r.has("display")) { - c.addText(r.get("display").primitiveValue()); - if (tr != null && tr.getResource() != null) { - c.tx(context.formatPhrase(RenderingContext.RES_REND_GEN_SUM)+" "); - new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, v.startsWith("#"), false); - } - } else if (tr != null && tr.getResource() != null) { - new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), v.startsWith("#"), v.startsWith("#"), false); - } else { - c.addText(v); - } + if (trt != null && trt.getWebPath() != null && trt.getWebPath().startsWith("#")) { + text.append(")"); + } + pieces.add(gen.new Piece(link,text.toString(), null)); } - protected ResourceWithReference resolveReference(ResourceWrapper res, String url) { - if (url == null) - return null; - if (url.startsWith("#") && res != null) { - for (ResourceWrapper r : res.getContained()) { - if (r.getId().equals(url.substring(1))) - return new ResourceWithReference(ResourceReferenceKind.CONTAINED, url, r); - } - return null; - } - String version = null; - if (url.contains("/_history/")) { - version = url.substring(url.indexOf("/_history/")+10); - url = url.substring(0, url.indexOf("/_history/")); - } - - if (rcontext != null) { - BundleEntryComponent bundleResource = rcontext.resolve(url); - if (bundleResource != null) { - String id = bundleResource.getResource().getId(); - if (id == null) { - id = makeIdFromBundleEntry(bundleResource.getFullUrl()); + protected String getNameForResource(ResourceWrapper resource) { + ResourceWrapper name = resource.firstChild("name"); + if (name != null && !name.isEmpty()) { + if (name.isPrimitive()) { + return name.primitiveValue(); + } else if (name.fhirType().equals("HumanName")) { + String family = name.primitiveValue("family"); + String given = name.firstPrimitiveValue("given"); + return (family == null) ? given : given == null ? family : family+" "+given; + } else { + String n = name.primitiveValueMN("name", "text", "value"); + if (n != null) { + return n; } - String bundleUrl = "#" + bundleResource.getResource().getResourceType().name() + "_" + id; - return new ResourceWithReference(ResourceReferenceKind.BUNDLE, bundleUrl, new ResourceWrapperDirect(this.context, bundleResource.getResource())); } - org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url, version); - if (bundleElement != null) { - String bundleUrl = null; - Element br = bundleElement.getNamedChild("resource", false); - if (br.getChildValue("id") != null) { - if ("Bundle".equals(br.fhirType())) { - bundleUrl = "#"; + } + String n = resource.primitiveValue("productName"); + if (n == null) { + throw new Error("What to render for 'name'? Type is "+resource.fhirType()); + } else { + return n; + } + } + + protected void renderUri(RenderingStatus status, ResourceWrapper resource, XhtmlNode x, UriType uri) throws FHIRFormatError, DefinitionException, IOException { + if (!renderPrimitiveWithNoValue(status, x, uri)) { + String v = uri.primitiveValue(); + if ("/Binary/1-note".equals(v)) { + DebugUtilities.breakpoint(); + } + if (v.startsWith("mailto:")) { + x.ah(context.prefixLocalHref(v)).addText(v.substring(7)); + } else { + ResourceWithReference rr = resolveReference(resource, uri.primitiveValue(), false); + if (rr != null) { + x.ah(rr.getWebPath()).addText(RendererFactory.factory(rr.getResource(), context.forContained()).buildSummary(rr.getResource())); + } else { + Resource r = context.getContext().fetchResource(Resource.class, v); + if (r != null && r.getWebPath() != null) { + x.ah(context.prefixLocalHref(r.getWebPath())).addText(RendererFactory.factory(r, context.forContained()).buildSummary(wrap(r))); + } else { + String url = context.getResolver() != null ? context.getResolver().resolveUri(context, v) : null; + if (url != null) { + x.ah(context.prefixLocalHref(url)).addText(v); + } else if (Utilities.isAbsoluteUrlLinkable(v) && !uri.fhirType().equals("id")) { + x.ah(context.prefixLocalHref(v)).addText(v); + } else { + x.addText(v); + } + } + } + } + } + } + + @Override + protected void renderUri(RenderingStatus status, XhtmlNode x, ResourceWrapper uri) throws FHIRFormatError, DefinitionException, IOException { + if (!renderPrimitiveWithNoValue(status, x, uri)) { + String v = uri.primitiveValue(); + if ("/Binary/1-note".equals(v)) { + DebugUtilities.breakpoint(); + } + + if (context.getContextUtilities().isResource(v)) { + v = "http://hl7.org/fhir/StructureDefinition/"+v; + } + if (v.startsWith("mailto:")) { + x.ah(v).addText(v.substring(7)); + } else { + ResourceWithReference rr = resolveReference(uri); + if (rr != null) { + if (rr.getResource() == null) { + x.ah(context.prefixLocalHref(rr.getWebPath())).addText(rr.getUrlReference()); } else { - bundleUrl = "#" + br.fhirType() + "_" + br.getChildValue("id"); + x.ah(context.prefixLocalHref(rr.getWebPath())).addText(RendererFactory.factory(rr.getResource(), context.forContained()).buildSummary(rr.getResource())); } } else { - bundleUrl = "#" +fullUrlToAnchor(bundleElement.getChildValue("fullUrl")); + Resource r = context.getContext().fetchResource(Resource.class, v); + if (r != null && r.getWebPath() != null) { + x.ah(context.prefixLocalHref(r.getWebPath())).addText(RendererFactory.factory(r, context.forContained()).buildSummary(wrap(r))); + } else if (r != null) { + x.ah(context.prefixLocalHref(v)).addText(RendererFactory.factory(r, context.forContained()).buildSummary(wrap(r))); + } else { + String url = context.getResolver() != null ? context.getResolver().resolveUri(context, v) : null; + if (url != null) { + x.ah(context.prefixLocalHref(url)).addText(v); + } else if (Utilities.isAbsoluteUrlLinkable(v) && !uri.fhirType().equals("id")) { + x.ah(context.prefixLocalHref(v)).addText(v); + } else { + x.addText(v); + } + } + } + } + } + } + + /** + * Eventually this will be retired if and when there's no more direct renderers + * + * @param + */ + protected T findCanonical(Class class_, UriType canonical, ResourceWrapper sourceOfReference) { + return context.getContext().fetchResource(class_, canonical.asStringValue(), sourceOfReference.getResourceNative()); + } + + protected T findCanonical(Class class_, String canonical, ResourceWrapper sourceOfReference) { + return context.getContext().fetchResource(class_, canonical, sourceOfReference.getResourceNative()); + } + + + private ResourceWithReference resolveContained(ResourceWrapper resource, String url) { + ResourceWrapper container = findContainer(resource); + if (container == null) { + return null; + } else if ("#".equals(url)) { + return new ResourceWithReference(ResourceReferenceKind.CONTAINER, url, "#hc"+container.getScopedId(), container); + } else { + String tid = url.substring(1); + for (ResourceWrapper c : container.children("contained")) { + if (tid.equals(c.getId())) { + return new ResourceWithReference(ResourceReferenceKind.CONTAINED, url, "#hc"+c.getScopedId(), c); } - return new ResourceWithReference(ResourceReferenceKind.BUNDLE, bundleUrl, new ResourceWrapperMetaElement(this.context, br)); } } + return null; + } + + private ResourceWrapper findContainer(ResourceWrapper resource) { + ResourceWrapper container = resource; + while (container != null) { + if (container.isResource() && container.kind() != ElementKind.ContainedResource) { + break; + } + container = container.parent(); + } + return container; + } - Resource ae = getContext().getWorker().fetchResource(null, url, version); - if (ae != null) - return new ResourceWithReference(ResourceReferenceKind.EXTERNAL, url, new ResourceWrapperDirect(this.context, ae)); - else if (context.getResolver() != null) { - return context.getResolver().resolve(context, url); - } else + private ResourceWithReference resolveOutside(ResourceWrapper resource, String url, String version, boolean followLinks) { + ResourceWrapper container = findContainer(resource); + if (container != null) { + while (container != null) { + if (container.isResource() && container.fhirType().equals("Bundle")) { + ResourceWithReference rr = findInBundle(resource, url); + if (rr != null) { + return null; + } + } + container = container.parent(); + } + } + if (followLinks) { + // ok, we didn't find it in the current instance, so we go look elsewhere + if (context.getResolver() != null) { + ResourceWithReference rr = context.getResolver().resolve(context, url, version); + if (rr != null) { + return rr; + } + } + Resource r = context.getWorker().fetchResource(Resource.class, url, version); + if (r != null) { + return new ResourceWithReference(ResourceReferenceKind.EXTERNAL, url, r.getWebPath(), wrap(r)); + } + } + return null; + } + + private ResourceWithReference findInBundle(ResourceWrapper resource, String url) { + if (url.equals("Bundle/"+resource.getId())) { + return new ResourceWithReference(ResourceReferenceKind.BUNDLE, url, "#"+resource.getScopedId(), resource); + } + for (ResourceWrapper entry : resource.children("entry")) { + if (entry.has("resource")) { + ResourceWrapper res = entry.child("resource"); + if (entry.has("fullUrl")) { + String fu = entry.primitiveValue("fullUrl"); + if (url.equals(fu)) { + return new ResourceWithReference(ResourceReferenceKind.BUNDLE, url, "#"+res.getScopedId(), res); + } + } + if ("Bundle".equals(res.fhirType())) { + ResourceWithReference rr = findInBundle(res, url); + if (rr != null) { + return rr; + } + } + } + } + return null; + } + + protected ResourceWithReference resolveReference(ResourceWrapper resource, String url, boolean followLinks) { + if (url == null) { return null; + } + if ("http://example.org/fhir/Encounter/doc-example".equals(url)) { + DebugUtilities.breakpoint(); + } + if (url.startsWith("#")) { + return resolveContained(resource, url); + } else { + String version = null; + if (url.contains("/_history/")) { + version = url.substring(url.indexOf("/_history/")+10); + url = url.substring(0, url.indexOf("/_history/")); + } + + return resolveOutside(resource, url, version, followLinks); + } + + } + + protected ResourceWithReference resolveReference(ResourceWrapper reference) { + if (reference.fhirType().equals("CodeableReference")) { + if (reference.has("reference")) { + return resolveReference(reference.child("reference")); + } else { + return null; + } + } else if (reference.fhirType().equals("Reference")) { + return resolveReference(reference.getResourceWrapper(), reference.primitiveValue("reference"), true); + } else { + return resolveReference(reference.getResourceWrapper(), reference.primitiveValue(), true); + } } @@ -555,56 +747,26 @@ public abstract class ResourceRenderer extends DataRenderer { return url.replace(":", "").replace("/", "_"); } - protected void generateCopyright(XhtmlNode x, CanonicalResource cs) { + protected void generateCopyright(XhtmlNode x, ResourceWrapper cs) { XhtmlNode p = x.para(); p.b().tx(getContext().formatPhrase(RenderingContext.RESOURCE_COPYRIGHT)); - smartAddText(p, " " + cs.getCopyright()); + smartAddText(p, " " + context.getTranslated(cs.child("copyright"))); + } + + protected void generateCopyrightTableRow(XhtmlNode tbl, ResourceWrapper cs) { + XhtmlNode tr = tbl.tr(); + tr.td().b().tx(getContext().formatPhrase(RenderingContext.RESOURCE_COPYRIGHT)); + smartAddText(tr.td(), " " + context.getTranslated(cs.child("copyright"))); } public String displayReference(Resource res, Reference r) throws UnsupportedEncodingException, IOException { return (context.formatPhrase(RenderingContext.GENERAL_TODO)); } - public Base parseType(String string, String type) { return null; } - protected PropertyWrapper getProperty(ResourceWrapper res, String name) { - for (PropertyWrapper t : res.children()) { - if (t.getName().equals(name)) - return t; - } - return null; - } - - protected PropertyWrapper getProperty(BaseWrapper res, String name) { - for (PropertyWrapper t : res.children()) { - if (t.getName().equals(name)) - return t; - } - return null; - } - - protected boolean valued(PropertyWrapper pw) { - return pw != null && pw.hasValues(); - } - - - protected ResourceWrapper fetchResource(BaseWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException { - if (context.getResolver() == null) - return null; - - PropertyWrapper ref = subject.getChildByName("reference"); - if (ref == null || !ref.hasValues()) { - return null; - } - String url = ref.value().getBase().primitiveValue(); - ResourceWithReference rr = context.getResolver().resolve(context, url); - return rr == null ? null : rr.getResource(); - } - - protected String describeStatus(PublicationStatus status, boolean experimental) { switch (status) { case ACTIVE: return experimental ? (context.formatPhrase(RenderingContext.GENERAL_EXPER)) : (context.formatPhrase(RenderingContext.RES_REND_ACT)); @@ -624,7 +786,7 @@ public abstract class ResourceRenderer extends DataRenderer { if (cd == null) { x.tx(code); } else { - x.ah(cs.getWebPath()+"#"+cs.getId()+"-"+cd.getCode()).tx(cd.getDisplay()); + x.ah(context.prefixLocalHref(cs.getWebPath()+"#"+cs.getId()+"-"+cd.getCode())).tx(cd.getDisplay()); } } } @@ -637,125 +799,147 @@ public abstract class ResourceRenderer extends DataRenderer { return true; } - protected void renderResourceHeader(ResourceWrapper r, XhtmlNode x, boolean doId) throws UnsupportedEncodingException, FHIRException, IOException { - XhtmlNode div = x.div().style("display: inline-block").style("background-color: #d9e0e7").style("padding: 6px") - .style("margin: 4px").style("border: 1px solid #8da1b4") - .style("border-radius: 5px").style("line-height: 60%"); - - String id = getPrimitiveValue(r, "id"); - if (doId) { - div.an("hc"+id); + protected XhtmlNode renderResourceTechDetails(ResourceWrapper r, XhtmlNode x) throws UnsupportedEncodingException, FHIRException, IOException { + return renderResourceTechDetails(r, x, (context.isContained() ? " #"+r.getId() : r.getId())); + } + + protected XhtmlNode renderResourceTechDetails(ResourceWrapper r, XhtmlNode x, String desc) throws UnsupportedEncodingException, FHIRException, IOException { + XhtmlNode p = x.para().attribute("class", "res-header-id"); + String ft = context.getTranslatedCode(r.fhirType(), "http://hl7.org/fhir/fhir-types"); + if (desc == null) { + p.b().tx(context.formatPhrase(context.isTechnicalMode() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, ft, "")); + } else { + p.b().tx(context.formatPhrase(context.isTechnicalMode() ? RenderingContext.PROF_DRIV_GEN_NARR_TECH : RenderingContext.PROF_DRIV_GEN_NARR, ft, desc)); } - String lang = getPrimitiveValue(r, "language"); - String ir = getPrimitiveValue(r, "implicitRules"); - BaseWrapper meta = r.getChildByName("meta").hasValues() ? r.getChildByName("meta").getValues().get(0) : null; - String versionId = getPrimitiveValue(meta, "versionId"); - String lastUpdated = getPrimitiveValue(meta, "lastUpdated"); - String source = getPrimitiveValue(meta, "source"); - - if (id != null || lang != null || versionId != null || lastUpdated != null) { - XhtmlNode p = plateStyle(div.para()); - p.tx(context.formatPhrase(RenderingContext.GENERAL_RESOURCE)); - p.tx(r.fhirType()); - p.tx(" "); - if (id != null) { - p.tx("\""+id+"\" "); + // first thing we do is lay down the resource anchors. + if (!Utilities.noString(r.getId())) { + if (!context.isSecondaryLang()) { + x.an(context.prefixAnchor(r.getScopedId())); + x.an(context.prefixAnchor("hc"+r.getScopedId())); } - if (versionId != null) { - p.tx(context.formatPhrase(RenderingContext.GENERAL_VER) + "\""+versionId+"\" "); - } - if (lastUpdated != null) { - p.tx(context.formatPhrase(RenderingContext.RES_REND_UPDATED) + "\""); - renderDateTime(p, lastUpdated); - p.tx("\" "); - } - if (lang != null) { - p.tx(" " + context.formatPhrase(RenderingContext.RES_REND_LANGUAGE) + "\""+lang+"\") "); + if (context.getLocale() != null) { + String langSuffix = "-"+context.getLocale().toLanguageTag(); + x.an(context.prefixAnchor("hc"+r.getScopedId()+langSuffix)); } } - if (ir != null) { - plateStyle(div.para()).b().tx(context.formatPhrase(RenderingContext.RES_REND_SPEC_RULES) + " "+ir+"!"); - } - if (source != null) { - plateStyle(div.para()).tx(context.formatPhrase(RenderingContext.RES_REND_INFO_SOURCE) + " "+source+"!"); - } - if (meta != null) { - PropertyWrapper pl = meta.getChildByName("profile"); - if (pl.hasValues()) { - XhtmlNode p = plateStyle(div.para()); - p.tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_PROF), pl.getValues().size())+": "); - boolean first = true; - for (BaseWrapper bw : pl.getValues()) { - if (first) first = false; else p.tx(", "); - renderCanonical(r, p, bw.getBase().primitiveValue()); + + if (context.isTechnicalMode()) { + RenderingStatus status = new RenderingStatus(); + + String lang = r.primitiveValue("language"); + String ir = r.primitiveValue("implicitRules"); + ResourceWrapper meta = r.has("meta") && !r.child("meta").isEmpty() ? r.child("meta") : null; + ResourceWrapper versionId = meta == null ? null : meta.child("versionId"); + ResourceWrapper lastUpdated = meta == null ? null : meta.child("lastUpdated"); + ResourceWrapper source = meta == null ? null : meta.child("source"); + + if (lang != null || versionId != null || lastUpdated != null || ir != null || source != null) { + XhtmlNode div = x.div().style("display: inline-block").style("background-color: #d9e0e7").style("padding: 6px") + .style("margin: 4px").style("border: 1px solid #8da1b4") + .style("border-radius: 5px").style("line-height: 60%"); + + boolean sfirst = true; + p = plateStyle(div.para()); + if (versionId != null) { + p.tx(context.formatPhrase(RenderingContext.RES_REND_VER, versionId)); + sfirst = false; } - } - PropertyWrapper tl = meta.getChildByName("tag"); - if (tl.hasValues()) { - XhtmlNode p = plateStyle(div.para()); - p.tx(Utilities.pluralize(context.formatPhrase(RenderingContext.RES_REND_TAG), tl.getValues().size())+": "); - boolean first = true; - for (BaseWrapper bw : tl.getValues()) { - if (first) first = false; else p.tx(", "); - String system = getPrimitiveValue(bw, "system"); - String version = getPrimitiveValue(bw, "version"); - String code = getPrimitiveValue(bw, "system"); - String display = getPrimitiveValue(bw, "system"); - renderCoding(p, new Coding(system, version, code, display)); - } - } - PropertyWrapper sl = meta.getChildByName("security"); - if (sl.hasValues()) { - XhtmlNode p = plateStyle(div.para()); - p.tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_SECURITY_LABEL), tl.getValues().size())+": "); - boolean first = true; - for (BaseWrapper bw : sl.getValues()) { - if (first) first = false; else p.tx(", "); - String system = getPrimitiveValue(bw, "system"); - String version = getPrimitiveValue(bw, "version"); - String code = getPrimitiveValue(bw, "system"); - String display = getPrimitiveValue(bw, "system"); - renderCoding(p, new Coding(system, version, code, display)); - } + if (lastUpdated != null) { + if (!sfirst) { + p.tx("; "); + } + p.tx(context.formatPhrase(RenderingContext.RES_REND_UPDATED, displayDataType(lastUpdated))); + sfirst = false; + } + if (lang != null) { + if (!sfirst) { + p.tx("; "); + } + p.tx(context.formatPhrase(RenderingContext.RES_REND_LANGUAGE, lang)); + sfirst = false; + } + if (source != null) { + if (!sfirst) { + p.tx("; "); + } + XhtmlNode pp = plateStyle(div.para()); + pp.startScript("source"); + renderDataType(status, pp.param("source"), source); + pp.execScript(context.formatPhrase(RenderingContext.RES_REND_INFO_SOURCE)); + pp.closeScript(); + sfirst = false; + } + if (ir != null) { + if (!sfirst) { + p.tx("; "); + } + plateStyle(div.para()).b().tx(context.formatPhrase(RenderingContext.RES_REND_SPEC_RULES, ir)); + sfirst = false; + } + if (meta != null) { + List items = meta.children("profile"); + if (!items.isEmpty()) { + p = plateStyle(div.para()); + p.tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_PROF), items.size())+": "); + boolean first = true; + for (ResourceWrapper bw : items) { + if (first) first = false; else p.tx(", "); + renderCanonical(status, p, StructureDefinition.class, bw); + } + } + items = meta.children("tag"); + if (!items.isEmpty()) { + p = plateStyle(div.para()); + p.tx(Utilities.pluralize(context.formatPhrase(RenderingContext.RES_REND_TAG), items.size())+": "); + boolean first = true; + for (ResourceWrapper bw : items) { + if (first) first = false; else p.tx(", "); + renderCoding(status, p, bw); + } + } + items = meta.children("security"); + if (!items.isEmpty()) { + p = plateStyle(div.para()); + p.tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_SECURITY_LABEL), items.size())+": "); + boolean first = true; + for (ResourceWrapper bw : items) { + if (first) first = false; else p.tx(", "); + renderCoding(status, p, bw); + } + } + } + return div; } } - + return null; } private XhtmlNode plateStyle(XhtmlNode para) { return para.style("margin-bottom: 0px"); } - private String getPrimitiveValue(BaseWrapper b, String name) throws UnsupportedEncodingException, FHIRException, IOException { - return b != null && b.has(name) && b.getChildByName(name).hasValues() ? b.getChildByName(name).getValues().get(0).getBase().primitiveValue() : null; - } - - private String getPrimitiveValue(ResourceWrapper r, String name) throws UnsupportedEncodingException, FHIRException, IOException { - return r.has(name) && r.getChildByName(name).hasValues() ? r.getChildByName(name).getValues().get(0).getBase().primitiveValue() : null; - } - - public void renderOrError(DomainResource dr) { - try { - render(dr); - } catch (Exception e) { - XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); - x.para().tx(context.formatPhrase(RenderingContext.RES_REND_ERROR, e.getMessage())+" "); - dr.setText(null); - inject(dr, x, NarrativeStatus.GENERATED); - } - - } +// public void renderOrError(DomainResource dr) { +// try { +// render(dr); +// } catch (Exception e) { +// XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); +// x.para().tx(context.formatPhrase(RenderingContext.RES_REND_ERROR, e.getMessage())+" "); +// dr.setText(null); +// inject(dr, x, NarrativeStatus.GENERATED); +// } +// +// } public RendererType getRendererType() { return RendererType.NATIVE; } public class TableRowData { - private Map> cols = new HashMap<>(); + private Map> cols = new HashMap<>(); private TableData data; - public void value(String name, DataType value) { + public void value(String name, ResourceWrapper value) { if (!cols.containsKey(name)) { cols.put(name, new ArrayList<>()); } @@ -769,7 +953,7 @@ public abstract class ResourceRenderer extends DataRenderer { return cols.containsKey(name); } - public List get(String name) { + public List get(String name) { return cols.get(name); } @@ -802,7 +986,7 @@ public abstract class ResourceRenderer extends DataRenderer { } - public void renderTable(TableData provider, XhtmlNode x) throws FHIRFormatError, DefinitionException, IOException { + public void renderTable(RenderingStatus status, TableData provider, XhtmlNode x) throws FHIRFormatError, DefinitionException, IOException { List columns = new ArrayList<>(); for (String name : provider.getColumns()) { boolean hasData = false; @@ -830,25 +1014,221 @@ public abstract class ResourceRenderer extends DataRenderer { for (String col : columns) { XhtmlNode td = tr.td(); boolean first = true; - List list = row.get(col); + List list = row.get(col); if (list != null) { - for (DataType value : list) { + for (ResourceWrapper value : list) { if (first) first = false; else td.tx(", "); - render(td, value); + renderDataType(status, td, value); } } } } } } - - public void markLanguage(XhtmlNode x) { - x.setAttribute("lang", context.getLocale().toString()); - x.setAttribute("xml:lang", context.getLocale().toString()); - x.addTag(0, "hr"); - x.addTag(0, "p").b().tx(context.getLocale().getDisplayName()); - x.addTag(0, "hr"); + + public void renderOrError(ResourceWrapper dr) throws IOException { + try { + renderResource(dr); + } catch (Exception e) { + XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); + x.para().tx("Error rendering: " + e.getMessage()); + inject(dr, x, NarrativeStatus.GENERATED); + } } + public void genSummaryTable(RenderingStatus status, XhtmlNode x, CanonicalResource cr) throws IOException { + if (context.isShowSummaryTable() && cr != null) { + XhtmlNode tbl = x.table("grid"); + genSummaryTableContent(status, tbl, cr); + } + } + + + protected void genSummaryTableContent(RenderingStatus status, XhtmlNode tbl, CanonicalResource cr) throws IOException { + XhtmlNode tr; + if (cr.hasUrl()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_DEFINING_URL)+":"); + tr.td().tx(cr.getUrl()); + } else if (cr.hasExtension("http://hl7.org/fhir/5.0/StructureDefinition/extension-NamingSystem.url")) { + status.setExtensions(true); + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_DEFINING_URL)); + tr.td().tx(ToolingExtensions.readStringExtension(cr, "http://hl7.org/fhir/5.0/StructureDefinition/extension-NamingSystem.url")+":"); + } else if (!context.isContained()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_DEFINING_URL)); + tr.td(); + } + if (cr.hasVersion()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_VER)+":"); + tr.td().tx(cr.getVersion()); + } else if (cr.hasExtension("http://terminology.hl7.org/StructureDefinition/ext-namingsystem-version")) { + status.setExtensions(true); + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_VER)+":"); + tr.td().tx(ToolingExtensions.readStringExtension(cr, "http://hl7.org/fhir/5.0/StructureDefinition/extension-NamingSystem.version")); + } + + String name = cr.hasName() ? context.getTranslated(cr.getNameElement()) : null; + String title = cr.hasTitle() ? context.getTranslated(cr.getTitleElement()) : null; + + if (name != null) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_NAME)+":"); + tr.td().tx(name); + } + + if (title != null && !title.equalsIgnoreCase(name)) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_TITLE)+":"); + tr.td().tx(title); + } + + if (cr.hasStatus() && !context.isContained()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_STATUS)+":"); + tr.td().tx(describeStatus(status, cr)); + } + + if (cr.hasDescription()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_DEFINITION)+":"); + tr.td().markdown(cr.getDescription(), "description"); + } + + if (cr.hasPublisher()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.CANON_REND_PUBLISHER)+":"); + tr.td().tx(buildPublisherLinks(cr)); + } + + if (cr.hasExtension(ToolingExtensions.EXT_WORKGROUP)) { + status.setExtensions(true); + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.CANON_REND_COMMITTEE)+":"); + tr.td().tx(renderCommitteeLink(cr)); + } + + if (cr.hasCopyright()) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_COPYRIGHT)+":"); + tr.td().markdown(cr.getDescription(), "copyright"); + } + + if (ToolingExtensions.hasExtension(cr, ToolingExtensions.EXT_FMM_LEVEL)) { + status.setExtensions(true); + // Use hard-coded spec link to point to current spec because DSTU2 had maturity listed on a different page + tr = tbl.tr(); + tr.td().ah("http://hl7.org/fhir/versions.html#maturity", "Maturity Level").attribute("class", "fmm").tx(context.formatPhrase(RenderingContext.CANON_REND_COMMITTEE)+":"); + tr.td().tx(ToolingExtensions.readStringExtension(cr, ToolingExtensions.EXT_FMM_LEVEL)); + } + } + + + protected String renderCommitteeLink(CanonicalResource cr) { + String code = ToolingExtensions.readStringExtension(cr, ToolingExtensions.EXT_WORKGROUP); + CodeSystem cs = context.getContext().fetchCodeSystem("http://terminology.hl7.org/CodeSystem/hl7-work-group"); + if (cs == null || !cs.hasWebPath()) + return code; + else { + ConceptDefinitionComponent cd = CodeSystemUtilities.findCode(cs.getConcept(), code); + if (cd == null) { + return code; + } else { + return ""+cd.getDisplay()+""; + } + } + } + + private String buildPublisherLinks(CanonicalResource cr) { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(". "); + boolean useName = false; + for (ContactDetail cd : cr.getContact()) { + if (!cd.hasName()) { + useName = true; + } + } + if (!useName) { + b.append(Utilities.escapeXml(cr.getPublisher())); + } + for (ContactDetail cd : cr.getContact()) { + String name = cd.hasName() ? cd.getName() : cr.getPublisher(); + b.append(renderContact(name, cd.getTelecom())); + } + return b.toString(); + } + + private String renderContact(String name, List telecom) { + List urls = new ArrayList<>(); + for (ContactPoint t : telecom) { + if (t.getSystem() == ContactPointSystem.URL && t.hasValue()) { + urls.add(t.getValue()); + } + } + StringBuilder b = new StringBuilder(); + if (urls.size() == 1) { + b.append(""+Utilities.escapeXml(name)+""); + } else if (urls.size() == 1) { + b.append(Utilities.escapeXml(name)); + } + for (ContactPoint t : telecom) { + b.append(", "); + if (t.getSystem() == ContactPointSystem.URL && t.hasValue() && urls.size() > 1) { + b.append("Link"); + } + if (t.getSystem() == ContactPointSystem.EMAIL && t.hasValue()) { + b.append("Email"); + } + if (t.getSystem() == ContactPointSystem.PHONE && t.hasValue()) { + b.append(Utilities.escapeXml(t.getValue())); + } + if (t.getSystem() == ContactPointSystem.FAX && t.hasValue()) { + b.append("Fax:"+Utilities.escapeXml(t.getValue())); + } + } + return b.toString(); + } + + protected String describeStatus(RenderingStatus status, CanonicalResource cr) { + String s = describeStatus(cr.getStatus(), cr.hasExperimental() ? cr.getExperimental() : false, cr.hasDate() ? cr.getDateElement() : null, ToolingExtensions.readBooleanExtension(cr, "http://hl7.org/fhir/StructureDefinition/valueset-deprecated")); + if (cr.hasExtension(ToolingExtensions.EXT_STANDARDS_STATUS)) { + status.setExtensions(true); + s = s + presentStandardsStatus(ToolingExtensions.readStringExtension(cr, ToolingExtensions.EXT_STANDARDS_STATUS)); + } + return s; + } + + private String presentStandardsStatus(String code) { + String pfx = " (Standards Status: "; + switch (code) { + case "draft" : return pfx+"Draft)"; + case "normative" : return pfx+"Normative)"; + case "trial-use" : return pfx+"Trial Use)"; + case "informative" : return pfx+"Informative)"; + case "deprecated" : return pfx+"Deprecated)"; + case "external" : return pfx+"External)"; + } + return ""; + } + + protected String describeStatus(PublicationStatus status, boolean experimental, DateTimeType dt, Boolean deprecated) { + String sfx = dt != null ? " as of "+displayDataType(dt) : ""; + if (deprecated != null && deprecated) { + if (status == PublicationStatus.RETIRED) { + return "Deprecated + Retired"+sfx; + } else { + return "Deprecated"+sfx; + } + } else { + switch (status) { + case ACTIVE: return (experimental ? "Experimental" : "Active")+sfx; + case DRAFT: return "Draft"+sfx; + case RETIRED: return "Retired"+sfx; + default: return "Unknown"+sfx; + } + } + } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java index ff3734ef3..af0cf7c82 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SearchParameterRenderer.java @@ -4,8 +4,9 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; +import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r5.model.CodeType; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.model.Enumeration; import org.hl7.fhir.r5.model.Enumerations.SearchComparator; import org.hl7.fhir.r5.model.Enumerations.SearchModifierCode; @@ -18,7 +19,7 @@ import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.StandardsStatus; @@ -27,19 +28,30 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class SearchParameterRenderer extends TerminologyRenderer { - public SearchParameterRenderer(RenderingContext context) { - super(context); - } - public SearchParameterRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); + public SearchParameterRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (SearchParameter) r.getBase()); + + render(status, x, (SearchParameter) r.getBase()); + } else { + throw new Error("SearchParameterRenderer only renders native resources directly"); + } } - public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome { - return render(x, (SearchParameter) dr); + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public boolean render(XhtmlNode x, SearchParameter spd) throws IOException, FHIRException, EOperationOutcome { + public void render(RenderingStatus status, XhtmlNode x, SearchParameter spd) throws IOException, FHIRException, EOperationOutcome { XhtmlNode h2 = x.h2(); h2.addText(spd.getName()); StandardsStatus ss = ToolingExtensions.getStandardsStatus(spd); @@ -61,7 +73,7 @@ public class SearchParameterRenderer extends TerminologyRenderer { StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.getCode()); if (sd != null && sd.hasWebPath()) { td.sep(", "); - td.ah(sd.getWebPath()).tx(t.getCode()); + td.ah(context.prefixLocalHref(context.prefixLocalHref(sd.getWebPath()))).tx(t.getCode()); } else { td.sep(", "); td.tx(t.getCode()); @@ -84,13 +96,13 @@ public class SearchParameterRenderer extends TerminologyRenderer { tr.td().tx(Utilities.pluralize(context.formatPhrase(RenderingContext.SEARCH_PAR_REND_TARGET), spd.getTarget().size())); td = tr.td(); if (isAllConcreteResources(spd.getTarget())) { - td.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "resourcelist.html")).tx(context.formatPhrase(RenderingContext.SEARCH_PAR_RES)); + td.ah(context.prefixLocalHref(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "resourcelist.html"))).tx(context.formatPhrase(RenderingContext.SEARCH_PAR_RES)); } else { for (Enumeration t : spd.getTarget()) { StructureDefinition sd = context.getWorker().fetchTypeDefinition(t.getCode()); if (sd != null && sd.hasWebPath()) { td.sep(", "); - td.ah(sd.getWebPath()).tx(t.getCode()); + td.ah(context.prefixLocalHref(sd.getWebPath())).tx(t.getCode()); } else { td.sep(", "); td.tx(t.getCode()); @@ -154,14 +166,13 @@ public class SearchParameterRenderer extends TerminologyRenderer { tr = tbl.tr(); SearchParameter tsp = context.getWorker().fetchResource(SearchParameter.class, t.getDefinition(), spd); if (tsp != null && tsp.hasWebPath()) { - tr.td().ah(tsp.getWebPath()).tx(tsp.present()); + tr.td().ah(context.prefixLocalHref(tsp.getWebPath())).tx(tsp.present()); } else { tr.td().tx(t.getDefinition()); } tr.td().code().tx(t.getExpression()); } } - return false; } private boolean isAllConcreteResources(List> list) { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java index 8624f069f..bdd2f3fb5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureDefinitionRenderer.java @@ -1,106 +1,127 @@ package org.hl7.fhir.r5.renderers; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Stack; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang3.StringUtils; -import org.hl7.fhir.exceptions.DefinitionException; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation; -import org.hl7.fhir.r5.conformance.profile.BindingResolution; -import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; -import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.ElementChoiceGroup; -import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.ExtensionContext; -import org.hl7.fhir.r5.formats.IParser; -import org.hl7.fhir.r5.formats.IParser.OutputStyle; -import org.hl7.fhir.r5.formats.JsonParser; -import org.hl7.fhir.r5.formats.XmlParser; -import org.hl7.fhir.r5.model.ActorDefinition; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.BooleanType; -import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.CanonicalType; -import org.hl7.fhir.r5.model.CodeSystem; -import org.hl7.fhir.r5.model.CodeType; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.Coding; -import org.hl7.fhir.r5.model.DataType; -import org.hl7.fhir.r5.model.DecimalType; -import org.hl7.fhir.r5.model.Element; -import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.ElementDefinition.AdditionalBindingPurposeVS; -import org.hl7.fhir.r5.model.ElementDefinition.AggregationMode; -import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionExampleComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingComponent; -import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent; -import org.hl7.fhir.r5.model.ElementDefinition.PropertyRepresentation; -import org.hl7.fhir.r5.model.ElementDefinition.SlicingRules; -import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; -import org.hl7.fhir.r5.model.Enumeration; -import org.hl7.fhir.r5.model.Enumerations.BindingStrength; -import org.hl7.fhir.r5.model.Extension; -import org.hl7.fhir.r5.model.IdType; -import org.hl7.fhir.r5.model.IntegerType; -import org.hl7.fhir.r5.model.MarkdownType; -import org.hl7.fhir.r5.model.PrimitiveType; -import org.hl7.fhir.r5.model.Quantity; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StringType; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; -import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent; -import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; -import org.hl7.fhir.r5.model.UriType; -import org.hl7.fhir.r5.model.ValueSet; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; -import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.InternalMarkdownProcessor; -import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.RenderStyle; -import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.SourcedElementDefinition; -import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.FixedValueFormat; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.StructureDefinitionRendererMode; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; -import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; -import org.hl7.fhir.r5.utils.PublicationHacker; -import org.hl7.fhir.r5.utils.ToolingExtensions; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.apache.commons.lang3.StringUtils; +import org.hl7.fhir.exceptions.DefinitionException; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation; +import org.hl7.fhir.r5.conformance.profile.BindingResolution; +import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; +import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.ElementChoiceGroup; +import org.hl7.fhir.r5.conformance.profile.ProfileUtilities.ExtensionContext; +import org.hl7.fhir.r5.formats.IParser; +import org.hl7.fhir.r5.formats.IParser.OutputStyle; +import org.hl7.fhir.r5.formats.JsonParser; +import org.hl7.fhir.r5.formats.XmlParser; +import org.hl7.fhir.r5.model.ActorDefinition; +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.BooleanType; +import org.hl7.fhir.r5.model.CanonicalResource; +import org.hl7.fhir.r5.model.CanonicalType; +import org.hl7.fhir.r5.model.CodeSystem; +import org.hl7.fhir.r5.model.CodeType; +import org.hl7.fhir.r5.model.CodeableConcept; +import org.hl7.fhir.r5.model.Coding; +import org.hl7.fhir.r5.model.DataType; +import org.hl7.fhir.r5.model.DecimalType; +import org.hl7.fhir.r5.model.Element; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.ElementDefinition.AdditionalBindingPurposeVS; +import org.hl7.fhir.r5.model.ElementDefinition.AggregationMode; +import org.hl7.fhir.r5.model.ElementDefinition.DiscriminatorType; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionExampleComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingComponent; +import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionSlicingDiscriminatorComponent; +import org.hl7.fhir.r5.model.ElementDefinition.PropertyRepresentation; +import org.hl7.fhir.r5.model.ElementDefinition.SlicingRules; +import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; +import org.hl7.fhir.r5.model.Enumeration; +import org.hl7.fhir.r5.model.Extension; +import org.hl7.fhir.r5.model.IdType; +import org.hl7.fhir.r5.model.IntegerType; +import org.hl7.fhir.r5.model.MarkdownType; +import org.hl7.fhir.r5.model.PrimitiveType; +import org.hl7.fhir.r5.model.Quantity; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; +import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionMappingComponent; +import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; +import org.hl7.fhir.r5.model.UriType; +import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.FixedValueFormat; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.StructureDefinitionRendererMode; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; +import org.hl7.fhir.r5.utils.EOperationOutcome; +import org.hl7.fhir.r5.utils.PublicationHacker; +import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; -import org.hl7.fhir.utilities.MarkDownProcessor; -import org.hl7.fhir.utilities.StandardsStatus; -import org.hl7.fhir.utilities.TextFile; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.VersionUtilities; -import org.hl7.fhir.utilities.i18n.I18nConstants; -import org.hl7.fhir.utilities.i18n.RenderingI18nContext; -import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableGenerationMode; -import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; -import org.hl7.fhir.utilities.xhtml.NodeType; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; -import org.hl7.fhir.utilities.xhtml.XhtmlNodeList; +import org.hl7.fhir.utilities.MarkDownProcessor; +import org.hl7.fhir.utilities.StandardsStatus; +import org.hl7.fhir.utilities.TextFile; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.VersionUtilities; +import org.hl7.fhir.utilities.i18n.I18nConstants; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableGenerationMode; +import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; +import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlParser; public class StructureDefinitionRenderer extends ResourceRenderer { + public StructureDefinitionRenderer(RenderingContext context) { + super(context); + hostMd = new InternalMarkdownProcessor(); + corePath = context.getContext().getSpecUrl(); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (!r.isDirect()) { + throw new Error("StructureDefinitionRenderer only renders native resources directly"); + } + renderResourceTechDetails(r, x); + StructureDefinition sd = (StructureDefinition) r.getBase(); + genSummaryTable(status, x, sd); + if (context.getStructureMode() == StructureDefinitionRendererMode.DATA_DICT) { + renderDict(status, sd, sd.getDifferential().getElement(), x.table("dict"), false, GEN_MODE_DIFF, "", r); + } else { + x.getChildNodes().add(generateTable(status, context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false, + context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, context, "", r)); + } + status.setExtensions(true); + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + public enum RenderStyle { } @@ -196,7 +217,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } public void renderDetails(XhtmlNode f) { if (cr != null && cr.hasWebPath()) { - f.ah(cr.getWebPath()).tx(cr.present()); + f.ah(context.prefixLocalHref(cr.getWebPath())).tx(cr.present()); } else { f.code().tx(url); } @@ -270,7 +291,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { public void renderDetails(XhtmlNode f) { if (value.hasUserData("render.link")) { - f = f.ah(value.getUserString("render.link")); + f = f.ah(context.prefixLocalHref(value.getUserString("render.link"))); } f.tx(value.asStringValue()); } @@ -290,7 +311,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { public void renderDetails(XhtmlNode f) throws IOException { if (value.hasUserData("render.link")) { - f = f.ah(value.getUserString("render.link")); + f = f.ah(context.prefixLocalHref(value.getUserString("render.link"))); } f.tx(summarize(value)); } @@ -302,16 +323,6 @@ public class StructureDefinitionRenderer extends ResourceRenderer { private Map> sdMapCache = new HashMap<>(); private IMarkdownProcessor hostMd; - public StructureDefinitionRenderer(RenderingContext context) { - super(context); - hostMd = new InternalMarkdownProcessor(); - corePath = context.getContext().getSpecUrl(); - } - - public StructureDefinitionRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - public Map> getSdMapCache() { return sdMapCache; @@ -329,19 +340,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { this.hostMd = hostMd; } - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (StructureDefinition) dr); - } - public boolean render(XhtmlNode x, StructureDefinition sd) throws FHIRFormatError, DefinitionException, IOException { - if (context.getStructureMode() == StructureDefinitionRendererMode.DATA_DICT) { - renderDict(sd, sd.getDifferential().getElement(), x.table("dict"), false, GEN_MODE_DIFF, ""); - } else { - x.getChildNodes().add(generateTable(context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false, - context.getLink(KnownLinkType.SPEC), "", sd.getKind() == StructureDefinitionKind.LOGICAL, false, null, false, context, "")); - } - return true; - } public void describe(XhtmlNode x, StructureDefinition sd) { x.tx(display(sd)); @@ -351,22 +350,6 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return sd.present(); } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((StructureDefinition) r).present(); - } - - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } - - // private static final int AGG_NONE = 0; // private static final int AGG_IND = 1; // private static final int AGG_GR = 2; @@ -546,11 +529,13 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } - public XhtmlNode generateTable(String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath, - boolean logicalModel, boolean allInvariants, Set outputTracker, boolean mustSupport, RenderingContext rc, String anchorPrefix) throws IOException, FHIRException { + public XhtmlNode generateTable(RenderingStatus status, String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath, + boolean logicalModel, boolean allInvariants, Set outputTracker, boolean mustSupport, RenderingContext rc, String anchorPrefix, ResourceWrapper res) throws IOException, FHIRException { assert(diff != snapshot);// check it's ok to get rid of one of these HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defFile, anchorPrefix); + gen.setUniqueLocalPrefix(context.getUniqueLocalPrefix()); + List list; if (diff) list = supplementMissingDiffElements(profile); @@ -581,7 +566,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { profiles.add(profile); keyRows.clear(); - genElement(defFile == null ? null : defFile+"#", gen, model.getRows(), list.get(0), list, profiles, diff, profileBaseFileName, null, snapshot, corePath, imagePath, true, logicalModel, profile.getDerivation() == TypeDerivationRule.CONSTRAINT && usesMustSupport(list), allInvariants, null, mustSupport, rc, anchorPrefix, profile, columns); + genElement(status, defFile == null ? null : defFile+"#", gen, model.getRows(), list.get(0), list, profiles, diff, profileBaseFileName, null, snapshot, corePath, imagePath, true, logicalModel, profile.getDerivation() == TypeDerivationRule.CONSTRAINT && usesMustSupport(list), allInvariants, null, mustSupport, rc, anchorPrefix, profile, columns, res); try { return gen.generate(model, imagePath, 0, outputTracker); } catch (org.hl7.fhir.exceptions.FHIRException e) { @@ -714,8 +699,8 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return model; } - private Row genElement(String defPath, HierarchicalTableGenerator gen, List rows, ElementDefinition element, List all, List profiles, boolean showMissing, String profileBaseFileName, Boolean extensions, - boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean isConstraintMode, boolean allInvariants, Row slicingRow, boolean mustSupport, RenderingContext rc, String anchorPrefix, Resource srcSD, List columns) throws IOException, FHIRException { + private Row genElement(RenderingStatus status, String defPath, HierarchicalTableGenerator gen, List rows, ElementDefinition element, List all, List profiles, boolean showMissing, String profileBaseFileName, Boolean extensions, + boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean isConstraintMode, boolean allInvariants, Row slicingRow, boolean mustSupport, RenderingContext rc, String anchorPrefix, Resource srcSD, List columns, ResourceWrapper res) throws IOException, FHIRException { Row originalRow = slicingRow; StructureDefinition profile = profiles == null ? null : profiles.get(profiles.size()-1); Row typesRow = null; @@ -815,7 +800,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { genElementObligations(gen, element, columns, row, corePath, profile); break; case SUMMARY: - genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc, children.size() > 0, defPath, anchorPrefix, all); + genElementCells(status, gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc, children.size() > 0, defPath, anchorPrefix, all, res); break; } if (element.hasSlicing()) { @@ -935,7 +920,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } if (logicalModel || !child.getPath().endsWith(".id") || (child.getPath().endsWith(".id") && (profile != null) && (profile.getDerivation() == TypeDerivationRule.CONSTRAINT))) { - slicer = genElement(defPath, gen, parent.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, slicer, mustSupport, rc, anchorPrefix, srcSD, columns); + slicer = genElement(status, defPath, gen, parent.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, slicer, mustSupport, rc, anchorPrefix, srcSD, columns, res); } } } @@ -1076,9 +1061,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return left; } - public List genElementCells(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath, + public List genElementCells(RenderingStatus status, HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, StructureDefinition profile, Row typesRow, Row row, boolean hasDef, - boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows, RenderingContext rc, boolean walksIntoThis, String defPath, String anchorPrefix, List inScopeElements) throws IOException { + boolean ext, UnusedTracker used, String ref, String sName, Cell nameCell, boolean mustSupport, boolean allowSubRows, RenderingContext rc, boolean walksIntoThis, String defPath, String anchorPrefix, List inScopeElements, ResourceWrapper resource) throws IOException { List res = new ArrayList<>(); Cell gc = gen.new Cell(); row.getCells().add(gc); @@ -1121,7 +1106,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (extDefn == null) { res.add(genCardinality(gen, element, row, hasDef, used, null)); res.add(addCell(row, gen.new Cell(null, null, "?gen-e1? "+element.getType().get(0).getProfile(), null, null))); - res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements)); + res.add(generateDescription(status, gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements, resource)); } else { String name = element.hasSliceName() ? element.getSliceName() : urltail(eurl); nameCell.getPieces().get(0).setText(name); @@ -1134,7 +1119,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { else // if it's complex, we just call it nothing // genTypes(gen, row, extDefn.getSnapshot().getElement().get(0), profileBaseFileName, profile); res.add(addCell(row, gen.new Cell(null, null, "("+(context.formatPhrase(RenderingContext.STRUC_DEF_COMPLEX))+")", null, null))); - res.add(generateDescription(gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows, rc, inScopeElements)); + res.add(generateDescription(status, gen, row, element, extDefn.getElement(), used.used, null, extDefn.getUrl(), profile, corePath, imagePath, root, logicalModel, allInvariants, valueDefn, snapshot, mustSupport, allowSubRows, rc, inScopeElements, resource)); } } else { res.add(genCardinality(gen, element, row, hasDef, used, null)); @@ -1142,7 +1127,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { res.add(addCell(row, gen.new Cell())); else res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport)); - res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements)); + res.add(generateDescription(status, gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements, resource)); } } } else if (element != null) { @@ -1151,7 +1136,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { res.add(genTypes(gen, row, element, profileBaseFileName, profile, corePath, imagePath, root, mustSupport)); else res.add(addCell(row, gen.new Cell())); - res.add(generateDescription(gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements)); + res.add(generateDescription(status, gen, row, element, (ElementDefinition) element.getUserData(ProfileUtilities.UD_DERIVATION_POINTER), used.used, null, null, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc, inScopeElements, resource)); } return res; } @@ -1308,15 +1293,15 @@ public class StructureDefinitionRenderer extends ResourceRenderer { && element.getSlicing().getRules() != SlicingRules.CLOSED && element.getSlicing().getDiscriminator().size() == 1 && element.getSlicing().getDiscriminator().get(0).getPath().equals("url") && element.getSlicing().getDiscriminator().get(0).getType().equals(DiscriminatorType.VALUE); } - public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc) throws IOException, FHIRException { - return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, new ArrayList()); + public Cell generateDescription(RenderingStatus status, HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, ResourceWrapper res) throws IOException, FHIRException { + return generateDescription(status, gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, new ArrayList(), res); } - public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List inScopeElements) throws IOException, FHIRException { - return generateDescription(gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, inScopeElements); + public Cell generateDescription(RenderingStatus status, HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List inScopeElements, ResourceWrapper res) throws IOException, FHIRException { + return generateDescription(status, gen, row, definition, fallback, used, baseURL, url, profile, corePath, imagePath, root, logicalModel, allInvariants, null, snapshot, mustSupportOnly, allowSubRows, rc, inScopeElements, res); } - public Cell generateDescription(HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List inScopeElements) throws IOException, FHIRException { + public Cell generateDescription(RenderingStatus status, HierarchicalTableGenerator gen, Row row, ElementDefinition definition, ElementDefinition fallback, boolean used, String baseURL, String url, StructureDefinition profile, String corePath, String imagePath, boolean root, boolean logicalModel, boolean allInvariants, ElementDefinition valueDefn, boolean snapshot, boolean mustSupportOnly, boolean allowSubRows, RenderingContext rc, List inScopeElements, ResourceWrapper res) throws IOException, FHIRException { Cell c = gen.new Cell(); row.getCells().add(c); @@ -1695,7 +1680,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (!definition.getPath().contains(".") && profile.hasExtension(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)) { obr.seeObligations(profile.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)); } - obr.renderTable(gen, c, inScopeElements); + obr.renderTable(status, res, gen, c, inScopeElements); if (definition.hasMaxLength() && definition.getMaxLength()!=0) { if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); } @@ -3147,13 +3132,13 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (sd == null) { x.code().tx(type); } else { - x.ah(sd.getWebPath()).tx(sd.getTypeName()); + x.ah(context.prefixLocalHref(sd.getWebPath())).tx(sd.getTypeName()); } } return first ? null : x; } - public XhtmlNode generateExtensionTable(String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set outputTracker, RenderingContext rc, String defPath, String anchorPrefix) throws IOException, FHIRException { + public XhtmlNode generateExtensionTable(RenderingStatus status, String defFile, StructureDefinition ed, String imageFolder, boolean inlineGraphics, boolean full, String corePath, String imagePath, Set outputTracker, RenderingContext rc, String defPath, String anchorPrefix, ResourceWrapper res) throws IOException, FHIRException { HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, imageFolder, inlineGraphics, true, defPath, anchorPrefix); TableModel model = gen.initNormalTable(corePath, false, true, ed.getId()+(full ? "f" : "n"), true, TableGenerationMode.XHTML); @@ -3191,7 +3176,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (!child.getPath().endsWith(".id")) { List sdl = new ArrayList<>(); sdl.add(ed); - genElement(defFile == null ? "" : defFile+"-definitions.html#extension.", gen, r.getSubRows(), child, ed.getSnapshot().getElement(), sdl, true, defFile, true, full, corePath, imagePath, true, false, false, false, null, false, rc, "", ed, null); + genElement(status, defFile == null ? "" : defFile+"-definitions.html#extension.", gen, r.getSubRows(), child, ed.getSnapshot().getElement(), sdl, true, defFile, true, full, corePath, imagePath, true, false, false, false, null, false, rc, "", ed, null, res); } } else if (deep) { List children = new ArrayList(); @@ -3215,7 +3200,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { r1.getCells().add(gen.new Cell(null, null, describeCardinality(c, null, new UnusedTracker()), null, null)); genTypes(gen, r1, ved, defFile, ed, corePath, imagePath, false, false); r1.setIcon("icon_"+m+"extension_simple.png", context.formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_SIMPLE)); - generateDescription(gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc, new ArrayList()); + generateDescription(status, gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc, new ArrayList(), res); } } } else { @@ -3295,7 +3280,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return null; } - public void renderDict(StructureDefinition sd, List elements, XhtmlNode t, boolean incProfiledOut, int mode, String anchorPrefix) throws FHIRException, IOException { + public void renderDict(RenderingStatus status, StructureDefinition sd, List elements, XhtmlNode t, boolean incProfiledOut, int mode, String anchorPrefix, ResourceWrapper res) throws FHIRException, IOException { int i = 0; Map allAnchors = new HashMap<>(); List excluded = new ArrayList<>(); @@ -3320,7 +3305,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { XhtmlNode tr = t.tr(); XhtmlNode sp = renderStatus(ec, tr.td("structure").colspan(2).spanClss("self-link-parent")); for (String s : anchors) { - sp.an(s).tx(" "); + sp.an(context.prefixAnchor(s)).tx(" "); } sp.span("color: grey", null).tx(Integer.toString(i++)); sp.b().tx(". "+title); @@ -3328,7 +3313,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (isProfiledExtension(ec)) { StructureDefinition extDefn = context.getContext().fetchResource(StructureDefinition.class, ec.getType().get(0).getProfile().get(0).getValue()); if (extDefn == null) { - generateElementInner(t, sd, ec, 1, null, compareElement, null, false, "", anchorPrefix, elements); + generateElementInner(status, t, sd, ec, 1, null, compareElement, null, false, "", anchorPrefix, elements, res); } else { ElementDefinition valueDefn = getExtensionValueDefinition(extDefn); ElementDefinition compareValueDefn = null; @@ -3336,15 +3321,15 @@ public class StructureDefinitionRenderer extends ResourceRenderer { StructureDefinition compareExtDefn = context.getContext().fetchResource(StructureDefinition.class, compareElement.getType().get(0).getProfile().get(0).getValue()); compareValueDefn = getExtensionValueDefinition(extDefn); } catch (Exception except) {} - generateElementInner(t, sd, ec, valueDefn == null || valueDefn.prohibited() ? 2 : 3, valueDefn, compareElement, compareValueDefn, false, "", anchorPrefix, elements); + generateElementInner(status, t, sd, ec, valueDefn == null || valueDefn.prohibited() ? 2 : 3, valueDefn, compareElement, compareValueDefn, false, "", anchorPrefix, elements, res); // generateElementInner(b, extDefn, extDefn.getSnapshot().getElement().get(0), valueDefn == null ? 2 : 3, valueDefn); } } else { while (!dstack.isEmpty() && !isParent(dstack.peek(), ec)) { - finish(t, sd, dstack.pop(), mode, "", anchorPrefix); + finish(status, t, sd, dstack.pop(), mode, "", anchorPrefix, res); } dstack.push(ec); - generateElementInner(t, sd, ec, mode, null, compareElement, null, false, "", anchorPrefix, elements); + generateElementInner(status, t, sd, ec, mode, null, compareElement, null, false, "", anchorPrefix, elements, res); if (ec.hasSlicing()) { generateSlicing(t, sd, ec, ec.getSlicing(), compareElement, mode, false); } @@ -3354,12 +3339,12 @@ public class StructureDefinitionRenderer extends ResourceRenderer { i++; } while (!dstack.isEmpty()) { - finish(t, sd, dstack.pop(), mode, "", anchorPrefix); + finish(status, t, sd, dstack.pop(), mode, "", anchorPrefix, res); } - finish(t, sd, null, mode, "", anchorPrefix); + finish(status, t, sd, null, mode, "", anchorPrefix, res); } - private void finish(XhtmlNode t, StructureDefinition sd, ElementDefinition ed, int mode, String defPath, String anchorPrefix) throws FHIRException, IOException { + private void finish(RenderingStatus status, XhtmlNode t, StructureDefinition sd, ElementDefinition ed, int mode, String defPath, String anchorPrefix, ResourceWrapper res) throws FHIRException, IOException { for (Base b : VersionComparisonAnnotation.getDeleted(ed == null ? sd : ed, "element")) { ElementDefinition ec = (ElementDefinition) b; @@ -3369,7 +3354,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { sp.span("color: grey", null).tx("--"); sp.b().tx(". "+title); - generateElementInner(t, sd, ec, mode, null, null, null, true, defPath, anchorPrefix, new ArrayList()); + generateElementInner(status, t, sd, ec, mode, null, null, null, true, defPath, anchorPrefix, new ArrayList(), res); if (ec.hasSlicing()) { generateSlicing(t, sd, ec, ec.getSlicing(), null, mode, true); } @@ -3516,7 +3501,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { private void link(XhtmlNode x, String id, String anchorPrefix) { - var ah = x.ah("#" + anchorPrefix + id); + var ah = x.ah(context.prefixLocalHref("#" + anchorPrefix + id)); ah.attribute("title", "link to here"); ah.attribute("class", "self-link"); var svg = ah.svg(); @@ -3627,7 +3612,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); if (mode != GEN_MODE_KEY) { if (newStr != null) { - renderStatus(source, x).ah(nLink).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); + renderStatus(source, x).ah(context.prefixLocalHref(nLink)).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); } else if (VersionComparisonAnnotation.hasDeleted(parent, name)) { PrimitiveType p = (PrimitiveType) VersionComparisonAnnotation.getDeletedItem(parent, name); renderStatus(p, x).txOrCode(code, p.primitiveValue()); @@ -3638,27 +3623,27 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (newStr==null || newStr.isEmpty()) { return null; } else { - renderStatus(source, x).ah(nLink).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); + renderStatus(source, x).ah(context.prefixLocalHref(nLink)).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); } } else if (oldStr!=null && !oldStr.isEmpty() && (newStr==null || newStr.isEmpty())) { if (mode == GEN_MODE_DIFF) { return null; } else { - removed(x).ah(oLink).txOrCode(code, oldStr).iff(externalO).txN(" ").img("external.png", null); + removed(x).ah(context.prefixLocalHref(oLink)).txOrCode(code, oldStr).iff(externalO).txN(" ").img("external.png", null); } } else if (oldStr.equals(newStr)) { if (mode==GEN_MODE_DIFF) { return null; } else { - unchanged(x).ah(nLink).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); + unchanged(x).ah(context.prefixLocalHref(nLink)).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); } } else if (newStr.startsWith(oldStr)) { - unchanged(x).ah(oLink).txOrCode(code, oldStr).iff(externalO).txN(" ").img("external.png", null); - renderStatus(source, x).ah(nLink).txN(newStr.substring(oldStr.length())).iff(externalN).txN(" ").img("external.png", null); + unchanged(x).ah(context.prefixLocalHref(oLink)).txOrCode(code, oldStr).iff(externalO).txN(" ").img("external.png", null); + renderStatus(source, x).ah(context.prefixLocalHref(nLink)).txN(newStr.substring(oldStr.length())).iff(externalN).txN(" ").img("external.png", null); } else { // TODO: improve comparision in this fall-through case, by looking for matches in sub-paragraphs? - renderStatus(source, x).ah(nLink).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); - removed(x).ah(oLink).txOrCode(code, oldStr).iff(externalO).txN(" ").img("external.png", null); + renderStatus(source, x).ah(context.prefixLocalHref(nLink)).txOrCode(code, newStr).iff(externalN).txN(" ").img("external.png", null); + removed(x).ah(context.prefixLocalHref(oLink)).txOrCode(code, oldStr).iff(externalO).txN(" ").img("external.png", null); } return x; } @@ -3689,7 +3674,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { return "color:DarkGray;text-decoration:line-through"; } - private void generateElementInner(XhtmlNode tbl, StructureDefinition sd, ElementDefinition d, int mode, ElementDefinition value, ElementDefinition compare, ElementDefinition compareValue, boolean strikethrough, String defPath, String anchorPrefix, List inScopeElements) throws FHIRException, IOException { + private void generateElementInner(RenderingStatus status, XhtmlNode tbl, StructureDefinition sd, ElementDefinition d, int mode, ElementDefinition value, ElementDefinition compare, ElementDefinition compareValue, boolean strikethrough, String defPath, String anchorPrefix, List inScopeElements, ResourceWrapper res) throws FHIRException, IOException { boolean root = !d.getPath().contains("."); boolean slicedExtension = d.hasSliceName() && (d.getPath().endsWith(".extension") || d.getPath().endsWith(".modifierExtension")); // int slicedExtensionMode = (mode == GEN_MODE_KEY) && slicedExtension ? GEN_MODE_SNAP : mode; // see ProfileUtilities.checkExtensionDoco / Task 3970 @@ -3783,7 +3768,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { tableRow(tbl, context.formatPhrase(RenderingContext.STRUC_DEF_COMP_PROF), "http://hl7.org/fhir/extensions/StructureDefinition-structuredefinition-compliesWithProfile.html", strikethrough, renderCanonicalListExt(context.formatPhrase(RenderingContext.STRUC_DEF_PROF_COMP)+" ", sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_COMPLIES_WITH_PROFILE))); } - tableRow(tbl, context.formatPhrase(RenderingContext.GENERAL_OBLIG), null, strikethrough, describeObligations(d, root, sd, defPath, anchorPrefix, inScopeElements)); + tableRow(tbl, context.formatPhrase(RenderingContext.GENERAL_OBLIG), null, strikethrough, describeObligations(status, d, root, sd, defPath, anchorPrefix, inScopeElements, res)); if (d.hasExtension(ToolingExtensions.EXT_EXTENSION_STYLE)) { String es = d.getExtensionString(ToolingExtensions.EXT_EXTENSION_STYLE); @@ -3881,7 +3866,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (sd == null) { x.code().tx(t); } else { - x.ah(sd.getWebPath(), t).tx(sd.present()); + x.ah(context.prefixLocalHref(sd.getWebPath()), t).tx(sd.present()); } return x; } @@ -3985,7 +3970,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } } - private XhtmlNode describeObligations(ElementDefinition d, boolean root, StructureDefinition sdx, String defPath, String anchorPrefix, List inScopeElements) throws IOException { + private XhtmlNode describeObligations(RenderingStatus status, ElementDefinition d, boolean root, StructureDefinition sdx, String defPath, String anchorPrefix, List inScopeElements, ResourceWrapper res) throws IOException { XhtmlNode ret = new XhtmlNode(NodeType.Element, "div"); ObligationsRenderer obr = new ObligationsRenderer(corePath, sdx, d.getPath(), context, hostMd, this); obr.seeObligations(d.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_CORE, ToolingExtensions.EXT_OBLIGATION_TOOLS)); @@ -4004,9 +3989,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (sd == null) { bb.code().tx(iu); } else if (sd.hasWebPath()) { - bb.ah(sd.getWebPath()).tx(sd.present()); + bb.ah(context.prefixLocalHref(sd.getWebPath())).tx(sd.present()); } else { - bb.ah(iu).tx(sd.present()); + bb.ah(context.prefixLocalHref(iu)).tx(sd.present()); } } if (ul.isEmpty()) { @@ -4015,7 +4000,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { } if (obr.hasObligations()) { XhtmlNode tbl = ret.table("grid"); - obr.renderTable(tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements); + obr.renderTable(status, res, tbl.getChildNodes(), true, defPath, anchorPrefix, inScopeElements); if (tbl.isEmpty()) { ret.remove(tbl); } @@ -4050,9 +4035,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (cr == null) { x.code().tx(url); } else if (!cr.hasWebPath()) { - x.ah(url).tx(cr.present()); + x.ah(context.prefixLocalHref(url)).tx(cr.present()); } else { - x.ah(cr.getWebPath()).tx(cr.present()); + x.ah(context.prefixLocalHref(cr.getWebPath())).tx(cr.present()); } } @@ -4187,7 +4172,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { tr.style("text-decoration: line-through"); } addFirstCell(name, defRef, tr); - tr.td().ah(link).tx(text); + tr.td().ah(context.prefixLocalHref(link)).tx(text); } } @@ -4199,9 +4184,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (defRef == null) { td.tx(name); } else if (Utilities.isAbsoluteUrl(defRef)) { - td.ah(defRef).tx(name); + td.ah(context.prefixLocalHref(defRef)).tx(name); } else { - td.ah(corePath+defRef).tx(name); + td.ah(context.prefixLocalHref(corePath+defRef)).tx(name); } } @@ -4222,14 +4207,14 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (name.equals("identifier")) { XhtmlNode ret = new XhtmlNode(NodeType.Element, "div"); ret.tx(context.formatPhrase(RenderingContext.STRUC_DEF_BUSINESS_ID)+" "); - ret.ah(corePath + "resource.html#identifiers").tx(context.formatPhrase(RenderingContext.STRUC_DEF_DISCUSSION)); + ret.ah(context.prefixLocalHref(corePath + "resource.html#identifiers")).tx(context.formatPhrase(RenderingContext.STRUC_DEF_DISCUSSION)); ret.tx(")"); return ret; } if (name.equals("version")) {// && !resource.equals("Device")) XhtmlNode ret = new XhtmlNode(NodeType.Element, "div"); ret.tx(context.formatPhrase(RenderingContext.STRUC_DEF_BUSINESS_VERID)+" "); - ret.ah(corePath + "resource.html#versions").tx(context.formatPhrase(RenderingContext.STRUC_DEF_DISCUSSION)); + ret.ah(context.prefixLocalHref(corePath + "resource.html#versions")).tx(context.formatPhrase(RenderingContext.STRUC_DEF_DISCUSSION)); ret.tx(")"); return ret; } @@ -4389,9 +4374,9 @@ public class StructureDefinitionRenderer extends ResourceRenderer { if (psd == null) { x.code().tx(type); } else if (psd.getWebPath() == null) { - x.ah(type).tx(type); + x.ah(context.prefixLocalHref(type)).tx(type); } else { - x.ah(psd.getWebPath()).tx(type); + x.ah(context.prefixLocalHref(psd.getWebPath())).tx(type); } } x.tx(">"); @@ -4491,7 +4476,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { private void getTypeLink(XhtmlNode x, TypeRefComponent t, StructureDefinition sd) { String s = context.getPkp().getLinkFor(sd.getWebPath(), t.getWorkingCode()); if (s != null) { - x.ah(s).tx(t.getWorkingCode()); + x.ah(context.prefixLocalHref(s)).tx(t.getWorkingCode()); } else { x.code().tx(t.getWorkingCode()); } @@ -4607,7 +4592,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer { span.br(); span.tx("("); if (binding.hasStrength()) { - span.ah(Utilities.pathURL(corePath, "terminologies.html#"+binding.getStrength().toCode())).tx(binding.getStrength().toCode()); + span.ah(context.prefixLocalHref(Utilities.pathURL(corePath, "terminologies.html#"+binding.getStrength().toCode()))).tx(binding.getStrength().toCode()); } if (binding.hasStrength() && binding.hasValueSet()) { span.tx(" "); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureMapRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureMapRenderer.java index d07fa3094..5ddd14226 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureMapRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/StructureMapRenderer.java @@ -9,20 +9,22 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.r5.model.CodeSystem; -import org.hl7.fhir.r5.model.CodeType; import org.hl7.fhir.r5.model.ConceptMap; +import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent; +import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent; +import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.model.Enumeration; -import org.hl7.fhir.r5.model.IdType; import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship; -import org.hl7.fhir.r5.model.Enumerations.SearchComparator; -import org.hl7.fhir.r5.model.Enumerations.SearchModifierCode; -import org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll; +import org.hl7.fhir.r5.model.IdType; import org.hl7.fhir.r5.model.OperationDefinition; import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.SearchParameter; -import org.hl7.fhir.r5.model.SearchParameter.SearchParameterComponentComponent; +import org.hl7.fhir.r5.model.StringType; +import org.hl7.fhir.r5.model.StructureDefinition; +import org.hl7.fhir.r5.model.StructureMap; import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupComponent; import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupInputComponent; import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleComponent; @@ -33,27 +35,40 @@ import org.hl7.fhir.r5.model.StructureMap.StructureMapGroupRuleTargetParameterCo import org.hl7.fhir.r5.model.StructureMap.StructureMapStructureComponent; import org.hl7.fhir.r5.model.StructureMap.StructureMapTargetListMode; import org.hl7.fhir.r5.model.StructureMap.StructureMapTransform; -import org.hl7.fhir.r5.model.StringType; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.StructureMap; import org.hl7.fhir.r5.model.UriType; -import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent; -import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent; -import org.hl7.fhir.r5.model.DataType; import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; -import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities; -import org.hl7.fhir.utilities.StandardsStatus; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.VersionUtilities; -import org.hl7.fhir.utilities.xhtml.XhtmlFluent; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class StructureMapRenderer extends TerminologyRenderer { + public StructureMapRenderer(RenderingContext context) { + super(context); + } + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (r.isDirect()) { + renderResourceTechDetails(r, x); + genSummaryTable(status, x, (StructureMap) r.getBase()); + renderMap(status, x.pre("fml"), (StructureMap) r.getBase()); + } else { + throw new Error("StructureMapRenderer only renders native resources directly"); + } + } + + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } + + + private static final String COLOR_COMMENT = "green"; private static final String COLOR_METADATA = "#cc00cc"; private static final String COLOR_CONST = "blue"; @@ -62,24 +77,8 @@ public class StructureMapRenderer extends TerminologyRenderer { private static final boolean MULTIPLE_TARGETS_ONELINE = true; private static final String COLOR_SPECIAL = "#b36b00"; - public StructureMapRenderer(RenderingContext context) { - super(context); - } - - public StructureMapRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - - public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome { - return render(x, (StructureMap) dr); - } - - public boolean render(XhtmlNode x, StructureMap map) throws IOException, FHIRException, EOperationOutcome { - renderMap(x.pre("fml"), map); - return false; - } - - public void renderMap(XhtmlNode x, StructureMap map) { + public void renderMap(RenderingStatus status, XhtmlNode x, StructureMap map) { + x.tx("\r\n"); if (VersionUtilities.isR5Plus(context.getContext().getVersion())) { renderMetadata(x, "url", map.getUrlElement()); @@ -155,7 +154,7 @@ public class StructureMapRenderer extends TerminologyRenderer { x.color(COLOR_SYNTAX).tx(" = \""); CodeSystem cs = context.getContext().fetchResource(CodeSystem.class, cg.getSource()); if (cs != null && cs.hasWebPath()) { - x.ah(cs.getWebPath(), cs.present()).tx(cg.getSource()); + x.ah(context.prefixLocalHref(cs.getWebPath()), cs.present()).tx(cg.getSource()); } else { x.tx(cg.getSource()); } @@ -169,7 +168,7 @@ public class StructureMapRenderer extends TerminologyRenderer { x.color(COLOR_SYNTAX).tx(" = \""); CodeSystem cs = context.getContext().fetchResource(CodeSystem.class, cg.getTarget()); if (cs != null && cs.hasWebPath()) { - x.ah(cs.getWebPath(), cs.present()).tx(cg.getTarget()); + x.ah(context.prefixLocalHref(cs.getWebPath()), cs.present()).tx(cg.getTarget()); } else { x.tx(""+cg.getTarget()); } @@ -257,7 +256,7 @@ public class StructureMapRenderer extends TerminologyRenderer { x.color(COLOR_SYNTAX).tx(" \""); StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, s.getUrl()); if (sd != null && sd.hasWebPath()) { - x.ah(sd.getWebPath(), sd.present()).tx(s.getUrl()); + x.ah(context.prefixLocalHref(sd.getWebPath()), sd.present()).tx(s.getUrl()); } else { x.tx(s.getUrl()); } @@ -282,7 +281,7 @@ public class StructureMapRenderer extends TerminologyRenderer { x.color(COLOR_SYNTAX).tx(" \""); StructureMap m = context.getContext().fetchResource(StructureMap.class, s.getValue()); if (m != null) { - x.ah(m.getWebPath(), m.present()).tx(s.getValue()); + x.ah(context.prefixLocalHref(m.getWebPath()), m.present()).tx(s.getValue()); } else { x.tx(s.getValue()); } @@ -322,7 +321,7 @@ public class StructureMapRenderer extends TerminologyRenderer { x.b().tx(" extends "); String ref = resolveRuleReference(g.getExtendsElement()); if (ref != null) { - x.ah(ref).tx(g.getExtends()); + x.ah(context.prefixLocalHref(ref)).tx(g.getExtends()); } else { x.tx(g.getExtends()); } @@ -412,7 +411,7 @@ public class StructureMapRenderer extends TerminologyRenderer { x.color(COLOR_SYNTAX).tx(", "); String ref = resolveRuleReference(rd.getNameElement()); if (ref != null) { - x.ah(ref).tx(rd.getName()); + x.ah(context.prefixLocalHref(ref)).tx(rd.getName()); } else { x.tx(rd.getName()); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SubscriptionTopicRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SubscriptionTopicRenderer.java index 8484efa9f..73d9265ad 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SubscriptionTopicRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/SubscriptionTopicRenderer.java @@ -4,168 +4,141 @@ import java.io.IOException; 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.model.Enumeration; -import org.hl7.fhir.r5.model.Enumerations.SearchComparator; -import org.hl7.fhir.r5.model.Enumerations.SearchModifierCode; -import org.hl7.fhir.r5.model.Library; +import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.MarkdownType; -import org.hl7.fhir.r5.model.Requirements; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StringType; -import org.hl7.fhir.r5.model.SubscriptionTopic; -import org.hl7.fhir.r5.model.SubscriptionTopic.InteractionTrigger; -import org.hl7.fhir.r5.model.SubscriptionTopic.SubscriptionTopicCanFilterByComponent; -import org.hl7.fhir.r5.model.SubscriptionTopic.SubscriptionTopicEventTriggerComponent; -import org.hl7.fhir.r5.model.SubscriptionTopic.SubscriptionTopicNotificationShapeComponent; -import org.hl7.fhir.r5.model.SubscriptionTopic.SubscriptionTopicResourceTriggerComponent; -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.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class SubscriptionTopicRenderer extends ResourceRenderer { - public SubscriptionTopicRenderer(RenderingContext context) { - super(context); + public SubscriptionTopicRenderer(RenderingContext context) { + super(context); + } + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } - public SubscriptionTopicRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper st) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(st, x); + genSummaryTable(status, x, (CanonicalResource) st.getResourceNative()); - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (SubscriptionTopic) dr); - } - - public boolean render(XhtmlNode x, SubscriptionTopic st) throws FHIRFormatError, DefinitionException, IOException { - - if (context.isHeader()) { - XhtmlNode h = x.h2(); - h.addText(st.hasTitle() ? st.getTitle() : st.getName()); - addMarkdown(x, st.getDescription()); - if (st.hasCopyright()) - generateCopyright(x, st); + XhtmlNode tbl = x.table("grid"); + XhtmlNode ttr = tbl.tr(); + ttr.td().b().tx("SubscriptionTopic"); + ttr.td().tx(context.getTranslated(st.has("title") ? st.child("title") : st.child("name"))); + if (st.has("description")) { + ttr = tbl.tr(); + ttr.td().b().tx("Description"); + addMarkdown(ttr.td(), st.primitiveValue("description")); } + if (st.has("copyright")) { + generateCopyrightTableRow(tbl, st); + } + - if (st.hasResourceTrigger()) { + if (st.has("resourceTrigger")) { TableData td = new TableData(context.formatPhrase(RenderingContext.SUB_TOPIC_RES_TRIG)); - for (SubscriptionTopicResourceTriggerComponent rt : st.getResourceTrigger()) { + for (ResourceWrapper rt : st.children("resourceTrigger")) { TableRowData tr = td.addRow(); - if (rt.hasResource()) { - tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.getResourceElement()); + if (rt.has("resource")) { + tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.child("resource")); } - for (Enumeration t : rt.getSupportedInteraction()) { + for (ResourceWrapper t : rt.children("supportedInteraction")) { tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_INT), t); } - if (rt.hasQueryCriteria()) { - StringBuilder md = new StringBuilder(); - if (rt.getQueryCriteria().hasPrevious()) { - md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_PREV, rt.getQueryCriteria().getPrevious()+"\r\n")+" "); + if (rt.has("queryCriteria")) { + StringBuilder md = new StringBuilder(); + ResourceWrapper qc = rt.child("queryCriteria"); + if (qc.has("previous")) { + md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_PREV, qc.primitiveValue("previous")+"\r\n")+" "); } - if (rt.getQueryCriteria().hasResultForCreate()) { - md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_CREATE, rt.getQueryCriteria().getResultForCreate()+"\r\n")+" "); + if (qc.has("resultForCreate")) { + md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_CREATE, qc.primitiveValue("resultForCreate")+"\r\n")+" "); } - if (rt.getQueryCriteria().hasCurrent()) { - md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_CREATE, rt.getQueryCriteria().getCurrent()+"\r\n")+" "); + if (qc.has("current")) { + md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_CREATE, qc.primitiveValue("current")+"\r\n")+" "); } - if (rt.getQueryCriteria().hasPrevious()) { - md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_DELETE, rt.getQueryCriteria().getResultForDelete()+"\r\n")+" "); + if (qc.has("previous")) { + md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_DELETE, qc.primitiveValue("resultForDelete")+"\r\n")+" "); } - if (rt.getQueryCriteria().hasRequireBoth()) { - md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_REQ, rt.getQueryCriteria().getRequireBoth()+"\r\n")+" "); + if (qc.has("requireBoth")) { + md.append(context.formatPhrase(RenderingContext.SUB_TOPIC_REQ, qc.primitiveValue("requireBoth")+"\r\n")+" "); } - tr.value(context.formatPhrase(RenderingContext.GENERAL_CRIT), new MarkdownType(md.toString())); + tr.value(context.formatPhrase(RenderingContext.GENERAL_CRIT), wrapNC(new MarkdownType(md.toString()))); } - if (rt.hasFhirPathCriteriaElement()) { - tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_FHIR_PATH), rt.getFhirPathCriteriaElement()); + if (rt.has("fhirPathCriteria")) { + tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_FHIR_PATH), rt.child("fhirPathCriteria")); } - if (rt.hasDescription()) { - tr.value(context.formatPhrase(RenderingContext.GENERAL_DESC), rt.getDescriptionElement()); + if (rt.has("description")) { + tr.value(context.formatPhrase(RenderingContext.GENERAL_DESC), rt.child("description")); } } - renderTable(td, x); + renderTable(status, td, x); } - if (st.hasEventTrigger()) { + if (st.has("eventTrigger")) { TableData td = new TableData("Event Triggers"); - for (SubscriptionTopicEventTriggerComponent rt : st.getEventTrigger()) { + for (ResourceWrapper rt : st.children("eventTrigger")) { TableRowData tr = td.addRow(); - if (rt.hasResource()) { - tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.getResourceElement()); + if (rt.has("resource")) { + tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.child("resource")); } - if (rt.hasEvent()) { - tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_EVENT), rt.getEvent()); + if (rt.has("event(")) { + tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_EVENT), rt.child("event")); } - if (rt.hasDescription()) { - tr.value(context.formatPhrase(RenderingContext.GENERAL_DESC), rt.getDescriptionElement()); + if (rt.has("description")) { + tr.value(context.formatPhrase(RenderingContext.GENERAL_DESC), rt.child("description")); } } - renderTable(td, x); + renderTable(status, td, x); } - if (st.hasCanFilterBy()) { + if (st.has("canFilterBy")) { TableData td = new TableData("Can Filter By"); - for (SubscriptionTopicCanFilterByComponent rt : st.getCanFilterBy()) { + for (ResourceWrapper rt : st.children("canFilterBy")) { TableRowData tr = td.addRow(); - if (rt.hasResource()) { - tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.getResourceElement()); + if (rt.has("resource")) { + tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.child("resource")); } - if (rt.hasFilterParameter()) { - tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_FILT_PAR), rt.getFilterParameterElement()); + if (rt.has("filterParameter")) { + tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_FILT_PAR), rt.child("filterParameter")); } - if (rt.hasFilterDefinition()) { - tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_FILT_DEF), rt.getFilterDefinitionElement()); + if (rt.has("filterDefinition")) { + tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_FILT_DEF), rt.child("filterDefinition")); } - for (Enumeration t : rt.getComparator()) { + for (ResourceWrapper t : rt.children("comparator")) { tr.value(context.formatPhrase(RenderingContext.GENERAL_COMPARATORS), t); } - for (Enumeration t : rt.getModifier()) { + for (ResourceWrapper t : rt.children("modifier")) { tr.value(context.formatPhrase(RenderingContext.GENERAL_MODIFIERS), t); } } - renderTable(td, x); + renderTable(status, td, x); } - if (st.hasNotificationShape()) { + if (st.has("notificationShape")) { TableData td = new TableData("Notification Shapes"); - for (SubscriptionTopicNotificationShapeComponent rt : st.getNotificationShape()) { + for (ResourceWrapper rt : st.children("notificationShape")) { TableRowData tr = td.addRow(); - if (rt.hasResource()) { - tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.getResourceElement()); + if (rt.has("resource")) { + tr.value(context.formatPhrase(RenderingContext.GENERAL_RESOURCE), rt.child("resource")); } - for (StringType t : rt.getInclude()) { + for (ResourceWrapper t : rt.children("include")) { tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_INCL), t); } - for (StringType t : rt.getRevInclude()) { + for (ResourceWrapper t : rt.children("revInclude")) { tr.value(context.formatPhrase(RenderingContext.SUB_TOPIC_REV_INCL), t); } } - renderTable(td, x); + renderTable(status, td, x); } - - return false; - } - - public void describe(XhtmlNode x, Library lib) { - x.tx(display(lib)); - } - - public String display(Library lib) { - return lib.present(); - } - - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return ((Library) r).present(); - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - return "??"; } } 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 bfea1ffef..4f19db591 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 @@ -8,7 +8,6 @@ import java.util.Map; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; @@ -22,9 +21,7 @@ import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; -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.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; import org.hl7.fhir.r5.utils.ToolingExtensions; @@ -41,24 +38,10 @@ public abstract class TerminologyRenderer extends ResourceRenderer { super(context); } - public TerminologyRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } - public String display(Resource r) throws UnsupportedEncodingException, IOException { return ((CanonicalResource) r).present(); } - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - if (r.has("name")) { - return r.children("name").get(0).getBase().primitiveValue(); - } - return "??"; - } - protected class TargetElementComponentWrapper { protected ConceptMapGroupComponent group; protected TargetElementComponent comp; @@ -119,7 +102,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer { XhtmlNode td = tr.td(); XhtmlNode b = td.b(); String link = m.getLink(); - XhtmlNode a = b.ah(link); + XhtmlNode a = b.ah(context.prefixLocalHref(link)); a.addText(m.getDetails().getName()); if (m.getDetails().isDoDescription() && m.getMap().hasDescription()) addMarkdown(td, m.getMap().getDescription()); @@ -181,13 +164,13 @@ public abstract class TerminologyRenderer extends ResourceRenderer { } String spec = getSpecialReference(inc.getSystem()); if (spec != null) { - XhtmlNode a = li.ah(spec); + XhtmlNode a = li.ah(context.prefixLocalHref(spec)); a.code(inc.getSystem()); } else if (cs != null && ref != null) { if (addHtml && !ref.contains(".html")) ref = ref + ".html"; ref = context.fixReference(ref); - XhtmlNode a = li.ah(ref.replace("\\", "/")); + XhtmlNode a = li.ah(context.prefixLocalHref(ref.replace("\\", "/"))); a.code(inc.getSystem()); } else { li.code(inc.getSystem()); @@ -281,12 +264,6 @@ public abstract class TerminologyRenderer extends ResourceRenderer { protected void AddVsRef(String value, XhtmlNode li, Resource source) { Resource res = null; - if (rcontext != null) { - BundleEntryComponent be = rcontext.resolve(value); - if (be != null) { - res = be.getResource(); - } - } if (res != null && !(res instanceof CanonicalResource)) { li.addText(value); return; @@ -302,17 +279,17 @@ public abstract class TerminologyRenderer extends ResourceRenderer { String ref = (String) vs.getWebPath(); ref = context.fixReference(ref); - XhtmlNode a = li.ah(ref == null ? "?ngen-11?" : ref.replace("\\", "/")); + XhtmlNode a = li.ah(context.prefixLocalHref(ref == null ? "?ngen-11?" : ref.replace("\\", "/"))); a.addText(vs.present()); } else { CodeSystem cs = getContext().getWorker().fetchCodeSystem(value); if (cs != null) { String ref = (String) cs.getWebPath(); ref = context.fixReference(ref); - XhtmlNode a = li.ah(ref == null ? "?ngen-12?" : ref.replace("\\", "/")); + XhtmlNode a = li.ah(context.prefixLocalHref(ref == null ? "?ngen-12?" : ref.replace("\\", "/"))); a.addText(value); } else if (value.equals("http://snomed.info/sct") || value.equals("http://snomed.info/id")) { - XhtmlNode a = li.ah(value); + XhtmlNode a = li.ah(context.prefixLocalHref(value)); a.tx(context.formatPhrase(RenderingContext.STRUC_DEF_SNOMED)); } else { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TestPlanRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TestPlanRenderer.java index e4b27a4cd..4a348a798 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TestPlanRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/TestPlanRenderer.java @@ -2,324 +2,310 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.List; import org.hl7.fhir.exceptions.DefinitionException; import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.CodeableConcept; -import org.hl7.fhir.r5.model.CodeableReference; -import org.hl7.fhir.r5.model.ContactDetail; -import org.hl7.fhir.r5.model.ContactPoint; -import org.hl7.fhir.r5.model.Reference; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.TestPlan; -import org.hl7.fhir.r5.model.TestPlan.TestCaseDependencyComponent; -import org.hl7.fhir.r5.model.TestPlan.TestPlanDependencyComponent; -import org.hl7.fhir.r5.model.TestPlan.TestPlanTestCaseAssertionComponent; -import org.hl7.fhir.r5.model.TestPlan.TestPlanTestCaseComponent; -import org.hl7.fhir.r5.model.TestPlan.TestPlanTestCaseTestDataComponent; -import org.hl7.fhir.r5.model.TestPlan.TestPlanTestCaseTestRunComponent; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; +import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.renderers.utils.RenderingContext; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class TestPlanRenderer extends ResourceRenderer { - public TestPlanRenderer(RenderingContext context) { - super(context); - } - public TestPlanRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); - } + public TestPlanRenderer(RenderingContext context) { + super(context); + } - @Override - public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - return render(x, (TestPlan) r); - } + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); + } - public boolean render(XhtmlNode x, TestPlan tp) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { - XhtmlNode p = null; - if (!tp.getContact().isEmpty()) { - p = x.para(); + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper tp) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + renderResourceTechDetails(tp, x); + genSummaryTable(status, x, (CanonicalResource) tp.getResourceNative()); + XhtmlNode p = null; + if (tp.has("contact")) { + p = x.para(); p.b().tx(context.formatPhrase(RenderingContext.GENERAL_CONTACT)); - p.tx(" ("); - boolean firsti = true; - for (ContactDetail ci : tp.getContact()) { - if (firsti) - firsti = false; - else - p.tx(", "); - if (ci.hasName()) - p.addText(ci.getName() + ": "); - boolean first = true; - for (ContactPoint c : ci.getTelecom()) { - if (first) - first = false; - else - p.tx(", "); - addTelecom(p, c); - } - } - p.tx(")"); - } + p.tx(" ("); + boolean firsti = true; + for (ResourceWrapper ci : tp.children("contact")) { + if (firsti) + firsti = false; + else + p.tx(", "); + if (ci.has("name")) + p.addText(ci.primitiveValue("name") + ": "); + boolean first = true; + for (ResourceWrapper c : ci.children("telecom")) { + if (first) + first = false; + else + p.tx(", "); + addTelecom(p, c); + } + } + p.tx(")"); + } - if (tp.hasCategory()) { - p = x.para(); - p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_CATEGORY)+" "); + if (tp.has("category")) { + p = x.para(); + p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_CATEGORY)+" "); boolean first = true; - for (CodeableConcept cc : tp.getCategory()) { + for (ResourceWrapper cc : tp.children("category")) { if (first) first = false; else p.tx(", "); - renderCodeableConcept(p, cc, false); - } - } + renderCodeableConcept(status, p, cc); + } + } - if (tp.hasScope()) { - if (tp.getScope().size() == 1) { - p = x.para(); - p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPE)+" "); - renderReference(tp, p, tp.getScopeFirstRep()); - } else { - x.para().b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPES)); - XhtmlNode ul = x.ul(); - for (Reference ref : tp.getScope()) { - renderReference(tp, ul.li(), ref); - } - } - } + if (tp.has("scope")) { + List scopes = tp.children("scope"); + if (scopes.size() == 1) { + p = x.para(); + p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPE)+" "); + renderReference(status, p, scopes.get(0)); + } else { + x.para().b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPES)); + XhtmlNode ul = x.ul(); + for (ResourceWrapper ref : scopes) { + renderReference(status, ul.li(), ref); + } + } + } - if (tp.hasDependency()) { - if (tp.getDependency().size() == 1) { - p = x.para(); - p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_DEP)+" "); - XhtmlNode t = x.table("grid"); - XhtmlNode tr = t.tr(); - if (!Utilities.noString(tp.getDependencyFirstRep().getDescription())) { - addMarkdown(tr.td(), tp.getDependencyFirstRep().getDescription()); - } - tr = t.tr(); - renderReference(tp, tr.td(), tp.getDependencyFirstRep().getPredecessor()); - } else { - x.para().b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_DEPEN)); - XhtmlNode ul = x.ul(); - XhtmlNode li = null; - for (TestPlanDependencyComponent d : tp.getDependency()) { - li = ul.li(); - if (!Utilities.noString(d.getDescription())) { - addMarkdown(li, d.getDescription()); - } - else { - li.addText(context.formatPhrase(RenderingContext.TEST_PLAN_DESC)); - } - if (d.hasPredecessor()) { - XhtmlNode liul = li.ul(); - XhtmlNode liulli = liul.li(); - renderReference(tp, liulli, d.getPredecessor()); - } - } - } - } - - if (tp.hasExitCriteria()) { - addMarkdown(x, tp.getExitCriteria()); - } - - if (tp.hasTestCase()) { - for (TestPlanTestCaseComponent tc : tp.getTestCase()) { - x.h2().addText(tc.hasSequence() ? formatPhrase(RenderingContext.TEST_PLAN_CASE) : formatPhrase(RenderingContext.TEST_PLAN_CASE_SEQ, tc.getSequence())); - - if (tc.hasScope()) { - if (tc.getScope().size() == 1) { - p = x.para(); - p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPE)+" "); - renderReference(tp, p, tc.getScopeFirstRep()); - } else { - x.para().b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPES)); - XhtmlNode ul = x.ul(); - for (Reference ref : tc.getScope()) { - renderReference(tp, ul.li(), ref); - } - } - } - - if (tc.hasDependency()) { - if (tc.getDependency().size() == 1) { - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_DEP)); - XhtmlNode t = x.table("grid"); - XhtmlNode tr = t.tr(); - if (!Utilities.noString(tc.getDependencyFirstRep().getDescription())) { - addMarkdown(tr.td(), tc.getDependencyFirstRep().getDescription()); - } - tr = t.tr(); - renderReference(tp, tr.td(), tc.getDependencyFirstRep().getPredecessor()); - } else { - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_DEPEN)); - XhtmlNode ul = x.ul(); - XhtmlNode li = null; - for (TestCaseDependencyComponent d : tc.getDependency()) { - li = ul.li(); - if (!Utilities.noString(d.getDescription())) { - addMarkdown(li, d.getDescription()); - } - else { - li.addText(context.formatPhrase(RenderingContext.TEST_PLAN_DESC)); - } - if (d.hasPredecessor()) { - XhtmlNode liul = li.ul(); - XhtmlNode liulli = liul.li(); - renderReference(tp, liulli, d.getPredecessor()); - } - } - } - } - - if (tc.hasTestRun()) { - if (tc.getTestRun().size() == 1) { - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_RUN)); - renderTestRun(x, tp, tc.getTestRunFirstRep()); - } - else { - int count = 0; - for (TestPlanTestCaseTestRunComponent trun : tc.getTestRun()) { - count++; - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_TEST_RUN, count)+" "); - renderTestRun(x, tp, trun); - } - } - } - - if (tc.hasTestData()) { - if (tc.getTestData().size() == 1) { - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_DATA)); - renderTestData(x, tp, tc.getTestDataFirstRep()); + if (tp.has("dependency")) { + List deps = tp.children("dependency"); + if (deps.size() == 1) { + ResourceWrapper dep = deps.get(0); + p = x.para(); + p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_DEP)+" "); + XhtmlNode t = x.table("grid"); + XhtmlNode tr = t.tr(); + if (!Utilities.noString(dep.primitiveValue("description"))) { + addMarkdown(tr.td(), dep.primitiveValue("description")); + } + tr = t.tr(); + renderReference(status, tr.td(), dep.child("predecessor")); + } else { + x.para().b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_DEPEN)); + XhtmlNode ul = x.ul(); + XhtmlNode li = null; + for (ResourceWrapper d : deps) { + li = ul.li(); + if (!Utilities.noString(d.primitiveValue("description"))) { + addMarkdown(li, d.primitiveValue("description")); } else { - int count = 0; - for (TestPlanTestCaseTestDataComponent tdata : tc.getTestData()) { - count++; - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_TEST_DATA, count)+" "); - renderTestData(x, tp, tdata); + li.addText(context.formatPhrase(RenderingContext.TEST_PLAN_DESC)); + } + if (d.has("predecessor")) { + XhtmlNode liul = li.ul(); + XhtmlNode liulli = liul.li(); + renderReference(status, liulli, d.child("predecessor")); + } + } + } + } + + if (tp.has("exitCriteria")) { + addMarkdown(x, tp.primitiveValue("exitCriteria")); + } + + for (ResourceWrapper tc : tp.children("testCase")) { + x.h2().addText(tc.has("sequence") ? formatPhrase(RenderingContext.TEST_PLAN_CASE) : formatPhrase(RenderingContext.TEST_PLAN_CASE_SEQ, tc.primitiveValue("sequence"))); + + if (tc.has("scope")) { + List scopes = tc.children("scope"); + if (scopes.size() == 1) { + p = x.para(); + p.b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPE)+" "); + renderReference(status, p, scopes.get(0)); + } else { + x.para().b().tx(context.formatPhrase(RenderingContext.TEST_PLAN_SCOPES)); + XhtmlNode ul = x.ul(); + for (ResourceWrapper ref : scopes) { + renderReference(status, ul.li(), ref); + } + } + } + + if (tc.has("dependency")) { + List deps = tc.children("dependency"); + if (deps.size() == 1) { + ResourceWrapper dep = deps.get(0); + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_DEP)); + XhtmlNode t = x.table("grid"); + XhtmlNode tr = t.tr(); + if (!Utilities.noString(dep.primitiveValue("description"))) { + addMarkdown(tr.td(), dep.primitiveValue("description")); + } + tr = t.tr(); + renderReference(status, tr.td(), dep.child("predecessor")); + + } else { + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_DEPEN)); + XhtmlNode ul = x.ul(); + XhtmlNode li = null; + for (ResourceWrapper d : deps) { + li = ul.li(); + if (!Utilities.noString(d.primitiveValue("description"))) { + addMarkdown(li, d.primitiveValue("description")); + } + else { + li.addText(context.formatPhrase(RenderingContext.TEST_PLAN_DESC)); + } + if (d.has("predecessor")) { + XhtmlNode liul = li.ul(); + XhtmlNode liulli = liul.li(); + renderReference(status, liulli, d.child("predecessor")); } } } + } - if (tc.hasAssertion()) { - if (tc.getAssertion().size() == 1) { - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_ASS)); - renderAssertion(x, tp, tc.getAssertionFirstRep()); - } - else { - int count = 0; - for (TestPlanTestCaseAssertionComponent as : tc.getAssertion()) { - count++; - x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_ASSERTION, count)+" "); - renderAssertion(x, tp, as); - } - } - } - } + if (tc.has("testRun")) { + List runs = tc.children("testRun"); + if (runs.size() == 1) { + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_RUN)); + renderTestRun(status, x, tp, runs.get(0)); + } + else { + int count = 0; + for (ResourceWrapper trun : runs) { + count++; + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_TEST_RUN, count)+" "); + renderTestRun(status, x, tp, trun); + } + } + } + + if (tc.has("testData")) { + List dl = tc.children("testData"); + if (dl.size() == 1) { + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_DATA)); + renderTestData(status, x, tp, dl.get(0)); + } + else { + int count = 0; + for (ResourceWrapper tdata : dl) { + count++; + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_TEST_DATA, count)+" "); + renderTestData(status, x, tp, tdata); + } + } + } + + if (tc.has("assertion")) { + List al = tc.children("assertion"); + if (al.size() == 1) { + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_ASS)); + renderAssertion(status, x, tp, al.get(0)); + } + else { + int count = 0; + for (ResourceWrapper as : al) { + count++; + x.h3().addText(context.formatPhrase(RenderingContext.TEST_PLAN_ASSERTION, count)+" "); + renderAssertion(status, x, tp, as); + } + } + } } + } - return false; - } - - private void renderTestRun(XhtmlNode x, TestPlan tp, TestPlanTestCaseTestRunComponent trun) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + private void renderTestRun(RenderingStatus status, XhtmlNode x, ResourceWrapper tp, ResourceWrapper trun) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { if (trun.hasNarrative()) { - addMarkdown(x, trun.getNarrative()); + addMarkdown(x, trun.primitiveValue("narrative")); } - if (trun.hasScript()) { + if (trun.has("script")) { + ResourceWrapper script = trun.child("script"); XhtmlNode t = x.table("grid"); XhtmlNode tr = t.tr(); tr.td().b().addText(context.formatPhrase(RenderingContext.TEST_PLAN_LANG)); tr.td().b().addText(context.formatPhrase(RenderingContext.TEST_PLAN_SOURCE)); tr = t.tr(); - if (trun.getScript().hasLanguage()) { - renderCodeableConcept(tr.td(), trun.getScript().getLanguage(), false); - } - else { + if (script.has("language")) { + renderCodeableConcept(status, tr.td(), script.child("language")); + } else { tr.td().addText("??"); } - if (trun.getScript().hasSourceReference()) { - renderReference(tp, tr.td(), trun.getScript().getSourceReference()); - } - else if(trun.getScript().hasSourceStringType()) { - tr.td().addText(trun.getScript().getSourceStringType().asStringValue()); - } - else { + if (script.has("source")) { + renderDataType(status, tr.td(), script.child("script")); + } else { tr.td().addText("??"); } } - } + } - private void renderTestData(XhtmlNode x, TestPlan tp, TestPlanTestCaseTestDataComponent tdata) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + private void renderTestData(RenderingStatus status, XhtmlNode x, ResourceWrapper tp, ResourceWrapper tdata) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { XhtmlNode t = x.table("grid"); XhtmlNode tr = t.tr(); tr.td().b().addText(context.formatPhrase(RenderingContext.GENERAL_TYPE)); tr.td().b().addText(context.formatPhrase(RenderingContext.GENERAL_CONTENT)); tr.td().b().addText(context.formatPhrase(RenderingContext.TEST_PLAN_SOURCE)); tr = t.tr(); - if (tdata.hasType()) { - renderCoding(tr.td(), tdata.getType()); + if (tdata.has("type")) { + renderCoding(status, tr.td(), tdata.child("type")); } else { tr.td().addText("??"); } - if (tdata.hasContent()) { - renderReference(tp, tr.td(), tdata.getContent()); + if (tdata.has("content")) { + renderReference(status, tr.td(), tdata.child("content")); } else { tr.td().addText("??"); } - if (tdata.hasSourceReference()) { - renderReference(tp, tr.td(), tdata.getSourceReference()); - } - else if(tdata.hasSourceStringType()) { - tr.td().addText(tdata.getSourceStringType().asStringValue()); - } - else { + if (tdata.has("source")) { + renderDataType(status, tr.td(), tdata.child("source")); + } else { tr.td().addText("??"); } } - private void renderAssertion(XhtmlNode x, TestPlan tp, TestPlanTestCaseAssertionComponent as) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + private void renderAssertion(RenderingStatus status, XhtmlNode x, ResourceWrapper tp, ResourceWrapper as) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { XhtmlNode t = x.table("grid"); XhtmlNode tr = t.tr(); tr.td().b().addText(context.formatPhrase(RenderingContext.GENERAL_TYPE)); tr.td().b().addText(context.formatPhrase(RenderingContext.GENERAL_CONTENT)); tr.td().b().addText(context.formatPhrase(RenderingContext.TEST_PLAN_RESULT)); tr = t.tr(); - if (as.hasType()) { + if (as.has("type")) { XhtmlNode td = tr.td(); XhtmlNode ul = td.ul(); - for (CodeableConcept cc : as.getType()) { - renderCodeableConcept(ul.li(), cc, false); + for (ResourceWrapper cc : as.children("type")) { + renderCodeableConcept(status, ul.li(), cc); } } else { tr.td().addText("??"); } - if (as.hasObject()) { + if (as.has("object")) { XhtmlNode td = tr.td(); XhtmlNode ul = td.ul(); - for (CodeableReference cr : as.getObject()) { - renderCodeableReference(ul.li(), cr, false); + for (ResourceWrapper cr : as.children("object")) { + renderCodeableReference(status, ul.li(), cr); } } else { tr.td().addText("??"); } - if (as.hasResult()) { + if (as.has("result")) { XhtmlNode td = tr.td(); XhtmlNode ul = td.ul(); - for (CodeableReference cr : as.getResult()) { - renderCodeableReference(ul.li(), cr, false); + for (ResourceWrapper cr : as.children("result")) { + renderCodeableReference(status, ul.li(), cr); } } else { @@ -327,17 +313,4 @@ public class TestPlanRenderer extends ResourceRenderer { } } - @Override - public String display(Resource r) throws UnsupportedEncodingException, IOException { - return null; - } - - @Override - public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { - if (r.has("title")) { - return r.children("title").get(0).getBase().primitiveValue(); - } - return "??"; - } - } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java index 8d795a457..2655d077d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ValueSetRenderer.java @@ -1,6 +1,7 @@ package org.hl7.fhir.r5.renderers; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -18,7 +19,6 @@ import org.hl7.fhir.exceptions.FHIRFormatError; import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.r5.comparison.VersionComparisonAnnotation; import org.hl7.fhir.r5.model.Base; -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.CodeSystem.ConceptDefinitionComponent; @@ -29,7 +29,6 @@ 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.ExtensionHelper; -import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StringType; @@ -47,20 +46,16 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent; import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.ValueSetUtilities; import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; import org.hl7.fhir.r5.terminologies.utilities.CodingValidationRequest; -import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache; -import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass; import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; -import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.CacheToken; +import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.utilities.LoincLinker; import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.i18n.I18nConstants; -import org.hl7.fhir.utilities.i18n.RenderingI18nContext; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; @@ -71,12 +66,32 @@ import com.google.common.collect.Multimap; public class ValueSetRenderer extends TerminologyRenderer { - public ValueSetRenderer(RenderingContext context) { - super(context); + public ValueSetRenderer(RenderingContext context) { + super(context); } - - public ValueSetRenderer(RenderingContext context, ResourceContext rcontext) { - super(context, rcontext); + + @Override + public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { + if (!r.isDirect()) { + throw new Error("ValueSetRenderer only renders native resources directly"); + } + renderResourceTechDetails(r, x); + ValueSet vs = (ValueSet) r.getBase(); + genSummaryTable(status, x, vs); + List maps = findReleventMaps(vs); + + if (vs.hasExpansion()) { + // for now, we just accept an expansion if there is one + generateExpansion(status, r, x, vs, false, maps); + } else { + generateComposition(status, r, x, vs, false, maps); + } + } + + + @Override + public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { + return canonicalTitle(r); } private static final int MAX_DESIGNATIONS_IN_LINE = 5; @@ -84,23 +99,10 @@ public class ValueSetRenderer extends TerminologyRenderer { private static final int MAX_BATCH_VALIDATION_SIZE = 1000; private List renderingMaps = new ArrayList(); - - public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException { - return render(x, (ValueSet) dr, false); - } - public boolean render(XhtmlNode x, ValueSet vs, boolean header) throws FHIRFormatError, DefinitionException, IOException { - List maps = findReleventMaps(vs); + public void render(RenderingStatus status, XhtmlNode x, ValueSet vs, boolean header) throws FHIRFormatError, DefinitionException, IOException { - boolean hasExtensions; - if (vs.hasExpansion()) { - // for now, we just accept an expansion if there is one - hasExtensions = generateExpansion(x, vs, header, maps); - } else { - hasExtensions = generateComposition(x, vs, header, maps); - } - return hasExtensions; } public void describe(XhtmlNode x, ValueSet vs) { @@ -176,8 +178,7 @@ public class ValueSetRenderer extends TerminologyRenderer { return vs.hasUrl() && source != null && vs.getUrl().equals(source.primitiveValue()); } - private boolean generateExpansion(XhtmlNode x, ValueSet vs, boolean header, List maps) throws FHIRFormatError, DefinitionException, IOException { - boolean hasExtensions = false; + private void generateExpansion(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ValueSet vs, boolean header, List maps) throws FHIRFormatError, DefinitionException, IOException { List langs = new ArrayList(); Map designations = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list Map properties = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list @@ -188,7 +189,7 @@ public class ValueSetRenderer extends TerminologyRenderer { if (IsNotFixedExpansion(vs)) addMarkdown(x, vs.getDescription()); if (vs.hasCopyright()) - generateCopyright(x, vs); + generateCopyright(x, res); } boolean hasFragment = generateContentModeNotices(x, vs.getExpansion(), vs); generateVersionNotice(x, vs.getExpansion(), vs); @@ -261,11 +262,11 @@ public class ValueSetRenderer extends TerminologyRenderer { tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_DEFINITION)); doDesignations = false; for (String n : Utilities.sorted(properties.keySet())) { - tr.td().b().ah(properties.get(n)).addText(n); + tr.td().b().ah(context.prefixLocalHref(properties.get(n))).addText(n); } } else { for (String n : Utilities.sorted(properties.keySet())) { - tr.td().b().ah(properties.get(n)).addText(n); + tr.td().b().ah(context.prefixLocalHref(properties.get(n))).addText(n); } // if we're not doing definitions and we don't have too many languages, we'll do them in line doDesignations = langs.size() + properties.size() + designations.size() < MAX_DESIGNATIONS_IN_LINE; @@ -286,7 +287,7 @@ public class ValueSetRenderer extends TerminologyRenderer { addMapHeaders(tr, maps); for (ValueSetExpansionContainsComponent c : vs.getExpansion().getContains()) { - addExpansionRowToTable(t, vs, c, 1, doLevel, doDefinition, doInactive, maps, langs, designations, doDesignations, properties); + addExpansionRowToTable(t, vs, c, 1, doLevel, doDefinition, doInactive, maps, langs, designations, doDesignations, properties, res); } // now, build observed languages @@ -314,7 +315,6 @@ public class ValueSetRenderer extends TerminologyRenderer { } } - return hasExtensions; } @@ -458,7 +458,7 @@ public class ValueSetRenderer extends TerminologyRenderer { if (cs == null) { x.code(url); } else if (cs.hasWebPath()) { - x.ah(cs.getWebPath()).tx(cs.present()); + x.ah(context.prefixLocalHref(cs.getWebPath())).tx(cs.present()); } else { x.code(url); x.tx(" ("+cs.present()+")"); @@ -531,7 +531,7 @@ public class ValueSetRenderer extends TerminologyRenderer { CanonicalResource cr = (CanonicalResource) getContext().getWorker().fetchResource(Resource.class, u, source); if (cr != null) { if (cr.hasWebPath()) { - x.ah(cr.getWebPath()).tx(t+" "+cr.present()+" "+ context.formatPhrase(RenderingContext.VALUE_SET_NO_VERSION)+cr.fhirType()+")"); + x.ah(context.prefixLocalHref(cr.getWebPath())).tx(t+" "+cr.present()+" "+ context.formatPhrase(RenderingContext.VALUE_SET_NO_VERSION)+cr.fhirType()+")"); } else { x.tx(t+" "+displaySystem(u)+" "+context.formatPhrase(RenderingContext.VALUE_SET_NO_VERSION)+cr.fhirType()+")"); } @@ -542,7 +542,7 @@ public class ValueSetRenderer extends TerminologyRenderer { CanonicalResource cr = (CanonicalResource) getContext().getWorker().fetchResource(Resource.class, u+"|"+v, source); if (cr != null) { if (cr.hasWebPath()) { - x.ah(cr.getWebPath()).tx(t+" "+cr.present()+" v"+v+" ("+cr.fhirType()+")"); + x.ah(context.prefixLocalHref(cr.getWebPath())).tx(t+" "+cr.present()+" v"+v+" ("+cr.fhirType()+")"); } else { x.tx(t+" "+displaySystem(u)+" v"+v+" ("+cr.fhirType()+")"); } @@ -800,7 +800,7 @@ public class ValueSetRenderer extends TerminologyRenderer { } } - private void addExpansionRowToTable(XhtmlNode t, ValueSet vs, ValueSetExpansionContainsComponent c, int i, boolean doLevel, boolean doDefinition, boolean doInactive, List maps, List langs, Map designations, boolean doDesignations, Map properties) throws FHIRFormatError, DefinitionException, IOException { + private void addExpansionRowToTable(XhtmlNode t, ValueSet vs, ValueSetExpansionContainsComponent c, int i, boolean doLevel, boolean doDefinition, boolean doInactive, List maps, List langs, Map designations, boolean doDesignations, Map properties, ResourceWrapper res) throws FHIRFormatError, DefinitionException, IOException { XhtmlNode tr = t.tr(); if (ValueSetUtilities.isDeprecated(vs, c)) { tr.setAttribute("style", "background-color: #ffeeee"); @@ -809,7 +809,7 @@ public class ValueSetRenderer extends TerminologyRenderer { XhtmlNode td = tr.td(); String tgt = makeAnchor(c.getSystem(), c.getCode()); - td.an(tgt); + td.an(res.getScopedId()+"-"+context.prefixAnchor(tgt)); if (doLevel) { td.addText(Integer.toString(i)); @@ -865,7 +865,7 @@ public class ValueSetRenderer extends TerminologyRenderer { addLangaugesToRow(c, langs, tr); } for (ValueSetExpansionContainsComponent cc : c.getContains()) { - addExpansionRowToTable(t, vs, cc, i+1, doLevel, doDefinition, doInactive, maps, langs, designations, doDesignations, properties); + addExpansionRowToTable(t, vs, cc, i+1, doLevel, doDefinition, doInactive, maps, langs, designations, doDesignations, properties, res); } } @@ -898,9 +898,9 @@ public class ValueSetRenderer extends TerminologyRenderer { if (isAbstract) td.i().setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).addText(code); else if ("http://snomed.info/sct".equals(system)) { - td.ah(sctLink(code)).addText(code); + td.ah(context.prefixLocalHref(sctLink(code))).addText(code); } else if ("http://loinc.org".equals(system)) { - td.ah(LoincLinker.getLinkForCode(code)).addText(code); + td.ah(context.prefixLocalHref(LoincLinker.getLinkForCode(code))).addText(code); } else td.addText(code); } else { @@ -910,9 +910,9 @@ public class ValueSetRenderer extends TerminologyRenderer { else href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(code); if (isAbstract) - td.ah(href).setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).i().addText(code); + td.ah(context.prefixLocalHref(href)).setAttribute("title", context.formatPhrase(RenderingContext.VS_ABSTRACT_CODE_HINT)).i().addText(code); else - td.ah(href).addText(code); + td.ah(context.prefixLocalHref(href)).addText(code); } } @@ -931,12 +931,11 @@ public class ValueSetRenderer extends TerminologyRenderer { // if (!Utilities.isAbsoluteUrl(link)) { // link = getContext().getSpecificationLink()+link; // } -// XhtmlNode a = td.ah(link); +// XhtmlNode a = td.ah(context.prefixLocalHref(link)); // a.addText(code); } - private boolean generateComposition(XhtmlNode x, ValueSet vs, boolean header, List maps) throws FHIRException, IOException { - boolean hasExtensions = false; + private void generateComposition(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ValueSet vs, boolean header, List maps) throws FHIRException, IOException { List langs = new ArrayList(); Map designations = new HashMap<>(); // map of url = description, where url is the designation code. Designations that are for languages won't make it into this list for (ConceptSetComponent inc : vs.getCompose().getInclude()) { @@ -952,21 +951,21 @@ public class ValueSetRenderer extends TerminologyRenderer { h.addText(vs.present()); addMarkdown(x, vs.getDescription()); if (vs.hasCopyrightElement()) - generateCopyright(x, vs); + generateCopyright(x, res); } int index = 0; if (vs.getCompose().getInclude().size() == 1 && vs.getCompose().getExclude().size() == 0 && !VersionComparisonAnnotation.hasDeleted(vs.getCompose(), "include", "exclude")) { - hasExtensions = genInclude(x.ul(), vs.getCompose().getInclude().get(0), "Include", langs, doDesignations, maps, designations, index, vs) || hasExtensions; + genInclude(status, x.ul(), vs.getCompose().getInclude().get(0), "Include", langs, doDesignations, maps, designations, index, vs); } else { XhtmlNode p = x.para(); p.tx(context.formatPhrase(RenderingContext.VALUE_SET_RULES_INC)); XhtmlNode ul = x.ul(); for (ConceptSetComponent inc : vs.getCompose().getInclude()) { - hasExtensions = genInclude(ul, inc, context.formatPhrase(RenderingContext.VALUE_SET_INC), langs, doDesignations, maps, designations, index, vs) || hasExtensions; + genInclude(status, ul, inc, context.formatPhrase(RenderingContext.VALUE_SET_INC), langs, doDesignations, maps, designations, index, vs); index++; } for (Base inc : VersionComparisonAnnotation.getDeleted(vs.getCompose(), "include")) { - genInclude(ul, (ConceptSetComponent) inc, context.formatPhrase(RenderingContext.VALUE_SET_INC), langs, doDesignations, maps, designations, index, vs); + genInclude(status, ul, (ConceptSetComponent) inc, context.formatPhrase(RenderingContext.VALUE_SET_INC), langs, doDesignations, maps, designations, index, vs); index++; } if (vs.getCompose().hasExclude() || VersionComparisonAnnotation.hasDeleted(vs.getCompose(), "exclude")) { @@ -974,11 +973,11 @@ public class ValueSetRenderer extends TerminologyRenderer { p.tx(context.formatPhrase(RenderingContext.VALUE_SET_RULES_EXC)); ul = x.ul(); for (ConceptSetComponent exc : vs.getCompose().getExclude()) { - hasExtensions = genInclude(ul, exc, context.formatPhrase(RenderingContext.VALUE_SET_EXCL), langs, doDesignations, maps, designations, index, vs) || hasExtensions; + genInclude(status, ul, exc, context.formatPhrase(RenderingContext.VALUE_SET_EXCL), langs, doDesignations, maps, designations, index, vs); index++; } for (Base inc : VersionComparisonAnnotation.getDeleted(vs.getCompose(), "exclude")) { - genInclude(ul, (ConceptSetComponent) inc, context.formatPhrase(RenderingContext.VALUE_SET_EXCL), langs, doDesignations, maps, designations, index, vs); + genInclude(status, ul, (ConceptSetComponent) inc, context.formatPhrase(RenderingContext.VALUE_SET_EXCL), langs, doDesignations, maps, designations, index, vs); index++; } } @@ -1010,9 +1009,6 @@ public class ValueSetRenderer extends TerminologyRenderer { } } } - - - return hasExtensions; } private void renderExpansionRules(XhtmlNode x, ConceptSetComponent inc, int index, Map definitions) throws FHIRException, IOException { @@ -1166,8 +1162,7 @@ public class ValueSetRenderer extends TerminologyRenderer { } } - private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List langs, boolean doDesignations, List maps, Map designations, int index, ValueSet vsRes) throws FHIRException, IOException { - boolean hasExtensions = false; + private void genInclude(RenderingStatus status, XhtmlNode ul, ConceptSetComponent inc, String type, List langs, boolean doDesignations, List maps, Map designations, int index, ValueSet vsRes) throws FHIRException, IOException { XhtmlNode li; li = ul.li(); li = renderStatus(inc, li); @@ -1200,8 +1195,9 @@ public class ValueSetRenderer extends TerminologyRenderer { ConceptDefinitionComponent cc = definitions == null ? null : definitions.get(c.getCode()); hasDefinition = hasDefinition || ((cc != null && cc.hasDefinition()) || ExtensionHelper.hasExtension(c, ToolingExtensions.EXT_DEFINITION)); } - if (hasComments || hasDefinition) - hasExtensions = true; + if (hasComments || hasDefinition) { + status.setExtensions(true); + } addMapHeaders(addTableHeaderRowStandard(t, false, true, hasDefinition, hasComments, false, false, null, langs, designations, doDesignations), maps); for (ConceptReferenceComponent c : inc.getConcept()) { renderConcept(inc, langs, doDesignations, maps, designations, definitions, t, hasComments, hasDefinition, c); @@ -1238,7 +1234,7 @@ public class ValueSetRenderer extends TerminologyRenderer { href = href + "-"+Utilities.nmtokenize(f.getValue()); else href = href + "#"+e.getId()+"-"+Utilities.nmtokenize(f.getValue()); - wli.ah(href).addText(f.getValue()); + wli.ah(context.prefixLocalHref(href)).addText(f.getValue()); } else if ("concept".equals(f.getProperty()) && inc.hasSystem()) { wli.addText(f.getValue()); ValidationResult vr = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions(), inc.getSystem(), inc.getVersion(), f.getValue(), null); @@ -1268,7 +1264,7 @@ public class ValueSetRenderer extends TerminologyRenderer { } } if (inc.hasExtension(ToolingExtensions.EXT_EXPAND_RULES) || inc.hasExtension(ToolingExtensions.EXT_EXPAND_GROUP)) { - hasExtensions = true; + status.setExtensions(true); renderExpansionRules(li, inc, index, definitions); } } else { @@ -1296,7 +1292,6 @@ public class ValueSetRenderer extends TerminologyRenderer { } } - return hasExtensions; } private void renderConcept(ConceptSetComponent inc, List langs, boolean doDesignations, @@ -1521,10 +1516,6 @@ public class ValueSetRenderer extends TerminologyRenderer { return null; } - - - - private boolean inConcept(String code, ConceptDefinitionComponent c) { if (c.hasCodeElement() && c.getCode().equals(code)) return true; @@ -1536,4 +1527,18 @@ public class ValueSetRenderer extends TerminologyRenderer { } + @Override + protected void genSummaryTableContent(RenderingStatus status, XhtmlNode tbl, CanonicalResource cr) throws IOException { + super.genSummaryTableContent(status, tbl, cr); + + ValueSet vs = (ValueSet) cr; + XhtmlNode tr; + + if (CodeSystemUtilities.hasOID(vs)) { + tr = tbl.tr(); + tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_OID)+":"); + tr.td().tx(context.formatPhrase(RenderingContext.CODE_SYS_FOR_OID, CodeSystemUtilities.getOID(vs))); + } + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CanonicalSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CanonicalSpreadsheetGenerator.java index 4993e2f5f..3db7a19da 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CanonicalSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CanonicalSpreadsheetGenerator.java @@ -32,7 +32,7 @@ public class CanonicalSpreadsheetGenerator extends SpreadsheetGenerator { } addMetadataRow(sheet, "URL", cr.getUrl()); for (Identifier id : cr.getIdentifier()) { - addMetadataRow(sheet, "Identifier", dr.display(id)); + addMetadataRow(sheet, "Identifier", dr.displayDataType(id)); } addMetadataRow(sheet, "Version", cr.getVersion()); addMetadataRow(sheet, "Name", cr.getName()); @@ -42,10 +42,10 @@ public class CanonicalSpreadsheetGenerator extends SpreadsheetGenerator { addMetadataRow(sheet, "Date", cr.getDateElement().asStringValue()); addMetadataRow(sheet, "Publisher", cr.getPublisher()); for (ContactDetail c : cr.getContact()) { - addMetadataRow(sheet, "Contact", dr.display(c)); + addMetadataRow(sheet, "Contact", dr.displayDataType(c)); } for (CodeableConcept j : cr.getJurisdiction()) { - addMetadataRow(sheet, "Jurisdiction", dr.display(j)); + addMetadataRow(sheet, "Jurisdiction", dr.displayDataType(j)); } addMetadataRow(sheet, "Description", cr.getDescription()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CodeSystemSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CodeSystemSpreadsheetGenerator.java index 235193e99..0f26d721b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CodeSystemSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/CodeSystemSpreadsheetGenerator.java @@ -106,7 +106,7 @@ public class CodeSystemSpreadsheetGenerator extends CanonicalSpreadsheetGenerato Sheet sheet = makeSheet("Expansion Parameters"); addHeaders(sheet, "Parameter", "Value"); for (ValueSetExpansionParameterComponent p : params) { - addRow(sheet, p.getName(), dr.display(p.getValue())); + addRow(sheet, p.getName(), dr.displayDataType(p.getValue())); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java index dfc40017e..b9fcda38f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/StructureDefinitionSpreadsheetGenerator.java @@ -135,7 +135,7 @@ public class StructureDefinitionSpreadsheetGenerator extends CanonicalSpreadshee private void addStructureDefinitionMetadata(Sheet sheet, StructureDefinition sd) { for (Coding k : sd.getKeyword()) { - addMetadataRow(sheet, "Keyword", dr.display(k)); + addMetadataRow(sheet, "Keyword", dr.displayDataType(k)); } addMetadataRow(sheet, "FHIR Version", sd.getFhirVersionElement().asStringValue()); addMetadataRow(sheet, "Kind", sd.getKindElement().asStringValue()); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java index d7227204e..106a581e2 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/spreadsheets/ValueSetSpreadsheetGenerator.java @@ -59,7 +59,7 @@ public class ValueSetSpreadsheetGenerator extends CanonicalSpreadsheetGenerator Sheet sheet = makeSheet("Expansion Parameters"); addHeaders(sheet, "Parameter", "Value"); for (ValueSetExpansionParameterComponent p : params) { - addRow(sheet, p.getName(), dr.display(p.getValue())); + addRow(sheet, p.getName(), dr.displayDataType(p.getValue())); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/BaseWrappers.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/BaseWrappers.java deleted file mode 100644 index 89a58fc8f..000000000 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/BaseWrappers.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.hl7.fhir.r5.renderers.utils; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.ResourceRenderer; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; - -public class BaseWrappers { - - public interface RendererWrapper { - public RenderingContext getContext(); - } - - public interface PropertyWrapper extends RendererWrapper { - public String getName(); - public boolean hasValues(); - public List getValues(); - public String getTypeCode(); - public String getDefinition(); - public int getMinCardinality(); - public int getMaxCardinality(); - public StructureDefinition getStructure(); - public ElementDefinition getElementDefinition(); - public BaseWrapper value(); - public ResourceWrapper getAsResource(); - public String fhirType(); - } - - public interface WrapperBase extends RendererWrapper { - public boolean has(String name); - public Base get(String name) throws UnsupportedEncodingException, FHIRException, IOException; - public List children(String name) throws UnsupportedEncodingException, FHIRException, IOException; - public List children(); - public String fhirType(); - } - - public interface ResourceWrapper extends WrapperBase { - public List getContained(); - public String getId(); - public XhtmlNode getNarrative() throws FHIRFormatError, IOException, FHIRException; - public Base getBase(); - public String getName(); - public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException; - public void injectNarrative(ResourceRenderer renderer, XhtmlNode x, NarrativeStatus status) throws IOException; - public BaseWrapper root(); - public PropertyWrapper getChildByName(String tail); - public StructureDefinition getDefinition(); - public boolean hasNarrative(); - public String getNameFromResource(); - public Resource getResource(); // if there is one - } - - public interface BaseWrapper extends WrapperBase { - public Base getBase() throws UnsupportedEncodingException, IOException, FHIRException; - public ResourceWrapper getResource() throws UnsupportedEncodingException, IOException, FHIRException; // for contained, etc - public PropertyWrapper getChildByName(String tail); - public String fhirType(); - } - - public static abstract class RendererWrapperImpl implements RendererWrapper { - protected RenderingContext context; - - public RendererWrapperImpl(RenderingContext context) { - super(); - this.context = context; - } - - public RenderingContext getContext() { - return context; - } - - protected String tail(String path) { - return path.substring(path.lastIndexOf(".")+1); - } - - } - - public static abstract class WrapperBaseImpl extends RendererWrapperImpl implements WrapperBase { - - public WrapperBaseImpl(RenderingContext context) { - super(context); - } - - @Override - public boolean has(String name) { - for (PropertyWrapper p : children()) { - if (p.getName().equals(name) || p.getName().equals(name+"[x]") ) { - return p.hasValues(); - } - } - return false; - } - - @Override - public Base get(String name) throws UnsupportedEncodingException, FHIRException, IOException { - for (PropertyWrapper p : children()) { - if (p.getName().equals(name) || p.getName().equals(name+"[x]")) { - if (p.hasValues()) { - return p.getValues().get(0).getBase(); - } else { - return null; - } - } - } - return null; - } - - @Override - public List children(String name) throws UnsupportedEncodingException, FHIRException, IOException { - for (PropertyWrapper p : children()) { - if (p.getName().equals(name) || p.getName().equals(name+"[x]")) { - List res = new ArrayList<>(); - for (BaseWrapper b : p.getValues()) { - res.add(b); - } - return res; - } - } - return null; - } - } -} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/DOMWrappers.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/DOMWrappers.java deleted file mode 100644 index 3b38ce6cb..000000000 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/DOMWrappers.java +++ /dev/null @@ -1,447 +0,0 @@ -package org.hl7.fhir.r5.renderers.utils; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.formats.FormatUtilities; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.Property; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; -import org.hl7.fhir.r5.renderers.ResourceRenderer; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.xhtml.XhtmlComposer; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; -import org.hl7.fhir.utilities.xhtml.XhtmlParser; -import org.hl7.fhir.utilities.xml.XMLUtil; -import org.hl7.fhir.utilities.xml.XmlGenerator; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -/** - * This class is only used in kindling, and it's going to be phased out and replaced by - * ElementWrappers. Don't use in any other context - */ -@Deprecated -public class DOMWrappers { - - -/** - * This class is only used in kindling, and it's going to be phased out and replaced by - * ElementWrappers. Don't use in any other context - */ -@Deprecated - public static class BaseWrapperElement extends WrapperBaseImpl implements BaseWrapper { - private Element element; - private String type; - private StructureDefinition structure; - private ElementDefinition definition; - private List children; - private List list; - - public BaseWrapperElement(RenderingContext context, Element element, String type, StructureDefinition structure, ElementDefinition definition) { - super(context); - this.element = element; - this.type = type; - this.structure = structure; - this.definition = definition; - } - - @Override - public Base getBase() throws UnsupportedEncodingException, IOException, FHIRException { - if (Utilities.noString(type) || type.equals("Resource") || type.equals("BackboneElement") || type.equals("Element")) - return null; - - String xml; - try { - xml = new XmlGenerator().generate(element); - } catch (org.hl7.fhir.exceptions.FHIRException e) { - throw new FHIRException(e.getMessage(), e); - } - Node n = element.getPreviousSibling(); - Base ret = context.getParser().parseType(xml, type); - while (n != null && (n.getNodeType() == Node.COMMENT_NODE || n.getNodeType() == Node.TEXT_NODE)) { - if (n.getNodeType() == Node.COMMENT_NODE) { - ret.getFormatCommentsPre().add(0, n.getTextContent()); - } - n = n.getPreviousSibling(); - } - return ret; - } - - @Override - public List children() { - if (list == null) { - children = context.getProfileUtilities().getChildList(structure, definition); - if (children.isEmpty() && type != null) { - StructureDefinition sdt = context.getWorker().fetchTypeDefinition(type); - children = context.getProfileUtilities().getChildList(sdt, sdt.getSnapshot().getElementFirstRep()); - } - list = new ArrayList(); - for (ElementDefinition child : children) { - List elements = new ArrayList(); - XMLUtil.getNamedChildrenWithWildcard(element, tail(child.getPath()), elements); - list.add(new PropertyWrapperElement(context, structure, child, elements)); - } - } - return list; - } - - @Override - public PropertyWrapper getChildByName(String name) { - for (PropertyWrapper p : children()) - if (p.getName().equals(name)) - return p; - return null; - } - - @Override - public String fhirType() { - return type; - } - - @Override - public ResourceWrapper getResource() throws UnsupportedEncodingException, IOException, FHIRException { - Element r = XMLUtil.getFirstChild(element); - StructureDefinition sd = getContext().getContext().fetchTypeDefinition(r.getLocalName()); - if (sd == null) { - throw new FHIRException("Unable to find definition for type "+type+" @ "+definition.getPath()); - } - if (sd.getKind() != StructureDefinitionKind.RESOURCE) { - throw new FHIRException("Definition for type "+type+" is not for a resource @ "+definition.getPath()); - } - return new ResourceWrapperElement(context, r, sd); - } - - } - -/** - * This class is only used in kindling, and it's going to be phased out and replaced by - * ElementWrappers. Don't use in any other context - */ -@Deprecated - public static class PropertyWrapperElement extends RendererWrapperImpl implements PropertyWrapper { - - private StructureDefinition structure; - private ElementDefinition definition; - private List values; - private List list; - - public PropertyWrapperElement(RenderingContext context, StructureDefinition structure, ElementDefinition definition, List values) { - super(context); - this.structure = structure; - this.definition = definition; - this.values = values; - } - - @Override - public String getName() { - return tail(definition.getPath()); - } - - @Override - public boolean hasValues() { - return values.size() > 0; - } - - @Override - public List getValues() { - if (list == null) { - list = new ArrayList(); - for (Element e : values) - list.add(new BaseWrapperElement(context, e, determineType(e), structure, definition)); - } - return list; - } - private String determineType(Element e) { - if (definition.getType().isEmpty()) - return null; - if (definition.getType().size() == 1) { - if (definition.getType().get(0).getWorkingCode().equals("Element") || definition.getType().get(0).getWorkingCode().equals("BackboneElement")) - return null; - return definition.getType().get(0).getWorkingCode(); - } - String t = e.getNodeName().substring(tail(definition.getPath()).length()-3); - - if (isPrimitive(Utilities.uncapitalize(t))) - return Utilities.uncapitalize(t); - else - return t; - } - - private boolean isPrimitive(String code) { - StructureDefinition sd = context.getWorker().fetchTypeDefinition(code); - return sd != null && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE; - } - - @Override - public String getTypeCode() { - if (definition == null || definition.getType().size() != 1) { - if (values.size() != 1) { - throw new Error("not handled"); - } - String tn = values.get(0).getLocalName().substring(tail(definition.getPath()).replace("[x]", "").length()); - if (isPrimitive(Utilities.uncapitalize(tn))) { - return Utilities.uncapitalize(tn); - } else { - return tn; - } - } - return definition.getType().get(0).getWorkingCode(); - } - - @Override - public String getDefinition() { - if (definition == null) - throw new Error("not handled"); - return definition.getDefinition(); - } - - @Override - public int getMinCardinality() { - if (definition == null) - throw new Error("not handled"); - return definition.getMin(); - } - - @Override - public int getMaxCardinality() { - if (definition == null) - throw new Error("not handled"); - return definition.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(definition.getMax()); - } - - @Override - public StructureDefinition getStructure() { - return structure; - } - - @Override - public BaseWrapper value() { - if (getValues().size() != 1) - throw new Error("Access single value, but value count is "+getValues().size()); - return getValues().get(0); - } - - @Override - public ResourceWrapper getAsResource() { - throw new Error("Not implemented yet"); - } - - @Override - public String fhirType() { - return getTypeCode(); - } - - @Override - public ElementDefinition getElementDefinition() { - return definition; - } - - } - -/** - * This class is only used in kindling, and it's going to be phased out and replaced by - * ElementWrappers. Don't use in any other context - */ -@Deprecated - public static class ResourceWrapperElement extends WrapperBaseImpl implements ResourceWrapper { - - private Element wrapped; - private StructureDefinition definition; - private List list; - private List list2; - - public ResourceWrapperElement(RenderingContext context, Element wrapped, StructureDefinition definition) { - super(context); - this.wrapped = wrapped; - this.definition = definition; - } - - @Override - public List getContained() { - if (list == null) { - List children = new ArrayList(); - XMLUtil.getNamedChildren(wrapped, "contained", children); - list = new ArrayList(); - for (Element e : children) { - Element c = XMLUtil.getFirstChild(e); - list.add(new ResourceWrapperElement(context, c, context.getWorker().fetchTypeDefinition(c.getNodeName()))); - } - } - return list; - } - - @Override - public String getId() { - return XMLUtil.getNamedChildValue(wrapped, "id"); - } - - @Override - public XhtmlNode getNarrative() throws FHIRFormatError, IOException, FHIRException { - Element txt = XMLUtil.getNamedChild(wrapped, "text"); - if (txt == null) - return null; - Element div = XMLUtil.getNamedChild(txt, "div"); - if (div == null) - return null; - try { - return new XhtmlParser().parse(new XmlGenerator().generate(div), "div"); - } catch (org.hl7.fhir.exceptions.FHIRFormatError e) { - throw new FHIRFormatError(e.getMessage(), e); - } catch (org.hl7.fhir.exceptions.FHIRException e) { - throw new FHIRException(e.getMessage(), e); - } - } - - @Override - public String getName() { - return wrapped.getNodeName(); - } - - @Override - public String getNameFromResource() { - Element e = XMLUtil.getNamedChild(wrapped, "name"); - if (e != null) { - if (e.hasAttribute("value")) { - return e.getAttribute("value"); - } - if (XMLUtil.hasNamedChild(e, "text")) { - return XMLUtil.getNamedChildValue(e, "text"); - } - if (XMLUtil.hasNamedChild(e, "family") || XMLUtil.hasNamedChild(e, "given")) { - Element family = XMLUtil.getNamedChild(e, "family"); - Element given = XMLUtil.getNamedChild(e, "given"); - String s = given != null && given.hasAttribute("value") ? given.getAttribute("value") : ""; - if (family != null && family.hasAttribute("value")) - s = s + " " + family.getAttribute("value").toUpperCase(); - return s; - } - return null; - } - return null; - } - - @Override - public List children() { - if (list2 == null) { - List children = context.getProfileUtilities().getChildList(definition, definition.getSnapshot().getElement().get(0)); - list2 = new ArrayList(); - for (ElementDefinition child : children) { - List elements = new ArrayList(); - XMLUtil.getNamedChildrenWithWildcard(wrapped, tail(child.getPath()), elements); - list2.add(new PropertyWrapperElement(context, definition, child, elements)); - } - } - return list2; - } - - - - @Override - public void describe(XhtmlNode x) { - throw new Error("Not done yet"); - } - - @Override - public void injectNarrative(ResourceRenderer renderer, XhtmlNode x, NarrativeStatus status) { - if (!x.hasAttribute("xmlns")) - x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); - Element le = XMLUtil.getNamedChild(wrapped, "language"); - String l = le == null ? null : le.getAttribute("value"); - if (!Utilities.noString(l)) { - // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues - x.setAttribute("lang", l); - x.setAttribute("xml:lang", l); - } - Element txt = XMLUtil.getNamedChild(wrapped, "text"); - if (txt == null) { - txt = wrapped.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "text"); - Element n = XMLUtil.getFirstChild(wrapped); - while (n != null && (n.getNodeName().equals("id") || n.getNodeName().equals("meta") || n.getNodeName().equals("implicitRules") || n.getNodeName().equals("language"))) - n = XMLUtil.getNextSibling(n); - if (n == null) - wrapped.appendChild(txt); - else - wrapped.insertBefore(txt, n); - } - Element st = XMLUtil.getNamedChild(txt, "status"); - if (st == null) { - st = wrapped.getOwnerDocument().createElementNS(FormatUtilities.FHIR_NS, "status"); - Element n = XMLUtil.getFirstChild(txt); - if (n == null) - txt.appendChild(st); - else - txt.insertBefore(st, n); - } - st.setAttribute("value", status.toCode()); - Element div = XMLUtil.getNamedChild(txt, "div"); - if (div == null) { - div = wrapped.getOwnerDocument().createElementNS(FormatUtilities.XHTML_NS, "div"); - div.setAttribute("xmlns", FormatUtilities.XHTML_NS); - txt.appendChild(div); - } - if (div.hasChildNodes()) - div.appendChild(wrapped.getOwnerDocument().createElementNS(FormatUtilities.XHTML_NS, "hr")); - new XhtmlComposer(XhtmlComposer.XML, context.isPretty()).compose(div, x); - } - - @Override - public BaseWrapper root() { - return new BaseWrapperElement(context, wrapped, getName(), definition, definition.getSnapshot().getElementFirstRep()); - } - - @Override - public StructureDefinition getDefinition() { - return definition; - } - - @Override - public Base getBase() { - throw new Error("Not Implemented yet"); - } - - @Override - public boolean hasNarrative() { - StructureDefinition sd = definition; - while (sd != null) { - if ("DomainResource".equals(sd.getType())) { - return true; - } - sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd); - } - return false; - } - - @Override - public String fhirType() { - return wrapped.getNodeName(); - } - - @Override - public PropertyWrapper getChildByName(String name) { - for (PropertyWrapper p : children()) - if (p.getName().equals(name)) - return p; - return null; - } - - @Override - public Resource getResource() { - return null; - } - } - -} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/DirectWrappers.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/DirectWrappers.java deleted file mode 100644 index d8ac976b5..000000000 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/DirectWrappers.java +++ /dev/null @@ -1,336 +0,0 @@ -package org.hl7.fhir.r5.renderers.utils; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.CanonicalResource; -import org.hl7.fhir.r5.model.DomainResource; -import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.Encounter; -import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; -import org.hl7.fhir.r5.model.Patient; -import org.hl7.fhir.r5.model.Property; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.renderers.EncounterRenderer; -import org.hl7.fhir.r5.renderers.PatientRenderer; -import org.hl7.fhir.r5.renderers.ResourceRenderer; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; - -public class DirectWrappers { - - public static class PropertyWrapperDirect extends RendererWrapperImpl implements PropertyWrapper { - private Property wrapped; - private List list; - private ElementDefinition ed; - - public PropertyWrapperDirect(RenderingContext context, Property wrapped) { - super(context); - if (wrapped == null) - throw new Error("wrapped == null"); - this.wrapped = wrapped; - } - - public PropertyWrapperDirect(RenderingContext context, Property wrapped, ElementDefinition ed) { - super(context); - if (wrapped == null) - throw new Error("wrapped == null"); - this.wrapped = wrapped; - this.ed = ed; - } - - @Override - public String getName() { - return wrapped.getName(); - } - - public Property getWrapped() { - return wrapped; - } - - @Override - public boolean hasValues() { - return wrapped.hasValues(); - } - - @Override - public List getValues() { - if (list == null) { - list = new ArrayList(); - for (Base b : wrapped.getValues()) - list.add(b == null ? null : new BaseWrapperDirect(context, b)); - } - return list; - } - - @Override - public String getTypeCode() { - return wrapped.getTypeCode(); - } - - @Override - public String getDefinition() { - return wrapped.getDefinition(); - } - - @Override - public int getMinCardinality() { - return wrapped.getMinCardinality(); - } - - @Override - public int getMaxCardinality() { - return wrapped.getMinCardinality(); - } - - @Override - public StructureDefinition getStructure() { - return wrapped.getStructure(); - } - - @Override - public BaseWrapper value() { - if (getValues().size() != 1) - throw new Error("Access single value, but value count is "+getValues().size()); - return getValues().get(0); - } - - public String toString() { - return "#."+wrapped.toString(); - } - - @Override - public ResourceWrapper getAsResource() { - return new ResourceWrapperDirect(context, (Resource) wrapped.getValues().get(0)); - } - - @Override - public String fhirType() { - return wrapped.getTypeCode(); - } - - @Override - public ElementDefinition getElementDefinition() { - return ed; - } - } - - public static class BaseWrapperDirect extends WrapperBaseImpl implements BaseWrapper { - private Base wrapped; - private List list; - - public BaseWrapperDirect(RenderingContext context, Base wrapped) { - super(context); - if (wrapped == null) - throw new Error("wrapped == null"); - this.wrapped = wrapped; - } - - @Override - public Base getBase() { - return wrapped; - } - - @Override - public List children() { - if (list == null) { - list = new ArrayList(); - for (Property p : wrapped.children()) - list.add(new PropertyWrapperDirect(context, p)); - } - return list; - - } - - @Override - public PropertyWrapper getChildByName(String name) { - Property p = wrapped.getChildByName(name); - if (p == null) - return null; - else - return new PropertyWrapperDirect(context, p); - } - - @Override - public String fhirType() { - return wrapped.fhirType(); - } - - @Override - public ResourceWrapper getResource() throws UnsupportedEncodingException, IOException, FHIRException { - return new DirectWrappers.ResourceWrapperDirect(getContext(), (Resource) wrapped); - } - - } - - public static class ResourceWrapperDirect extends WrapperBaseImpl implements ResourceWrapper { - private Resource wrapped; - - public ResourceWrapperDirect(RenderingContext context, Resource wrapped) { - super(context); - if (wrapped == null) - throw new Error("wrapped == null"); - this.wrapped = wrapped; - } - - @Override - public List getContained() { - List list = new ArrayList(); - if (wrapped instanceof DomainResource) { - DomainResource dr = (DomainResource) wrapped; - for (Resource c : dr.getContained()) { - list.add(new ResourceWrapperDirect(context, c)); - } - } - return list; - } - - @Override - public String getId() { - return wrapped.getId(); - } - - @Override - public XhtmlNode getNarrative() { - if (wrapped instanceof DomainResource) { - DomainResource dr = (DomainResource) wrapped; - if (dr.hasText() && dr.getText().hasDiv()) - return dr.getText().getDiv(); - } - return null; - } - - @Override - public String getName() { - return wrapped.getResourceType().toString(); - } - - @Override - public String getNameFromResource() { - Property name = wrapped.getChildByName("name"); - if (name != null && name.hasValues()) { - Base b = name.getValues().get(0); - if (b.isPrimitive()) { - return b.primitiveValue(); - } else if (b.fhirType().equals("HumanName")) { - Property family = b.getChildByName("family"); - Property given = wrapped.getChildByName("given"); - String s = given != null && given.hasValues() ? given.getValues().get(0).primitiveValue() : ""; - if (family != null && family.hasValues()) { - String v = family.getValues().get(0).primitiveValue(); - if (v == null) { - s = s + " " + "??"; - } else { - s = s + " " + v.toUpperCase(); - } - } - return s; - } else { - Property p = b.getChildByName("name"); - if (p == null || !p.hasValues()) { - p = b.getChildByName("name"); - } - if (p == null || !p.hasValues()) { - p = b.getChildByName("text"); - } - if (p == null || !p.hasValues()) { - p = b.getChildByName("value"); - } - if (p == null || !p.hasValues()) { - p = b.getChildByName("productName"); // MedicinalProductDefinition - } - if (p == null || !p.hasValues()) { - throw new Error("What to render for 'name'? Type is "+b.fhirType()); - } else { - return p.getValues().get(0).primitiveValue(); - } - } - } - return null; - } - - @Override - public List children() { - List list = new ArrayList(); - if (wrapped.children() != null) { - for (Property c : wrapped.children()) - list.add(new PropertyWrapperDirect(context, c)); - } - return list; - } - - @Override - public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException { - if (wrapped instanceof CanonicalResource) { - x.tx(((CanonicalResource) wrapped).present()); - } else if (wrapped instanceof Patient) { - new PatientRenderer(getContext()).describe(x, (Patient) wrapped); - } else if (wrapped instanceof Encounter) { - new EncounterRenderer(getContext()).describe(x, (Encounter) wrapped); - } - } - - @Override - public void injectNarrative(ResourceRenderer renderer, XhtmlNode x, NarrativeStatus status) { - renderer.inject((DomainResource) wrapped, x, status); - - } - - @Override - public BaseWrapper root() { - return new BaseWrapperDirect(context, wrapped); - } - - @Override - public StructureDefinition getDefinition() { - return context.getWorker().fetchTypeDefinition(wrapped.fhirType()); - } - - @Override - public Base getBase() { - return wrapped; - } - - @Override - public boolean hasNarrative() { - StructureDefinition sd = context.getWorker().fetchTypeDefinition(wrapped.fhirType()); - while (sd != null) { - if ("DomainResource".equals(sd.getType())) { - return true; - } - sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd); - } - return false; - - } - - @Override - public String fhirType() { - return wrapped.fhirType(); - } - - @Override - public PropertyWrapper getChildByName(String name) { - Property p = wrapped.getChildByName(name); - if (p == null) - return null; - else - return new PropertyWrapperDirect(context, p); - } - - public Resource getResource() { - return wrapped; - } - - } - -} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ElementWrappers.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ElementWrappers.java deleted file mode 100644 index b6a16c992..000000000 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ElementWrappers.java +++ /dev/null @@ -1,403 +0,0 @@ -package org.hl7.fhir.r5.renderers.utils; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.io.output.ByteArrayOutputStream; -import org.hl7.fhir.exceptions.FHIRException; -import org.hl7.fhir.exceptions.FHIRFormatError; -import org.hl7.fhir.r5.elementmodel.Element; -import org.hl7.fhir.r5.elementmodel.XmlParser; -import org.hl7.fhir.r5.formats.IParser.OutputStyle; -import org.hl7.fhir.r5.model.Base; -import org.hl7.fhir.r5.model.ElementDefinition; -import org.hl7.fhir.r5.model.Property; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; -import org.hl7.fhir.r5.model.StringType; -import org.hl7.fhir.r5.model.StructureDefinition; -import org.hl7.fhir.r5.renderers.ResourceRenderer; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl; -import org.hl7.fhir.utilities.Utilities; -import org.hl7.fhir.utilities.xhtml.NodeType; -import org.hl7.fhir.utilities.xhtml.XhtmlComposer; -import org.hl7.fhir.utilities.xhtml.XhtmlNode; - -public class ElementWrappers { - - public static class BaseWrapperMetaElement extends WrapperBaseImpl implements BaseWrapper { - private Element element; - private String type; - private StructureDefinition structure; - private ElementDefinition definition; - private List children; - private List list; - - public BaseWrapperMetaElement(RenderingContext context, Element element, String type, StructureDefinition structure, ElementDefinition definition) { - super(context); - this.element = element; - this.type = type; - this.structure = structure; - this.definition = definition; - } - - @Override - public Base getBase() throws UnsupportedEncodingException, IOException, FHIRException { - if (type == null || type.equals("Resource") || type.equals("BackboneElement") || type.equals("Element")) - return null; - - if (element.hasElementProperty()) { - return element; - } - ByteArrayOutputStream xml = new ByteArrayOutputStream(); - try { - new XmlParser(context.getWorker()).compose(element, xml, OutputStyle.PRETTY, null); - } catch (Exception e) { - throw new FHIRException(e.getMessage(), e); - } - if (context.getParser() == null) { - System.out.println("No version specific parser provided"); - } - if (context.getParser() == null) { - throw new Error("No type parser provided to renderer context"); - } else { - try { - return context.getParser().parseType(xml.toString(StandardCharsets.UTF_8), type); - } catch (Exception e) { - throw new FHIRException(e.getMessage(), e); - } - } - } - - @Override - public List children() { - if (list == null) { - children = context.getProfileUtilities().getChildList(structure, definition, false, true); - if (children.isEmpty() && !Utilities.noString(type)) { - StructureDefinition sd = context.getWorker().fetchTypeDefinition(type); - children = context.getProfileUtilities().getChildList(sd, sd.getSnapshot().getElementFirstRep()); - } - list = new ArrayList(); - for (ElementDefinition child : children) { - List elements = new ArrayList(); - String name = tail(child.getPath()); - if (name.endsWith("[x]")) - element.getNamedChildrenWithWildcard(name, elements); - else - element.getNamedChildren(name, elements); - list.add(new PropertyWrapperMetaElement(context, structure, child, elements)); - } - } - return list; - } - - @Override - public PropertyWrapper getChildByName(String name) { - for (PropertyWrapper p : children()) - if (p.getName().equals(name)) - return p; - return null; - } - - @Override - public String fhirType() { - return element.fhirType(); - } - - @Override - public ResourceWrapper getResource() throws UnsupportedEncodingException, IOException, FHIRException { - return new ElementWrappers.ResourceWrapperMetaElement(getContext(), element); - } - - } - - public static class ResourceWrapperMetaElement extends WrapperBaseImpl implements ResourceWrapper { - private Element wrapped; - private List list; - private List list2; - private StructureDefinition definition; - public ResourceWrapperMetaElement(RenderingContext context, Element wrapped) { - super(context); - this.wrapped = wrapped; - this.definition = wrapped.getProperty().getStructure(); - } - - @Override - public List getContained() { - if (list == null) { - List children = wrapped.getChildrenByName("contained"); - list = new ArrayList(); - for (Element e : children) { - list.add(new ResourceWrapperMetaElement(context, e)); - } - } - return list; - } - - @Override - public String getId() { - return wrapped.getNamedChildValue("id"); - } - - @Override - public XhtmlNode getNarrative() throws FHIRFormatError, IOException, FHIRException { - Element txt = wrapped.getNamedChild("text"); - if (txt == null) - return null; - Element div = txt.getNamedChild("div"); - if (div == null) - return null; - else - return div.getXhtml(); - } - - @Override - public String getName() { - return wrapped.getName(); - } - - @Override - public String getNameFromResource() { - Property name = wrapped.getChildByName("name"); - if (name != null && name.hasValues()) { - Base b = name.getValues().get(0); - if (b.isPrimitive()) { - return b.primitiveValue(); - } else if (b.fhirType().equals("HumanName")) { - Property family = b.getChildByName("family"); - Property given = wrapped.getChildByName("given"); - String s = given != null && given.hasValues() ? given.getValues().get(0).primitiveValue() : ""; - if (family != null && family.hasValues() && family.getValues().get(0).primitiveValue() != null) - s = s + " " + family.getValues().get(0).primitiveValue().toUpperCase(); - return s; - } else { - // well, we couldn't get a name from that - return null; - } - } - return null; - } - - @Override - public List children() { - if (list2 == null) { - List children = context.getProfileUtilities().getChildList(definition, definition.getSnapshot().getElement().get(0)); - list2 = new ArrayList(); - for (ElementDefinition child : children) { - List elements = new ArrayList(); - if (child.getPath().endsWith("[x]")) - wrapped.getNamedChildrenWithWildcard(tail(child.getPath()), elements); - else - wrapped.getNamedChildren(tail(child.getPath()), elements); - list2.add(new PropertyWrapperMetaElement(context, definition, child, elements)); - } - } - return list2; - } - - @Override - public void describe(XhtmlNode x) { - if (wrapped.hasChild("title") && wrapped.getChildValue("title") != null) { - x.tx(wrapped.getChildValue("title")); - } else if (wrapped.hasChild("name") && wrapped.getChildValue("name") != null) { - x.tx(wrapped.getChildValue("name")); - } else { - x.tx("?ngen-1?"); - } - } - - @Override - public void injectNarrative(ResourceRenderer renderer, XhtmlNode x, NarrativeStatus status) throws IOException { - org.hl7.fhir.r5.elementmodel.Element txt = wrapped.getNamedChild("text"); - if (txt == null) { - txt = new org.hl7.fhir.r5.elementmodel.Element("text", wrapped.getProperty().getChild(null, "text")); - int i = 0; - while (i < wrapped.getChildren().size() && (wrapped.getChildren().get(i).getName().equals("id") || wrapped.getChildren().get(i).getName().equals("meta") || wrapped.getChildren().get(i).getName().equals("implicitRules") || wrapped.getChildren().get(i).getName().equals("language"))) { - i++; - } - if (i >= wrapped.getChildren().size()) - wrapped.getChildren().add(txt); - else - wrapped.getChildren().add(i, txt); - } - org.hl7.fhir.r5.elementmodel.Element st = txt.getNamedChild("status"); - if (st == null) { - st = new org.hl7.fhir.r5.elementmodel.Element("status", txt.getProperty().getChild(null, "status")); - txt.getChildren().add(0, st); - } - st.setValue(status.toCode()); - org.hl7.fhir.r5.elementmodel.Element div = txt.getNamedChild("div"); - if (div == null) { - div = new org.hl7.fhir.r5.elementmodel.Element("div", txt.getProperty().getChild(null, "div")); - txt.getChildren().add(div); - } - // now process the xhtml - if (renderer.isMultiLangMode()) { - XhtmlNode xd = div.getXhtml(); - if (xd == null) { - xd = new XhtmlNode(NodeType.Element, "div"); - xd.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); - div.setXhtml(xd); - } else { - xd.getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang")); - } - renderer.markLanguage(x); - xd.getChildNodes().add(x); - } else { - if (!x.hasAttribute("xmlns")) { - x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); - } - String l = wrapped.getChildValue("language"); - if (!Utilities.noString(l)) { - // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues - x.setAttribute("lang", l); - x.setAttribute("xml:lang", l); - } - div.setXhtml(x); - } - div.setValue(new XhtmlComposer(XhtmlComposer.XML, context.isPretty()).compose(div.getXhtml())); - } - - @Override - public BaseWrapper root() { - return new BaseWrapperMetaElement(context, wrapped, getName(), definition, definition.getSnapshot().getElementFirstRep()); - } - - @Override - public StructureDefinition getDefinition() { - return definition; - } - - @Override - public Base getBase() { - return wrapped; - } - - @Override - public boolean hasNarrative() { - StructureDefinition sd = definition; - while (sd != null) { - if ("DomainResource".equals(sd.getType())) { - return true; - } - sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd); - } - return false; - } - - @Override - public String fhirType() { - return wrapped.fhirType(); - } - - @Override - public PropertyWrapper getChildByName(String name) { - for (PropertyWrapper p : children()) - if (p.getName().equals(name)) - return p; - return null; - } - - public Element getElement() { - return wrapped; - } - - @Override - public Resource getResource() { - return null; - } - -} - - public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper { - - private StructureDefinition structure; - private ElementDefinition definition; - private List values; - private List list; - - public PropertyWrapperMetaElement(RenderingContext context, StructureDefinition structure, ElementDefinition definition, List values) { - super(context); - this.structure = structure; - this.definition = definition; - this.values = values; - } - - @Override - public String getName() { - return tail(definition.getPath()); - } - - @Override - public boolean hasValues() { - return values.size() > 0; - } - - @Override - public List getValues() { - if (list == null) { - list = new ArrayList(); - for (Element e : values) { - list.add(new BaseWrapperMetaElement(context, e, e.fhirType(), structure, definition)); - } - } - return list; - } - - @Override - public String getTypeCode() { - return definition.typeSummary(); - } - - @Override - public String getDefinition() { - return definition.getDefinition(); - } - - @Override - public int getMinCardinality() { - return definition.getMin(); - } - - @Override - public int getMaxCardinality() { - return "*".equals(definition.getMax()) ? Integer.MAX_VALUE : Integer.valueOf(definition.getMax()); - } - - @Override - public StructureDefinition getStructure() { - return structure; - } - - @Override - public BaseWrapper value() { - if (getValues().size() != 1) - throw new Error("Access single value, but value count is "+getValues().size()); - return getValues().get(0); - } - - @Override - public ResourceWrapper getAsResource() { - return new ElementWrappers.ResourceWrapperMetaElement(context, values.get(0)); - } - - @Override - public String fhirType() { - return getTypeCode(); - } - - @Override - public ElementDefinition getElementDefinition() { - return definition; - } - - } - -} \ 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 0e936cff0..1b9dc364d 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 @@ -100,7 +100,7 @@ public class RenderingContext extends RenderingI18nContext { END_USER, /** - * The user wants to see the resource, but a technical view so they can see what's going on with the content + * The user wants to see the resource, but a technical view so they can see what's going on with the content - this includes content like the meta header */ TECHNICAL } @@ -226,6 +226,7 @@ public class RenderingContext extends RenderingI18nContext { private ITypeParser parser; // i18n related fields + private boolean secondaryLang; // true if this is not the primary language for the resource private MultiLanguagePolicy multiLanguagePolicy = MultiLanguagePolicy.NONE; private Set allowedLanguages = new HashSet<>(); private ZoneId timeZoneId; @@ -238,7 +239,7 @@ public class RenderingContext extends RenderingI18nContext { private int headerLevelContext; private boolean canonicalUrlsAsLinks; private boolean pretty; - private boolean header; + private boolean showSummaryTable; // for canonical resources private boolean contained; private ValidationOptions terminologyServiceOptions = new ValidationOptions(FhirPublication.R5); @@ -257,7 +258,6 @@ public class RenderingContext extends RenderingI18nContext { private StructureDefinitionRendererMode structureMode = StructureDefinitionRendererMode.SUMMARY; private FixedValueFormat fixedFormat = FixedValueFormat.JSON; - private boolean addGeneratedNarrativeHeader = true; private boolean showComments = false; private FhirPublication targetVersion; @@ -270,6 +270,9 @@ public class RenderingContext extends RenderingI18nContext { private Map namedLinks = new HashMap<>(); private boolean addName = false; private Map typeMap = new HashMap<>(); // type aliases that can be resolved in Markdown type links (mainly for cross-version usage) + private int base64Limit = 1024; + private boolean shortPatientForm; + private String uniqueLocalPrefix; /** * @@ -313,11 +316,10 @@ public class RenderingContext extends RenderingI18nContext { res.contextUtilities = contextUtilities; res.definitionsTarget = definitionsTarget; res.destDir = destDir; - res.addGeneratedNarrativeHeader = addGeneratedNarrativeHeader; res.scenarioMode = scenarioMode; res.questionnaireMode = questionnaireMode; res.structureMode = structureMode; - res.header = header; + res.showSummaryTable = showSummaryTable; res.links.putAll(links); res.inlineGraphics = inlineGraphics; res.timeZoneId = timeZoneId; @@ -509,12 +511,12 @@ public class RenderingContext extends RenderingI18nContext { return this; } - public boolean isHeader() { - return header; + public boolean isShowSummaryTable() { + return showSummaryTable; } - public RenderingContext setHeader(boolean header) { - this.header = header; + public RenderingContext setShowSummaryTable(boolean header) { + this.showSummaryTable = header; return this; } @@ -560,15 +562,6 @@ public class RenderingContext extends RenderingI18nContext { return this; } - public boolean isAddGeneratedNarrativeHeader() { - return addGeneratedNarrativeHeader; - } - - public RenderingContext setAddGeneratedNarrativeHeader(boolean addGeneratedNarrativeHeader) { - this.addGeneratedNarrativeHeader = addGeneratedNarrativeHeader; - return this; - } - public FhirPublication getTargetVersion() { return targetVersion; } @@ -800,6 +793,24 @@ public class RenderingContext extends RenderingI18nContext { return t.asStringValue(); } + public String getTranslated(ResourceWrapper t) { + if (t == null) { + return null; + } + if (locale != null) { + for (ResourceWrapper e : t.extensions(ToolingExtensions.EXT_TRANSLATION)) { + String l = e.extensionString("lang"); + if (l != null && l.equals(locale.toString())) { + String v = e.extensionString("content"); + if (v != null) { + return v; + } + } + } + } + return t.primitiveValue(); + } + public StringType getTranslatedElement(PrimitiveType t) { if (locale != null) { StringType v = ToolingExtensions.getLanguageTranslationElement(t, locale.toString()); @@ -937,5 +948,60 @@ public class RenderingContext extends RenderingI18nContext { } return contextUtilities; } + + public int getBase64Limit() { + return base64Limit; + } + + public void setBase64Limit(int base64Limit) { + this.base64Limit = base64Limit; + } + + public boolean isShortPatientForm() { + return shortPatientForm; + } + + public void setShortPatientForm(boolean shortPatientForm) { + this.shortPatientForm = shortPatientForm; + } + + public boolean isSecondaryLang() { + return secondaryLang; + } + + public void setSecondaryLang(boolean secondaryLang) { + this.secondaryLang = secondaryLang; + } + + public String prefixAnchor(String anchor) { + return uniqueLocalPrefix == null ? anchor : uniqueLocalPrefix+"-" + anchor; + } + + public String prefixLocalHref(String url) { + if (url == null || uniqueLocalPrefix == null || !url.startsWith("#")) { + return url; + } + return "#"+uniqueLocalPrefix+"-"+url.substring(1); + } + + public String getUniqueLocalPrefix() { + return uniqueLocalPrefix; + } + + public void setUniqueLocalPrefix(String uniqueLocalPrefix) { + this.uniqueLocalPrefix = uniqueLocalPrefix; + } + + public RenderingContext withUniqueLocalPrefix(String uniqueLocalPrefix) { + RenderingContext self = this.copy(); + self.uniqueLocalPrefix = uniqueLocalPrefix; + return self; + } + + public RenderingContext forContained() { + RenderingContext self = this.copy(); + self.contained = true; + return self; + } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java index a7cb6b4f9..6d3386231 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/Resolver.java @@ -1,24 +1,11 @@ package org.hl7.fhir.r5.renderers.utils; -import org.hl7.fhir.r5.model.Bundle; -import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; -import org.hl7.fhir.r5.model.DomainResource; -import org.hl7.fhir.r5.model.Parameters; -import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; -import org.hl7.fhir.r5.model.Resource; -import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; -import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceReferenceKind; -import org.w3c.dom.Element; - public class Resolver { public interface IReferenceResolver { - ResourceWithReference resolve(RenderingContext context, String url); + ResourceWithReference resolve(RenderingContext context, String url, String version); - // returns null if contained resource is inlined - String urlForContained(RenderingContext context, String containingType, String containingId, String containedType, String containedId); - /** * returns the correct literal URL for the specified logical uri * @param context @@ -28,6 +15,7 @@ public class Resolver { String resolveUri(RenderingContext context, String uri); } + /* public static class ResourceContext { private ResourceContext container; @@ -183,23 +171,25 @@ public class Resolver { } } } - +*/ public enum ResourceReferenceKind { - CONTAINED, BUNDLE, EXTERNAL, UNKNOWN + CONTAINED, BUNDLE, EXTERNAL, UNKNOWN, CONTAINER } public static class ResourceWithReference { private ResourceReferenceKind kind; - private String reference; + private String urlReference; + private String webPath; private ResourceWrapper resource; - public ResourceWithReference(ResourceReferenceKind kind, String reference, ResourceWrapper resource) { + public ResourceWithReference(ResourceReferenceKind kind, String urlReference, String webPath, ResourceWrapper resource) { super(); this.kind = kind; - this.reference = reference; + this.urlReference = urlReference; + this.webPath = webPath; this.resource = resource; } @@ -207,8 +197,12 @@ public class Resolver { return kind; } - public String getReference() { - return reference; + public String getUrlReference() { + return urlReference; + } + + public String getWebPath() { + return webPath == null ? urlReference : webPath; } public ResourceWrapper getResource() { diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapper.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapper.java new file mode 100644 index 000000000..4ca925231 --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapper.java @@ -0,0 +1,515 @@ +package org.hl7.fhir.r5.renderers.utils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; + +import org.hl7.fhir.r5.context.ContextUtilities; +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.Resource; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; + +/** + * This class is used to walk through the resources when rendering, whether + * the resource is a native resource or loaded by the element model + */ +public abstract class ResourceWrapper { + + public enum ElementKind { + PrimitiveType, + DataType, + BackboneElement, + ContainedResource, + InlineResource, + BundleEntry, + IndependentResource + } + + public static class NamedResourceWrapperList { + private String name; + private List values = new ArrayList(); + + public NamedResourceWrapperList(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + public List getValues() { + return values; + } +// public ElementDefinition getPropertyDefinition() { +// return values.isEmpty() ? null : values.get(0).getPropertyDefinition(); +// } +// public StructureDefinition getClassDefinition() { +// return values.isEmpty() ? null : values.get(0).getClassDefinition(); +// } + } + + protected ContextUtilities contextUtils; + protected ResourceWrapper parent; + protected String name; // null at root + protected int index; // -1 if not repeating + protected ElementKind kind; + + protected List children; + + // -- Constructors ------------------------------------------------------------------ + + protected ResourceWrapper() { + // TODO Auto-generated constructor stub + } + + public static ResourceWrapper forResource(ContextUtilities contextUtils, Resource resource) { + ResourceWrapperNative self = new ResourceWrapperNative(); + self.contextUtils = contextUtils; + self.parent = null; + self.name = null; + self.index = -1; + self.kind = ElementKind.IndependentResource; + self.element = resource; + return self; + } + + public static ResourceWrapper forResource(ContextUtilities contextUtils, Element resource) { + ResourceWrapperModel self = new ResourceWrapperModel(); + self.contextUtils = contextUtils; + self.parent = null; + self.name = null; + self.index = -1; + self.kind = ElementKind.IndependentResource; + self.model = resource; + return self; + } + + public static ResourceWrapper forResource(RenderingContext context, Resource resource) { + return forResource(context.getContextUtilities(), resource); + } + + public static ResourceWrapper forResource(RenderingContext context, Element resource) { + return forResource(context.getContextUtilities(), resource); + } + + public static ResourceWrapper forType(ContextUtilities contextUtils, Element resource) { + ResourceWrapperModel self = new ResourceWrapperModel(); + self.contextUtils = contextUtils; + self.parent = null; + self.name = null; + self.index = -1; + self.kind = ElementKind.DataType; + self.model = resource; + return self; + } + + public static ResourceWrapper forType(ContextUtilities contextUtils, DataType type) { + ResourceWrapperNative self = new ResourceWrapperNative(); + self.contextUtils = contextUtils; + self.parent = null; + self.name = null; + self.index = -1; + self.kind = null; + self.element = type; + return self; + } + + public static ResourceWrapper forType(ContextUtilities contextUtils, ResourceWrapper parent, DataType type) { + ResourceWrapperNative self = new ResourceWrapperNative(); + self.contextUtils = contextUtils; + self.parent = parent; + self.name = null; + self.index = -1; + self.kind = null; + self.element = type; + return self; + } + + + public String path() { + if (parent == null) { + return fhirType(); + } else { + return parent.path()+"." + (index == -1 ? name : name+"["+index+"]"); + } + } + + protected String basePath() { + if (parent == null || this.isResource()) { + return this.fhirType(); + } else { + return parent.basePath()+"."+name; + } + } + + public ElementKind kind() { + return kind; + } + + public String name() { + return name; + } + + public int index() { + return index; + } + + public boolean isPrimitive(String name) { + ResourceWrapper child = child(name); + return child != null && child.isPrimitive(); + } + + public boolean hasPrimitiveValue(String name) { + ResourceWrapper child = child(name); + return child != null && child.hasPrimitiveValue(); + } + + public String primitiveValue(String name) { + ResourceWrapper child = child(name); + return child == null ? null : child.primitiveValue(); + } + + public String primitiveValueMN(String... names) { + ResourceWrapper child = childMN(names); + return child == null ? null : child.primitiveValue(); + } + + public String firstPrimitiveValue(String name) { + ResourceWrapper child = firstChild(name); + return child == null ? null : child.primitiveValue(); + } + + private void loadChildren() { + if (children == null) { + children = new ArrayList<>(); + loadTheChildren(); + } + } + + + public List children() { + loadChildren(); + return children; + } + + public List childrenInGroups() { + loadChildren(); + List list = new ArrayList(); + for (ResourceWrapper e : children) { + NamedResourceWrapperList nl = null; + for (NamedResourceWrapperList t : list) { + if (t.name.equals(e.name())) { + nl = t; + } + } + if (nl == null) { + nl = new NamedResourceWrapperList(e.name()); + list.add(nl); + } + nl.values.add(e); + } + return list; + } + + public List children(String name) { + loadChildren(); + List list = new ArrayList(); + for (ResourceWrapper e : children) { + if (name.equals(e.name())) { + list.add(e); + } + } + return list; + } + + /** + * For when an item has been renamed - find by any of the names + * @param name + * @return + */ + public List childrenMN(String... names) { + loadChildren(); + List list = new ArrayList(); + for (ResourceWrapper e : children) { + for (String name : names) { + if (name.equals(e.name())) { + list.add(e); + } + } + } + return list; + } + + public ResourceWrapper child(String name) { + loadChildren(); + + ResourceWrapper res = null; + + for (ResourceWrapper e : children) { + if (name.equals(e.name()) || (name+"[x]").equals(e.name())) { + if (res == null) { + res = e; + } else { + throw new Error("Duplicated element '"+name+"' @ '"+path()+"'"); + } + } + } + return res; + } + + /** + * For when an item has been renamed - find by any of the names + * @param names + * @return + */ + public ResourceWrapper childMN(String... names) { + loadChildren(); + + ResourceWrapper res = null; + + for (ResourceWrapper e : children) { + for (String name : names) { + if (name.equals(e.name()) || (name+"[x]").equals(e.name())) { + if (res == null) { + res = e; + } else { + throw new Error("Duplicated element '"+name+"' @ '"+path()+"'"); + } + } + } + } + return res; + } + + public boolean has(String name) { + loadChildren(); + for (ResourceWrapper e : children) { + if (name.equals(e.name()) || (name+"[x]").equals(e.name())) { + return true; + } + } + return false; + } + + public boolean hasMN(String... names) { + loadChildren(); + for (ResourceWrapper e : children) { + for (String name : names) { + if (name.equals(e.name()) || (name+"[x]").equals(e.name())) { + return true; + } + } + } + return false; + } + + public ResourceWrapper resource() { + ResourceWrapper e = this.parent; + while (e != null && !e.isResource()) { + e = e.parent; + } + return e; + } + + public boolean hasChildren() { + loadChildren(); + return !children.isEmpty(); + } + + public boolean hasExtension(String url) { + loadChildren(); + for (ResourceWrapper e : children) { + if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) { + return true; + } + } + return false; + } + + public ResourceWrapper extension(String url) { + ResourceWrapper res = null; + loadChildren(); + for (ResourceWrapper e : children) { + if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) { + if (res == null) { + res = e; + } else { + throw new Error("Duplicated extension '"+url+"' @ '"+path()+"'"); + } + } + } + return res; + } + + public ResourceWrapper extensionValue(String url) { + ResourceWrapper res = null; + loadChildren(); + for (ResourceWrapper e : children) { + if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) { + if (res == null) { + res = e.child("value"); + } else { + throw new Error("Duplicated extension '"+url+"' @ '"+path()+"'"); + } + } + } + return res; + } + + public List extensions(String url) { + List res = new ArrayList(); + loadChildren(); + for (ResourceWrapper e : children) { + if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) { + res.add(e); + } + } + return res; + } + + public List extensions() { + List res = new ArrayList(); + loadChildren(); + for (ResourceWrapper e : children) { + if ("Extension".equals(e.fhirType())) { + res.add(e); + } + } + return res; + } + + public List extensionValues(String url) { + List res = new ArrayList(); + loadChildren(); + for (ResourceWrapper e : children) { + if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) { + if (e.has("value")) { + res.add(e.child("value")); + } + } + } + return res; + } + + public abstract Resource getResourceNative(); + public abstract boolean canHaveNarrative(); + public abstract XhtmlNode getNarrative(); + public abstract boolean hasNarrative(); + public abstract void setNarrative(XhtmlNode x, String status, boolean multiLangMode, Locale locale, boolean isPretty) throws IOException; + public abstract String getId(); + + public void markLanguage(XhtmlNode x, Locale locale) { + x.setAttribute("lang", locale.toString()); + x.setAttribute("xml:lang", locale.toString()); + x.addTag(0, "hr"); + x.addTag(0, "p").b().tx(locale.getDisplayName()); + x.addTag(0, "hr"); + } + + + public boolean matches(ResourceWrapper b) { + if (isEmpty() || b.isEmpty()) { + return isEmpty() && b.isEmpty(); + } else { + if (hasPrimitiveValue() || b.hasPrimitiveValue()) { + if (!hasPrimitiveValue() || !b.hasPrimitiveValue() || !primitiveValue().equals(b.primitiveValue())) { + return false; + } + } + if (children().size() != b.children().size()) { + return false; + } else { + for (int i = 0; i < children().size(); i++) { + if (!children().get(i).matches(b.children().get(i))) { + return false; + } + } + return true; + } + } + } + + public String extensionString(String url) { + ResourceWrapper re = extensionValue(url); + return re == null ? null : re.primitiveValue(); + } + + public boolean isEmpty() { + if (hasChildren()) { + for (ResourceWrapper c : children) { + if (!c.isEmpty()) { + return false; + } + } + } + return !isPrimitive() || !hasPrimitiveValue(); + } + + + public ResourceWrapper getResourceWrapper() { + ResourceWrapper focus = this; + while (focus != null && !focus.isResource()) { + focus = focus.parent; + } + return focus; + } + + public ResourceWrapper firstChild(String name) { + List list = children(name); + return list.size() == 0 ? null : list.get(0); + } + + public ContextUtilities getContextUtilities() { + return contextUtils; + } + + public String getScopedId() { + if (!isResource()) { + return null; + } else { + String res = getId(); + if (parent != null) { + res = parent.getResourceWrapper().getScopedId()+"/"+getId(); + } + return res; + } + } + + public ResourceWrapper parent() { + return parent; + } + + public ResourceWrapper getContained(String id) { + if (isResource()) { + List contained = children("contained"); + for (ResourceWrapper e : contained) { + if (id.equals(e.getId())) { + return e; + } + } + } + return null; + } + + + public abstract String getCodeSystemUri(); + public abstract boolean hasFormatComment(); + public abstract Collection getFormatCommentsPre(); + public abstract XhtmlNode getXhtml(); + public abstract Base getBase(); + public abstract String getWebPath(); + public abstract boolean isDirect(); + protected abstract void loadTheChildren(); + public abstract String fhirVersion(); + public abstract String fhirType(); + public abstract boolean isPrimitive(); + public abstract boolean hasPrimitiveValue(); + public abstract String primitiveValue(); + public abstract boolean isResource(); + + +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapperModel.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapperModel.java new file mode 100644 index 000000000..dd701528a --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapperModel.java @@ -0,0 +1,274 @@ +package org.hl7.fhir.r5.renderers.utils; + +import java.io.IOException; +import java.util.Collection; +import java.util.Locale; + +import org.hl7.fhir.r5.elementmodel.Element; +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.model.ValueSet; +import org.hl7.fhir.utilities.Utilities; +import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlComposer; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; + +/** + * This class is used to walk through the resources when rendering, whether + * the resource is a native resource or loaded by the element model + */ +public class ResourceWrapperModel extends ResourceWrapper { + + protected Element model; + + ResourceWrapperModel() { + super(); + } + + private ResourceWrapperModel makeChild(String name, int index, ElementKind kind, Element em) { + ResourceWrapperModel self = new ResourceWrapperModel(); + self.contextUtils = this.contextUtils; + self.parent = this; + self.name = name; + self.index = index; + self.kind = kind; + self.model = em; + return self; + } + + public String fhirVersion() { + return model.getFHIRPublicationVersion().toCode(); + } + + public String fhirType() { + if (kind == ElementKind.BackboneElement) { + return basePath(); + } else { + return model.fhirType(); + } + } + + public boolean isPrimitive() { + return model.isPrimitive(); + } + + public boolean hasPrimitiveValue() { + return model.hasPrimitiveValue(); + } + + public String primitiveValue() { + return model.primitiveValue(); + } + + protected void loadTheChildren() { + for (Element child : model.getChildren()) { + String name = child.getProperty().isChoice() ? child.getProperty().getName() : child.getName(); + int index = child.isList() ? child.getIndex() : -1; + ElementKind kind = determineModelKind(child); + children.add(makeChild(name, index, kind, child)); + } + } + + private ElementKind determineModelKind(Element child) { + if (child.isPrimitive()) { + return ElementKind.PrimitiveType; + } else if (child.fhirType().contains("Backbone")) { + return ElementKind.BackboneElement; + } else if (child.getProperty().getContextUtils().isDatatype(child.fhirType())) { + return ElementKind.DataType; + } else if (!child.isResource()) { + return ElementKind.BackboneElement; + } else if (parent == null) { + return ElementKind.IndependentResource; + } else switch (child.getSpecial()) { + case BUNDLE_ENTRY: + return ElementKind.BundleEntry; + case BUNDLE_ISSUES: + return ElementKind.InlineResource; + case BUNDLE_OUTCOME: + return ElementKind.InlineResource; + case CONTAINED: + return ElementKind.ContainedResource; + case PARAMETER: + return ElementKind.InlineResource; + default: + return ElementKind.IndependentResource; + } + } + + + public boolean isResource() { + return model.isResource(); + } + + public boolean canHaveNarrative() { + if (!isResource()) { + return false; + } + return contextUtils.isDomainResource(fhirType()); + } + + public XhtmlNode getNarrative() { + if (!canHaveNarrative()) { + return null; + } + ResourceWrapper text = child("text"); + if (text == null) { + return null; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return null; + } + return ((ResourceWrapperModel) div).model.getXhtml(); + } + + public boolean hasNarrative() { + if (!canHaveNarrative()) { + return false; + } + ResourceWrapper text = child("text"); + if (text == null) { + return false; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return false; + } + return ((ResourceWrapperModel) div).model.getXhtml() != null; + } + + @Override + public void setNarrative(XhtmlNode x, String status, boolean multiLangMode, Locale locale, boolean isPretty) throws IOException { + org.hl7.fhir.r5.elementmodel.Element txt = model.getNamedChild("text"); + if (txt == null) { + txt = new org.hl7.fhir.r5.elementmodel.Element("text", model.getProperty().getChild(null, "text")); + int i = 0; + while (i < model.getChildren().size() && (model.getChildren().get(i).getName().equals("id") || model.getChildren().get(i).getName().equals("meta") || model.getChildren().get(i).getName().equals("implicitRules") || model.getChildren().get(i).getName().equals("language"))) { + i++; + } + if (i >= model.getChildren().size()) + model.getChildren().add(txt); + else + model.getChildren().add(i, txt); + } + org.hl7.fhir.r5.elementmodel.Element st = txt.getNamedChild("status"); + if (st == null) { + st = new org.hl7.fhir.r5.elementmodel.Element("status", txt.getProperty().getChild(null, "status")); + txt.getChildren().add(0, st); + } + st.setValue(status); + org.hl7.fhir.r5.elementmodel.Element div = txt.getNamedChild("div"); + if (div == null) { + div = new org.hl7.fhir.r5.elementmodel.Element("div", txt.getProperty().getChild(null, "div")); + txt.getChildren().add(div); + } + // now process the xhtml + if (multiLangMode) { + XhtmlNode xd = div.getXhtml(); + if (xd == null) { + xd = new XhtmlNode(NodeType.Element, "div"); + xd.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + div.setXhtml(xd); + } else { + xd.getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang")); + } + markLanguage(x, locale); + xd.getChildNodes().add(x); + } else { + if (!x.hasAttribute("xmlns")) { + x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + } + String l = model.getChildValue("language"); + if (!Utilities.noString(l)) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", l); + x.setAttribute("xml:lang", l); + } + div.setXhtml(x); + } + div.setValue(new XhtmlComposer(XhtmlComposer.XML, isPretty).compose(div.getXhtml())); + } + + public void markLanguage(XhtmlNode x, Locale locale) { + x.setAttribute("lang", locale.toString()); + x.setAttribute("xml:lang", locale.toString()); + x.addTag(0, "hr"); + x.addTag(0, "p").b().tx(locale.getDisplayName()); + x.addTag(0, "hr"); + } + + + public String getId() { + return model.getIdBase(); + } + + @Override + public String toString() { + return name + (index == -1 ? "" : "["+index+"]")+": "+fhirType()+" ("+kind+"/"+path()+"): element = "+model.fhirType()+" -> "+model.toString(); + } + + public boolean matches(ResourceWrapperModel b) { + if (isEmpty() || b.isEmpty()) { + return isEmpty() && b.isEmpty(); + } else { + if (hasPrimitiveValue() || b.hasPrimitiveValue()) { + if (!hasPrimitiveValue() || !b.hasPrimitiveValue() || !primitiveValue().equals(b.primitiveValue())) { + return false; + } + } + if (children().size() != b.children().size()) { + return false; + } else { + for (int i = 0; i < children().size(); i++) { + if (!children().get(i).matches(b.children().get(i))) { + return false; + } + } + return true; + } + } + } + + public Resource getResourceNative() { + return null; + } + + public boolean hasFormatComment() { + return model.hasFormatComment(); + } + + public Collection getFormatCommentsPre() { + return model.getFormatCommentsPre(); + } + + public XhtmlNode getXhtml() { + return model.getXhtml(); + } + + public Base getBase() { + return model; + } + + public boolean isDirect() { + return false; + } + + public String getWebPath() { + return null; + } + + public String getCodeSystemUri() { + ElementDefinition pd = model.getProperty().getDefinition(); + if (pd != null && pd.hasBinding() && pd.getBinding().hasValueSet()) { + ValueSet vs = contextUtils.getWorker().fetchResource(ValueSet.class, pd.getBinding().getValueSet()); + if (vs != null && vs.hasCompose() && !vs.getCompose().hasExclude() && vs.getCompose().getInclude().size() == 1) { + return vs.getCompose().getIncludeFirstRep().getSystem(); + } + } + return null; + } + + +} \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapperNative.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapperNative.java new file mode 100644 index 000000000..e2240484a --- /dev/null +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/utils/ResourceWrapperNative.java @@ -0,0 +1,242 @@ +package org.hl7.fhir.r5.renderers.utils; + +import java.util.Collection; +import java.util.Locale; + +import org.hl7.fhir.r5.model.Base; +import org.hl7.fhir.r5.model.DomainResource; +import org.hl7.fhir.r5.model.ElementDefinition; +import org.hl7.fhir.r5.model.Enumeration; +import org.hl7.fhir.r5.model.Narrative; +import org.hl7.fhir.r5.model.Property; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.utilities.DebugUtilities; +import org.hl7.fhir.utilities.xhtml.NodeType; +import org.hl7.fhir.utilities.xhtml.XhtmlNode; + +/** + * This class is used to walk through the resources when rendering, whether + * the resource is a native resource or loaded by the element model + */ +public class ResourceWrapperNative extends ResourceWrapper { + + protected Base element; + + ResourceWrapperNative() { + super(); + } + + private ResourceWrapper makeChild(String name, int index, ElementKind kind, Base element) { + ResourceWrapperNative self = new ResourceWrapperNative(); + self.contextUtils = this.contextUtils; + self.parent = this; + self.name = name; + self.index = index; + self.kind = kind; + if (element == null) { + DebugUtilities.breakpoint(); + } + self.element = element; + return self; + } + + public String fhirVersion() { + return element.getFHIRPublicationVersion().toCode(); + } + + public String fhirType() { + if (kind == ElementKind.BackboneElement) { + return basePath(); + } else { + return element.fhirType(); + } + } + + public boolean isPrimitive() { + return element.isPrimitive(); + } + + public boolean hasPrimitiveValue() { + return element.hasPrimitiveValue(); + } + + public String primitiveValue() { + return element.primitiveValue(); + } + + protected void loadTheChildren() { + if (element == null) { + DebugUtilities.breakpoint(); + } + for (Property p : element.children()) { + String name = p.getName(); + int i = 0; + for (Base v : p.getValues()) { + loadElementChild(p, name, i, v); + i++; + } + } + } + + private void loadElementChild(Property p, String name, int i, Base v) { + ElementKind kind = determineModelKind(p, v); + int index = p.isList() ? i : -1; + ElementDefinition ed = null; + children.add(makeChild(name, index, kind, v)); + } + + private ElementKind determineModelKind(Property p, Base v) { + if (v.isPrimitive()) { + return ElementKind.PrimitiveType; + } else if (contextUtils.isDatatype(v.fhirType())) { + return ElementKind.DataType; + } else if (!v.isResource()) { + return ElementKind.BackboneElement; + } else if (parent == null) { + return ElementKind.IndependentResource; + } else if ("Bundle.entry".equals(fhirType()) && "resource".equals(p.getName())) { + return ElementKind.BundleEntry; + } else if ("Bundle".equals(fhirType()) && "outcome".equals(p.getName())) { + return ElementKind.InlineResource; + } else if ("Bundle".equals(fhirType()) && "issues".equals(p.getName())) { + return ElementKind.InlineResource; + } else if (isResource() && "contained".equals(p.getName())) { + return ElementKind.ContainedResource; + } else { + return ElementKind.InlineResource; + } + } + + public boolean isResource() { + return element.isResource(); + } + + public boolean canHaveNarrative() { + if (!isResource()) { + return false; + } + return element instanceof DomainResource; + } + + public XhtmlNode getNarrative() { + if (!canHaveNarrative()) { + return null; + } + ResourceWrapper text = child("text"); + if (text == null) { + return null; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return null; + } + return ((ResourceWrapperNative) div).element.getXhtml(); + } + + public boolean hasNarrative() { + if (!canHaveNarrative()) { + return false; + } + ResourceWrapper text = child("text"); + if (text == null) { + return false; + } + ResourceWrapper div = text.child("div"); + if (div == null) { + return false; + } + return ((ResourceWrapperNative) div).element.getXhtml() != null; + } + + public void setNarrative(XhtmlNode x, String status, boolean multiLangMode, Locale locale, boolean isPretty) { + if (element instanceof DomainResource) { + DomainResource r = (DomainResource) element; + r.getText().setUserData("renderer.generated", true); + if (!r.hasText() || !r.getText().hasDiv()) { + r.setText(new Narrative()); + r.getText().setStatusAsString(status); + } + if (multiLangMode) { + if (!r.getText().hasDiv()) { + XhtmlNode div = new XhtmlNode(NodeType.Element, "div"); + div.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + r.getText().setDiv(div); + } else { + r.getText().getDiv().getChildNodes().removeIf(c -> !"div".equals(c.getName()) || !c.hasAttribute("xml:lang")); + } + markLanguage(x, locale); + r.getText().getDiv().getChildNodes().add(x); + } else { + if (!x.hasAttribute("xmlns")) + x.setAttribute("xmlns", "http://www.w3.org/1999/xhtml"); + if (r.hasLanguage()) { + // use both - see https://www.w3.org/TR/i18n-html-tech-lang/#langvalues + x.setAttribute("lang", r.getLanguage()); + x.setAttribute("xml:lang", r.getLanguage()); + } + r.getText().setDiv(x); + } + } else { + throw new Error("Cannot call setNarrative on a "+element.fhirType()); + } + } + + public void markLanguage(XhtmlNode x, Locale locale) { + x.setAttribute("lang", locale.toString()); + x.setAttribute("xml:lang", locale.toString()); + x.addTag(0, "hr"); + x.addTag(0, "p").b().tx(locale.getDisplayName()); + x.addTag(0, "hr"); + } + + + public String getId() { + return element.getIdBase(); + } + + @Override + public String toString() { + return name + (index == -1 ? "" : "["+index+"]")+": "+fhirType()+" ("+kind+"/"+path()+"): native = "+element.fhirType()+" -> "+element.toString(); + } + + public Resource getResourceNative() { + ResourceWrapper focus = getResourceWrapper(); + return (Resource) ((ResourceWrapperNative) focus).element; + } + + public boolean hasFormatComment() { + return element.hasFormatComment(); + } + + public Collection getFormatCommentsPre() { + return element.getFormatCommentsPre(); + } + + public XhtmlNode getXhtml() { + return element.getXhtml(); + } + + public Base getBase() { + return element; + } + + public boolean isDirect() { + return true; + } + + public String getWebPath() { + if (isResource()) { + return ((Resource) element).getWebPath(); + } else { + return null; + } + } + + public String getCodeSystemUri() { + if (element instanceof Enumeration) { + return ((Enumeration) element).getSystem(); + } + return null; + } + +} \ No newline at end of file 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 aa4c6b0c6..dc7061576 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 @@ -1,5 +1,6 @@ package org.hl7.fhir.r5.test; +import java.io.File; import java.io.IOException; import java.time.ZoneId; import java.util.ArrayList; @@ -25,8 +26,8 @@ import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.renderers.RendererFactory; -import org.hl7.fhir.r5.renderers.utils.ElementWrappers; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ITypeParser; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; @@ -122,6 +123,12 @@ public class NarrativeGenerationTests { throw new NotImplementedException(); } + @Override + public String getCanonicalForDefaultContext() { + // TODO Auto-generated method stub + return null; + } + } public class TestTypeParser implements ITypeParser { @@ -158,6 +165,7 @@ public class NarrativeGenerationTests { private boolean meta; private boolean technical; private String register; + private String prefix; public TestDetails(Element test) { super(); @@ -170,6 +178,10 @@ public class NarrativeGenerationTests { if ("".equals(register)) { register = null; } + prefix = test.getAttribute("prefix"); + if ("".equals(prefix)) { + prefix = null; + } header = "true".equals(test.getAttribute("header")); pretty = !"false".equals(test.getAttribute("pretty")); meta = "true".equals(test.getAttribute("meta")); @@ -230,7 +242,7 @@ public class NarrativeGenerationTests { } RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); rc.setDestDir(Utilities.path("[tmp]", "narrative")); - rc.setHeader(test.isHeader()); + rc.setShowSummaryTable(test.isHeader()); rc.setDefinitionsTarget("test.html"); rc.setTerminologyServiceOptions(TerminologyServiceOptions.defaults()); rc.setParser(new TestTypeParser()); @@ -246,6 +258,9 @@ public class NarrativeGenerationTests { if (test.getSDMode() != null) { rc.setStructureMode(StructureDefinitionRendererMode.valueOf(test.getSDMode().toUpperCase())); } + if (test.prefix != null) { + rc.setUniqueLocalPrefix(test.prefix); + } Resource source; if (TestingUtilities.findTestResource("r5", "narrative", test.getId() + ".json")) { @@ -256,7 +271,7 @@ public class NarrativeGenerationTests { source = (Resource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".xml")); } - XhtmlNode x = RendererFactory.factory(source, rc).build(source); + XhtmlNode x = RendererFactory.factory(source, rc).buildNarrative(ResourceWrapper.forResource(rc.getContextUtilities(), source)); String expected = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", "output", test.getId() + ".html")); String actual = HEADER+new XhtmlComposer(true, test.pretty).compose(x)+FOOTER; String expectedFileName = CompareUtilities.tempFile("narrative", test.getId() + ".expected.html"); @@ -265,18 +280,29 @@ public class NarrativeGenerationTests { TextFile.stringToFile(actual, actualFileName); String msg = CompareUtilities.checkXMLIsSame(id, expectedFileName, actualFileName); Assertions.assertTrue(msg == null, "Output does not match expected: "+msg); - - if (test.isMeta()) { - org.hl7.fhir.r5.elementmodel.Element e = Manager.parseSingle(context, TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".xml"), FhirFormat.XML); - x = RendererFactory.factory(source, rc).render(new ElementWrappers.ResourceWrapperMetaElement(rc, e)); - expected = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", "output", test.getId() + "-meta.html")); - actual = HEADER+new XhtmlComposer(true, true).compose(x)+FOOTER; - actualFileName = CompareUtilities.tempFile("narrative", test.getId() + "-meta.actual.html"); - TextFile.stringToFile(actual, actualFileName); - msg = CompareUtilities.checkXMLIsSame(id, expectedFileName, actualFileName); - Assertions.assertTrue(msg == null, "Meta output does not match expected: "+msg); - } + String disp = RendererFactory.factory(source, rc).buildSummary(ResourceWrapper.forResource(rc.getContextUtilities(), source)); + expected = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", "output", test.getId() + ".txt")); + actual = disp; + expectedFileName = CompareUtilities.tempFile("narrative", test.getId() + ".expected.txt"); + actualFileName = CompareUtilities.tempFile("narrative", test.getId() + ".txt"); + TextFile.stringToFile(expected, expectedFileName); + TextFile.stringToFile(actual, actualFileName); + msg = CompareUtilities.checkTextIsSame(id, expected, actual); + Assertions.assertTrue(msg == null, "Summary Output does not match expected: "+msg); + + // +// if (test.isMeta()) { +// org.hl7.fhir.r5.elementmodel.Element e = Manager.parseSingle(context, TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".xml"), FhirFormat.XML); +// x = RendererFactory.factory(source, rc).build(ResourceElement.forResource(rc.getContextUtilities(), rc.getProfileUtilities(), e)); +// +// expected = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", "output", test.getId() + "-meta.html")); +// actual = HEADER+new XhtmlComposer(true, true).compose(x)+FOOTER; +// actualFileName = CompareUtilities.tempFile("narrative", test.getId() + "-meta.actual.html"); +// TextFile.stringToFile(actual, actualFileName); +// msg = CompareUtilities.checkXMLIsSame(id, expectedFileName, actualFileName); +// Assertions.assertTrue(msg == null, "Meta output does not match expected: "+msg); +// } } } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGeneratorTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGeneratorTests.java index 95e31bad7..47a6895a4 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGeneratorTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGeneratorTests.java @@ -14,8 +14,10 @@ import org.hl7.fhir.r5.formats.XmlParser; import org.hl7.fhir.r5.model.DateTimeType; import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.renderers.DataRenderer; +import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus; import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.test.utils.CompareUtilities; @@ -36,8 +38,9 @@ public class NarrativeGeneratorTests { private static RenderingContext rc; @BeforeAll - public static void setUp() throws FHIRException { + public static void setUp() throws FHIRException, IOException { rc = new RenderingContext(TestingUtilities.getSharedWorkerContext(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); + rc.setDestDir(Utilities.path("[tmp]")); } @Test @@ -48,7 +51,7 @@ public class NarrativeGeneratorTests { private void process(InputStream stream) throws FileNotFoundException, IOException, XmlPullParserException, EOperationOutcome, FHIRException { XmlParser p = new XmlParser(); DomainResource r = (DomainResource) p.parse(stream); - RendererFactory.factory(r, rc).render(r); + RendererFactory.factory(r, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), r)); FileOutputStream s = ManagedFileAccess.outStream(TestingUtilities.tempFile("gen", "gen.xml")); new XmlParser().compose(s, r, true); s.close(); @@ -71,11 +74,11 @@ public class NarrativeGeneratorTests { rc.setMode(mode); DateTimeType dt = new DateTimeType(src); - String actual = new DataRenderer(rc).display(dt); + String actual = new DataRenderer(rc).displayDataType(ResourceWrapper.forType(rc.getContextUtilities(), dt)); Assert.assertTrue("Actual = "+actual+", expected one of "+Utilities.toString(expected), Utilities.existsInList(actual, expected)); XhtmlNode node = new XhtmlNode(NodeType.Element, "p"); - new DataRenderer(rc).render(node, dt); + new DataRenderer(rc).renderDataType(new RenderingStatus(), node, ResourceWrapper.forType(rc.getContextUtilities(), dt)); actual = new XhtmlComposer(true, false).compose(node); Assert.assertTrue(actual.startsWith("

")); Assert.assertTrue(actual.endsWith("

")); diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceRoundTripTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceRoundTripTests.java index dabd3219a..ac7fa5b90 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceRoundTripTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/ResourceRoundTripTests.java @@ -23,6 +23,7 @@ import org.hl7.fhir.r5.model.DomainResource; import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.test.utils.CompareUtilities; @@ -37,7 +38,7 @@ public class ResourceRoundTripTests { public void test() throws IOException, FHIRException, EOperationOutcome { DomainResource res = (DomainResource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "unicode.xml")); RenderingContext rc = new RenderingContext(TestingUtilities.getSharedWorkerContext(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); - RendererFactory.factory(res, rc).render(res); + RendererFactory.factory(res, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), res)); IOUtils.copy(TestingUtilities.loadTestResourceStream("r5", "unicode.xml"), ManagedFileAccess.outStream(TestingUtilities.tempFile("gen", "unicode.xml"))); new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(TestingUtilities.tempFile("gen", "unicode.out.xml")), res); } diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java index ded2a8c3d..0b3ce1596 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/SnapShotGenerationTests.java @@ -40,6 +40,7 @@ import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.utils.XVerExtensionManager; import org.hl7.fhir.r5.utils.validation.IResourceValidator; @@ -291,6 +292,13 @@ public class SnapShotGenerationTests { return null; } + + @Override + public String getCanonicalForDefaultContext() { + // TODO Auto-generated method stub + return null; + } + } private static class SnapShotGenerationTestsContext implements IEvaluationContext { @@ -572,7 +580,7 @@ public class SnapShotGenerationTests { RenderingContext rc = new RenderingContext(TestingUtilities.getSharedWorkerContext(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); rc.setDestDir(Utilities.path("[tmp]", "snapshot")); rc.setProfileUtilities(new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), null, new TestPKP())); - RendererFactory.factory(output, rc).render(output); + RendererFactory.factory(output, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), output)); } if (!fail) { test.output = output; diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/rendering/ResourceElementTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/rendering/ResourceElementTests.java new file mode 100644 index 000000000..60eafd8ed --- /dev/null +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/rendering/ResourceElementTests.java @@ -0,0 +1,235 @@ +package org.hl7.fhir.r5.test.rendering; + + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.util.List; + +import org.hl7.fhir.exceptions.FHIRFormatError; +import org.hl7.fhir.r5.conformance.profile.ProfileUtilities; +import org.hl7.fhir.r5.context.ContextUtilities; +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.elementmodel.Manager; +import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat; +import org.hl7.fhir.r5.elementmodel.ValidatedFragment; +import org.hl7.fhir.r5.formats.XmlParser; +import org.hl7.fhir.r5.model.Resource; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper.ElementKind; +import org.hl7.fhir.r5.test.utils.TestingUtilities; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ResourceElementTests { + + @Test + public void testDirect() throws FHIRFormatError, IOException { + IWorkerContext worker = TestingUtilities.getSharedWorkerContext(); + Resource res = new XmlParser().parse(TestingUtilities.loadTestResource("r5", "bundle-resource-element-test.xml")); + ResourceWrapper re = ResourceWrapper.forResource(new ContextUtilities(worker), res); + checkTree(re); + } + + @Test + public void testIndirect() throws FHIRFormatError, IOException { + IWorkerContext worker = TestingUtilities.getSharedWorkerContext(); + List res = Manager.parse(worker, TestingUtilities.loadTestResourceStream("r5", "bundle-resource-element-test.xml"), FhirFormat.XML); + ResourceWrapper re = ResourceWrapper.forResource(new ContextUtilities(worker), res.get(0).getElement()); + checkTree(re); + } + + private void checkTree(ResourceWrapper bnd) { + Assertions.assertTrue(bnd.fhirType().equals("Bundle")); + Assertions.assertNull(bnd.name()); + Assertions.assertNull(bnd.getId()); + Assertions.assertEquals("Bundle", bnd.path()); + Assertions.assertEquals("5.0.0", bnd.fhirVersion()); + Assertions.assertFalse(bnd.canHaveNarrative()); + Assertions.assertFalse(bnd.hasNarrative()); + Assertions.assertEquals(ElementKind.IndependentResource, bnd.kind()); + + ResourceWrapper type = bnd.child("type"); + Assertions.assertTrue(type.fhirType().equals("code")); + Assertions.assertEquals("type", type.name()); + Assertions.assertEquals("Bundle.type", type.path()); + Assertions.assertTrue(type.isPrimitive()); + Assertions.assertTrue(type.hasPrimitiveValue()); + Assertions.assertEquals("collection", type.primitiveValue()); + Assertions.assertFalse(type.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, type.kind()); + + ResourceWrapper id = bnd.child("identifier"); + Assertions.assertEquals("Identifier", id.fhirType()); + Assertions.assertEquals("identifier", id.name()); + Assertions.assertEquals("Bundle.identifier", id.path()); + Assertions.assertFalse(id.isPrimitive()); + Assertions.assertFalse(id.hasPrimitiveValue()); + Assertions.assertTrue(id.hasChildren()); + Assertions.assertEquals(ElementKind.DataType, id.kind()); + + ResourceWrapper system = id.child("system"); + Assertions.assertEquals("uri", system.fhirType()); + Assertions.assertEquals("system", system.name()); + Assertions.assertEquals("Bundle.identifier.system", system.path()); + Assertions.assertTrue(system.isPrimitive()); + Assertions.assertTrue(system.hasPrimitiveValue()); + Assertions.assertEquals("http://something1", system.primitiveValue()); + Assertions.assertFalse(system.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, system.kind()); + + ResourceWrapper value = id.child("value"); + Assertions.assertEquals("string", value.fhirType()); + Assertions.assertEquals("value", value.name()); + Assertions.assertEquals("Bundle.identifier.value", value.path()); + Assertions.assertTrue(value.isPrimitive()); + Assertions.assertTrue(value.hasPrimitiveValue()); + Assertions.assertEquals("something2", value.primitiveValue()); + Assertions.assertFalse(value.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, value.kind()); + + int i = 0; + for (ResourceWrapper link : bnd.children("link")) { + checkLink(i, link); + i++; + } + + ResourceWrapper entry = bnd.child("entry"); + Assertions.assertEquals("Bundle.entry", entry.fhirType()); + Assertions.assertEquals("entry", entry.name()); + Assertions.assertEquals("Bundle.entry[0]", entry.path()); + Assertions.assertFalse(entry.isPrimitive()); + Assertions.assertFalse(entry.hasPrimitiveValue()); + Assertions.assertTrue(entry.hasChildren()); + Assertions.assertEquals(ElementKind.BackboneElement, entry.kind()); + + ResourceWrapper fu = entry.child("fullUrl"); + Assertions.assertEquals("uri", fu.fhirType()); + Assertions.assertEquals("fullUrl", fu.name()); + Assertions.assertEquals("Bundle.entry[0].fullUrl", fu.path()); + Assertions.assertTrue(fu.isPrimitive()); + Assertions.assertTrue(fu.hasPrimitiveValue()); + Assertions.assertEquals("http://something5", fu.primitiveValue()); + Assertions.assertFalse(fu.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, fu.kind()); + + ResourceWrapper obs = entry.child("resource"); + checkObservation(obs); + } + + private void checkObservation(ResourceWrapper obs) { + Assertions.assertTrue(obs.fhirType().equals("Observation")); + Assertions.assertEquals("resource", obs.name()); + Assertions.assertEquals("obs1", obs.getId()); + Assertions.assertEquals("Bundle.entry[0].resource", obs.path()); + Assertions.assertEquals(ElementKind.BundleEntry, obs.kind()); + Assertions.assertTrue(obs.canHaveNarrative()); + Assertions.assertTrue(obs.hasNarrative()); + Assertions.assertNotNull(obs.getNarrative()); + + List children = obs.children(); + assertEquals(5, children.size()); + + checkObsCode(children.get(3)); + + assertEquals(children.get(4), obs.child("value")); + assertEquals(children.get(4), obs.child("value[x]")); + checkObsValue(children.get(4)); + + assertEquals(children.get(2), obs.child("contained")); + checkContained(children.get(2)); + } + + private void checkContained(ResourceWrapper cont) { + Assertions.assertEquals("Provenance", cont.fhirType()); + Assertions.assertEquals("contained", cont.name()); + Assertions.assertEquals("Bundle.entry[0].resource.contained[0]", cont.path()); + Assertions.assertFalse(cont.isPrimitive()); + Assertions.assertFalse(cont.hasPrimitiveValue()); + Assertions.assertTrue(cont.hasChildren()); + Assertions.assertEquals(ElementKind.ContainedResource, cont.kind()); + } + + private void checkObsValue(ResourceWrapper obsValue) { + Assertions.assertEquals("Quantity", obsValue.fhirType()); + Assertions.assertEquals("value[x]", obsValue.name()); + Assertions.assertEquals("Bundle.entry[0].resource.value[x]", obsValue.path()); + Assertions.assertFalse(obsValue.isPrimitive()); + Assertions.assertFalse(obsValue.hasPrimitiveValue()); + Assertions.assertTrue(obsValue.hasChildren()); + Assertions.assertEquals(ElementKind.DataType, obsValue.kind()); + } + + private void checkObsCode(ResourceWrapper obsCode) { + Assertions.assertEquals("CodeableConcept", obsCode.fhirType()); + Assertions.assertEquals("code", obsCode.name()); + Assertions.assertEquals("Bundle.entry[0].resource.code", obsCode.path()); + Assertions.assertFalse(obsCode.isPrimitive()); + Assertions.assertFalse(obsCode.hasPrimitiveValue()); + Assertions.assertTrue(obsCode.hasChildren()); + Assertions.assertEquals(ElementKind.DataType, obsCode.kind()); + + ResourceWrapper txt = obsCode.children().get(1); + Assertions.assertEquals("string", txt.fhirType()); + Assertions.assertEquals("text", txt.name()); + Assertions.assertEquals("Bundle.entry[0].resource.code.text", txt.path()); + Assertions.assertTrue(txt.isPrimitive()); + Assertions.assertFalse(txt.hasPrimitiveValue()); + Assertions.assertTrue(txt.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, txt.kind()); + + ResourceWrapper e1 = txt.extension("http://something11"); + Assertions.assertEquals("Extension", e1.fhirType()); + Assertions.assertEquals("extension", e1.name()); + Assertions.assertEquals("Bundle.entry[0].resource.code.text.extension[0]", e1.path()); + Assertions.assertFalse(e1.isPrimitive()); + Assertions.assertFalse(e1.hasPrimitiveValue()); + Assertions.assertTrue(e1.hasChildren()); + Assertions.assertEquals(ElementKind.DataType, e1.kind()); + Assertions.assertEquals("http://something11", e1.primitiveValue("url")); + + ResourceWrapper ev = txt.extensionValue("http://something11"); + Assertions.assertEquals(ev, e1.child("value")); + Assertions.assertEquals(ev, e1.child("value[x]")); + + Assertions.assertEquals("string", ev.fhirType()); + Assertions.assertEquals("value[x]", ev.name()); + Assertions.assertEquals("Bundle.entry[0].resource.code.text.extension[0].value[x]", ev.path()); + Assertions.assertTrue(ev.isPrimitive()); + Assertions.assertTrue(ev.hasPrimitiveValue()); + Assertions.assertFalse(ev.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, ev.kind()); + Assertions.assertEquals("something12", ev.primitiveValue()); + } + + private void checkLink(int i, ResourceWrapper link) { + Assertions.assertEquals("Bundle.link", link.fhirType()); + Assertions.assertEquals("link", link.name()); + Assertions.assertEquals("Bundle.link["+i+"]", link.path()); + Assertions.assertFalse(link.isPrimitive()); + Assertions.assertFalse(link.hasPrimitiveValue()); + Assertions.assertTrue(link.hasChildren()); + Assertions.assertEquals(ElementKind.BackboneElement, link.kind()); + + ResourceWrapper rel = link.child("relation"); + Assertions.assertEquals("code", rel.fhirType()); + Assertions.assertEquals("relation", rel.name()); + Assertions.assertEquals("Bundle.link["+i+"].relation", rel.path()); + Assertions.assertTrue(rel.isPrimitive()); + Assertions.assertTrue(rel.hasPrimitiveValue()); + Assertions.assertEquals(i == 0 ? "self" : "next", rel.primitiveValue()); + Assertions.assertFalse(rel.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, rel.kind()); + + ResourceWrapper url = link.child("url"); + Assertions.assertEquals("uri", url.fhirType()); + Assertions.assertEquals("url", url.name()); + Assertions.assertEquals("Bundle.link["+i+"].url", url.path()); + Assertions.assertTrue(url.isPrimitive()); + Assertions.assertTrue(url.hasPrimitiveValue()); + Assertions.assertEquals(i == 0 ? "http://something3" : "http://something4", url.primitiveValue()); + Assertions.assertFalse(url.hasChildren()); + Assertions.assertEquals(ElementKind.PrimitiveType, url.kind()); + } + +} diff --git a/org.hl7.fhir.r5/src/test/resources/txCache/org.hl7.fhir.r5/vs-externals.json b/org.hl7.fhir.r5/src/test/resources/txCache/org.hl7.fhir.r5/vs-externals.json index f728ed045..fa50d1735 100644 --- a/org.hl7.fhir.r5/src/test/resources/txCache/org.hl7.fhir.r5/vs-externals.json +++ b/org.hl7.fhir.r5/src/test/resources/txCache/org.hl7.fhir.r5/vs-externals.json @@ -2,6 +2,7 @@ "http://example.org/fhir/example2" : null, "http://example.org/fhir/example1" : null, "http://somewhere/something-else" : null, + "http://hl7.org/fhir/ValueSet/concept-properties" : null, "http://loinc.org/vs/LL715-4" : null, "http://hl7.org/fhir/us/vrdr/ValueSet/vrdr-PlaceOfDeath" : null, "http://somewhere/something" : null diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java index eff5b94ab..55155e73a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/RenderingI18nContext.java @@ -44,6 +44,7 @@ public class RenderingI18nContext extends I18nBase { public static final String BUNDLE_HEADER_ENTRY = "BUNDLE_HEADER_ENTRY"; public static final String BUNDLE_HEADER_ENTRY_URL = "BUNDLE_HEADER_ENTRY_URL"; public static final String BUNDLE_HEADER_ROOT = "BUNDLE_HEADER_ROOT"; + public static final String BUNDLE_HEADER_DOCUMENT_CONTENTS = "BUNDLE_HEADER_DOCUMENT_CONTENTS"; public static final String BUNDLE_IF_MATCH = "BUNDLE_IF_MATCH"; public static final String BUNDLE_IF_MOD = "BUNDLE_IF_MOD"; public static final String BUNDLE_IF_NONE = "BUNDLE_IF_NONE"; @@ -99,6 +100,8 @@ public class RenderingI18nContext extends I18nBase { public static final String CAPABILITY_OTH_RES_ENB = "CAPABILITY_OTH_RES_ENB"; public static final String GENERAL_PAR = "GENERAL_PAR"; public static final String GENERAL_PARS = "GENERAL_PARS"; + public static final String PARS_SUMMARY_SIZE = "PARS_SUMMARY_SIZE"; + public static final String PARS_SUMMARY_LIST = "PARS_SUMMARY_LIST"; public static final String CAPABILITY_PATCH_INT = "CAPABILITY_PATCH_INT"; public static final String GENERAL_PROF = "GENERAL_PROF"; public static final String CAPABILITY_PROF_CONF = "CAPABILITY_PROF_CONF"; @@ -267,6 +270,12 @@ public class RenderingI18nContext extends I18nBase { public static final String GENERAL_REQUEST = "GENERAL_REQUEST"; public static final String DIAG_REP_REND_UNABLE = "DIAG_REP_REND_UNABLE"; public static final String DIAG_REP_REND_WHEN = "DIAG_REP_REND_WHEN"; + public static final String DIAG_REP_UNSPECIFIED_CODE = "DIAG_REP_UNSPECIFIED_CODE"; + public static final String DIAG_REP_UNSPECIFIED_SUBJECT = "DIAG_REP_UNSPECIFIED_SUBJECT"; + public static final String DIAG_REP_SUMMARY = "DIAG_REP_SUMMARY"; + public static final String LIST_UNSPECIFIED_CODE = "LIST_UNSPECIFIED_CODE"; + public static final String LIST_UNSPECIFIED_SUBJECT = "LIST_UNSPECIFIED_SUBJECT"; + public static final String LIST_SUMMARY = "LIST_SUMMARY"; public static final String EXAMPLE_SCEN_STEP_SCEN = "EXAMPLE_SCEN_STEP_SCEN"; public static final String EX_SCEN_ALT = "EX_SCEN_ALT"; public static final String EX_SCEN_BEL = "EX_SCEN_BEL"; @@ -332,6 +341,9 @@ public class RenderingI18nContext extends I18nBase { public static final String OP_OUT_OK = "OP_OUT_OK"; public static final String OP_OUT_SEV = "OP_OUT_SEV"; public static final String OP_OUT_SRC = "OP_OUT_SRC"; + public static final String OP_OUT_SUMM_NOHINT = "OP_OUT_SUMM_NOHINT"; + public static final String OP_OUT_SUMM = "OP_OUT_SUMM"; + public static final String OP_OUT_SUMM_ALL_OK = "OP_OUT_SUMM_ALL_OK"; public static final String PAT_ACTIVE = "PAT_ACTIVE"; public static final String PAT_ACTIVE_HINT = "PAT_ACTIVE_HINT"; public static final String PAT_ALT_NAME = "PAT_ALT_NAME"; @@ -374,6 +386,7 @@ public class RenderingI18nContext extends I18nBase { public static final String PROF_DRIV_EXCP = "PROF_DRIV_EXCP"; public static final String PROF_DRIV_FEXCP = "PROF_DRIV_FEXCP"; public static final String PROF_DRIV_GEN_NARR = "PROF_DRIV_GEN_NARR"; + public static final String PROF_DRIV_GEN_NARR_TECH = "PROF_DRIV_GEN_NARR_TECH"; public static final String PROV_ACT = "PROV_ACT"; public static final String PROV_AGE = "PROV_AGE"; public static final String PROV_BEHALF = "PROV_BEHALF"; @@ -454,6 +467,9 @@ public class RenderingI18nContext extends I18nBase { public static final String QUEST_UNKNOWN_MODE = "QUEST_UNKNOWN_MODE"; public static final String GENERAL_URL = "GENERAL_URL"; public static final String QUEST_VALUE = "QUEST_VALUE"; + public static final String QUEST_UNSPECIFIED_QUESTIONNAIRE = "QUEST_UNSPECIFIED_QUESTIONNAIRE"; + public static final String QUEST_UNSPECIFIED_SUBJECT = "QUEST_UNSPECIFIED_SUBJECT"; + public static final String QUEST_SUMMARY = "QUEST_SUMMARY"; public static final String REND_ADDED = "REND_ADDED"; public static final String REND_CHANGED = "REND_CHANGED"; public static final String REND_REMOVED = "REND_REMOVED"; @@ -890,7 +906,12 @@ public class RenderingI18nContext extends I18nBase { public static final String GENERAL_CODE = "GENERAL_CODE"; public static final String GENERAL_DESC = "GENERAL_DESC"; public static final String STRUC_DEF_TYPE_PARAMETER = "STRUC_DEF_TYPE_PARAMETER"; - + public static final String BUNDLE_SUMMARY = "BUNDLE_SUMMARY"; + public static final String PROF_DRIV_SUMM_PROP = "PROF_DRIV_SUMM_PROP"; + public static final String PROF_DRIV_SUMM_NONE = "PROF_DRIV_SUMM_NONE"; + public static final String PROF_DRIV_SUMM = "PROF_DRIV_SUMM"; + public static final String DOCUMENT_SUMMARY = "DOCUMENT_SUMMARY"; + protected String getMessagesSourceFileName() { return "rendering-phrases"; } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java index 39298308d..dbfa422a6 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/HierarchicalTableGenerator.java @@ -630,6 +630,7 @@ public class HierarchicalTableGenerator { private TableGenerationMode mode; private RenderingI18nContext i18n; + private String uniqueLocalPrefix; public HierarchicalTableGenerator(RenderingI18nContext i18n) { super(); @@ -904,7 +905,7 @@ public class HierarchicalTableGenerator { } } else if (!Utilities.noString(p.getReference())) { XhtmlNode a = addStyle(tc.addTag("a"), p); - a.setAttribute("href", p.getReference()); + a.setAttribute("href", prefixLocalHref(p.getReference())); if (mode == TableGenerationMode.XHTML && suppressExternals) { a.setAttribute("no-external", "true"); } @@ -944,8 +945,9 @@ public class HierarchicalTableGenerator { } } } - if (makeTargets && !Utilities.noString(anchor)) - tc.addTag("a").setAttribute("name", nmTokenize(anchor)).addText(" "); + if (makeTargets && !Utilities.noString(anchor)) { + tc.addTag("a").setAttribute("name", prefixAnchor(nmTokenize(anchor))).addText(" "); + } return tc; } @@ -1132,4 +1134,25 @@ public class HierarchicalTableGenerator { r.getCells().add(new Cell()); } } + + + public String getUniqueLocalPrefix() { + return uniqueLocalPrefix; + } + + public void setUniqueLocalPrefix(String uniqueLocalPrefix) { + this.uniqueLocalPrefix = uniqueLocalPrefix; + } + + public String prefixAnchor(String anchor) { + return uniqueLocalPrefix == null ? anchor : uniqueLocalPrefix+"-" + anchor; + } + + public String prefixLocalHref(String url) { + if (url == null || uniqueLocalPrefix == null || !url.startsWith("#")) { + return url; + } + return "#"+uniqueLocalPrefix+"-"+url.substring(1); + } + } \ No newline at end of file diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java index 4363eb7bd..cccc018a3 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/xhtml/XhtmlNode.java @@ -799,11 +799,19 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml { return span("color: "+color, null); } - public XhtmlNode param(String name) { - XhtmlNode node = new XhtmlNode(NodeType.Element, "p"); // this node is dead will never appear anywhere, but we are in paragraph mode - if (namedParams == null) { - namedParams = new HashMap<>(); + public void startScript(String name) { + if (namedParams != null) { + throw new Error("Sequence Error - script is already open @ "+name); } + namedParams = new HashMap<>(); + namedParamValues = new HashMap<>(); + } + + public XhtmlNode param(String name) { + if (namedParams == null) { + throw new Error("Sequence Error - script is not already open"); + } + XhtmlNode node = new XhtmlNode(NodeType.Element, "p"); // this node is dead will never appear anywhere, but we are in paragraph mode namedParams.put(name, node); return node; } @@ -811,40 +819,69 @@ public class XhtmlNode extends XhtmlFluent implements IBaseXhtml { public void paramValue(String name, String value) { if (namedParamValues == null) { - namedParamValues = new HashMap<>(); + throw new Error("Sequence Error - script is not already open"); } namedParamValues.put(name, value); } public void paramValue(String name, int value) { if (namedParamValues == null) { - namedParamValues = new HashMap<>(); + throw new Error("Sequence Error - script is not already open"); } namedParamValues.put(name, Integer.toString(value)); } - public void sentenceForParams(String structure) throws FHIRException, IOException { + /** + * To set up a script, you do the following: + * + * * call startScript - setting up the parameter infrastructure + * * define a set of parameters. Parameter values can be provided as string or integer, or: + * * you can use param(name) to render an arbitrarily complicated html fragment that will be inserted by the script + * * you can redefine parameters with the same name + * * call execScript() to execute the script. You can call this any number of times + * * call closeScript + * + * The script format is an xhtml fragment that can have any html in it, and also the following tags: + * param: - replace this tag with the named parameter (or delete it if no value) + * if: - condition is param op value, where value is a string, and op is =, != <, > + * + * @param structure + * @throws FHIRException + * @throws IOException + */ + public void execScript(String structure) throws FHIRException, IOException { XhtmlNode script = new XhtmlParser().parseFragment("
"+structure+"
"); - for (XhtmlNode n : script.getChildNodes()) { + parseNodes(script.getChildNodes(), this.getChildNodes()); + } + + private void parseNodes(XhtmlNodeList source, XhtmlNodeList dest) { + for (XhtmlNode n : source) { if ("param".equals(n.getName())) { XhtmlNode node = namedParams.get(n.getAttribute("name")); if (node != null) { - this.getChildNodes().addAll(node.getChildNodes()); + parseNodes(node.getChildNodes(), dest); } } else if ("if".equals(n.getName())) { String test = n.getAttribute("test"); if (passesTest(test)) { - this.getChildNodes().addAll(n.getChildNodes()); + parseNodes(n.getChildNodes(), dest); } } else { - this.getChildNodes().add(n); + dest.add(n); } } - namedParams = null; - namedParamValues = null; + } + public void closeScript() { + if (namedParams == null) { + throw new Error("Sequence Error - script is not already open"); + } + namedParams = null; + namedParamValues = null; + } + private boolean passesTest(String test) { String[] p = test.split("\\s+"); if (p.length != 3) { diff --git a/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties b/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties index 4d957579f..f8a0c22dd 100644 --- a/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties +++ b/org.hl7.fhir.utilities/src/main/resources/rendering-phrases.properties @@ -9,22 +9,22 @@ ADD_BIND_ALL_REP = All repeats ADD_BIND_ANY = Any ADD_BIND_ANY_REP = any repeat GENERAL_COMPONENT = Component -ADD_BIND_CURR_BIND = Current Binding +ADD_BIND_CURR_BIND = Current ADD_BIND_DESIG_SYS = This value set is a good set of codes to start with when designing your system GENERAL_DOCUMENTATION = Documentation ADD_BIND_EXT_PREF = A required binding, for use when the binding strength is ''extensible'' or ''preferred'' -ADD_BIND_EX_BIND = Extensible Binding +ADD_BIND_EX_BIND = Extensible ADD_BIND_GIVEN_CONT = This value set is provided to user look up in a given context ADD_BIND_MAX = Max Binding ADD_BIND_MIN = Min Binding GENERAL_BIND_MIN_ALLOW = The minimum allowable value set - any conformant system SHALL support all these codes ADD_BIND_NEW_REC = New records are required to use this value set, but legacy records may use other codes GENERAL_PREFERRED = Preferred -ADD_BIND_PREF_BIND = Preferred Binding +ADD_BIND_PREF_BIND = Preferred GENERAL_PURPOSE = Purpose ADD_BIND_RECOM_VALUE_SET = This is the value set that is recommended (documentation should explain why) GENERAL_REQUIRED = Required -ADD_BIND_REQ_BIND = Required Binding +ADD_BIND_REQ_BIND = Required GENERAL_STARTER = Starter ADD_BIND_UI = UI ADD_BIND_UI_BIND = UI Binding @@ -96,6 +96,8 @@ CAPABILITY_OPER = Operation CAPABILITY_OTH_RES_ENB = The other resources enabled for GENERAL_PAR = Parameter GENERAL_PARS = Parameters +PARS_SUMMARY_SIZE = Parameters ({0} parameters) +PARS_SUMMARY_LIST = Parameters: {0} CAPABILITY_PATCH_INT = PATCH a new resource version (patch interaction) GENERAL_PROF = Profile CAPABILITY_PROF_CONF = Profile Conformance @@ -157,7 +159,7 @@ CODE_SYS_DISP = displays CODE_SYS_DISP_PROP = displays and properties CODE_SYS_EXAMPLE = A few representative concepts are included in the code system resource CODE_SYS_FEAT = features -CODE_SYS_FOR_OID = for OID based terminology systems +CODE_SYS_FOR_OID = {0} (for OID based terminology systems) CODE_SYS_FRAGMENT = A subset of the code system concepts are included in the code system resource CODE_SYS_IN_A_HIERARCHY = in a {0} hierarchy CODE_SYS_NOTPRESENT = None of the concepts defined by the code system are included in the code system resource @@ -165,7 +167,7 @@ GENERAL_OID = OID CODE_SYS_PROP = properties CODE_SYS_REPLACED_BY = (replaced by CODE_SYS_SUPPLEMENT = This code system resource is a supplement to -CODE_SYS_THE_VALUE_SET = is the value set for all codes in this code system +CODE_SYS_THE_VALUE_SET = {0} is the value set for all codes in this code system CODE_SYS_UNDEF_HIER = in an undefined hierarchy CODE_SYS_UNKN_MODE = Unknown CodeSystemContentMode mode GENERAL_VALUESET = Value Set @@ -190,7 +192,7 @@ DATA_REND_AFTRWKNG = after waking DATA_REND_ATBKFST = at breakfast DATA_REND_ATDINR = at dinner DATA_REND_ATLUNCH = at lunch -DATA_REND_BASE64 = (base64 data - {0} bytes) +DATA_REND_BASE64 = (base64 data - {0} base64 chars) DATA_REND_BFBKFST = before breakfast DATA_REND_BFDINR = before dinner DATA_REND_BFLUNCH = before lunch @@ -252,7 +254,7 @@ DIAG_REP_REND_FOR = for DIAG_REP_REND_IDENTIFIER = Identifier GENERAL_TODO = Not done yet GENERAL_NOTE = Note -DIAG_REP_REND_NOTRES = This Observation could not be resolved +DIAG_REP_REND_NOTRES = The observation ''{0}'' could not be resolved DIAG_REP_REND_OBS = Observation DIAG_REP_REND_PER = Performer DIAG_REP_REND_REFRAN = Reference Range @@ -371,7 +373,8 @@ PAT_RELN = Relationships: PROF_DRIV_ERR_GEN_NARR = Error Generating Narrative for PROF_DRIV_EXCP = Exception Generating Narrative: {0} PROF_DRIV_FEXCP = Cannot find definition for {0} -PROF_DRIV_GEN_NARR = Generated Narrative: {0} {1} +PROF_DRIV_GEN_NARR = {0} {1} +PROF_DRIV_GEN_NARR_TECH = Generated Narrative: {0} {1} PROV_ACT = Activity PROV_AGE = Agents PROV_BEHALF = On Behalf Of @@ -450,6 +453,15 @@ QUEST_TRY = Try this questionnaire out: QUEST_TRY_QUEST = Try this QuestionnaireResponse out: QUEST_TYPE_ITEM = The type of the item QUEST_UNKNOWN_MODE = Unknown QuestionnaireResponse Renderer Mode +QUEST_UNSPECIFIED_QUESTIONNAIRE = Unspecified Questionnaire +QUEST_UNSPECIFIED_SUBJECT = Unspecified Subject +QUEST_SUMMARY = Response to Questionnaire ''{0}'' about ''{1}'' +DIAG_REP_UNSPECIFIED_CODE = Unspecified Report Type +DIAG_REP_UNSPECIFIED_SUBJECT = Unspecified Subject +DIAG_REP_SUMMARY = Diagnostic Report for ''{0}'' for ''{1}'' +LIST_UNSPECIFIED_CODE = Unspecified List Type +LIST_UNSPECIFIED_SUBJECT = Unspecified Subject +LIST_SUMMARY = List for ''{0}'' for ''{1}'' GENERAL_URL = URL QUEST_VALUE = Value Set: REND_ADDED = Added: @@ -476,17 +488,17 @@ RES_REND_DESC = . Description: (todo) RES_REND_DRAFT = draft RES_REND_ERROR = Error rendering: {0} RES_REND_GEN_SUM = . Generated Summary: -RES_REND_INFO_SOURCE = Information Source: -RES_REND_LANGUAGE = (Language +RES_REND_INFO_SOURCE = Information Source: +RES_REND_LANGUAGE = Language: {0} GENERAL_RESOURCE = Resource RES_REND_RET = retired GENERAL_SECURITY_LABEL = Security Label RES_REND_SEE_ON_THIS_PAGE = See on this page: -RES_REND_SPEC_RULES = Special rules apply: +RES_REND_SPEC_RULES = Special rules apply: {0}! RES_REND_TAG = Tag RES_REND_UNKNOWN = Unknown -RES_REND_UPDATED = Updated -RES_REND_VER = (version +RES_REND_UPDATED = Last updated: {0} +RES_REND_VER = version: {0} SD_COMP_HEAD_CARD_L = L Card. SD_COMP_HEAD_CARD_L_DESC = Minimum and Maximum # of times the element can appear in the instance - Left Structure SD_COMP_HEAD_CARD_R = R Card. @@ -891,6 +903,15 @@ STRUC_DEF_BINDINGS = Binding: STRUC_DEF_BINDING_STYLE = binding style VALUE_SET_CODES_FROM = codes from VALUE_SET_CODE_ITEM = The code for the item -VALUE_SET_CODE_SELEC = This value set cannot be fully expanded, but a selection ( {0} codes) of the whole set of codes is shown here. +VALUE_SET_CODE_SELEC = This value set cannot be fully expanded, but a selection ({0} codes) of the whole set of codes is shown here. LIST_REND_CODE = Code: {0} STRUC_DEF_TYPE_PARAMETER = Type Parameter +OP_OUT_SUMM_ALL_OK = OperationOutcome (ALL OK) +OP_OUT_SUMM_NOHINT = OperationOutcome ({0} Error(s), {1} Warning(s)) +OP_OUT_SUMM = OperationOutcome ({0} Error(s), {1} Warning(s), {2} Hint(s)) +BUNDLE_SUMMARY = {0} Bundle, {1} Entries +PROF_DRIV_SUMM_PROP = {0} = {1} +PROF_DRIV_SUMM_NONE = {0} +PROF_DRIV_SUMM = {0}: {1} +BUNDLE_HEADER_DOCUMENT_CONTENTS = Additional Resources Included in Document +DOCUMENT_SUMMARY = Document at by for in encounter diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/xhtml/XhtmlNodeTest.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/xhtml/XhtmlNodeTest.java index 5dd09e3e2..bf8c81163 100644 --- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/xhtml/XhtmlNodeTest.java +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/xhtml/XhtmlNodeTest.java @@ -180,8 +180,10 @@ public class XhtmlNodeTest { public void testComposeScripted4() throws IOException { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); XhtmlNode p = x.para(); + p.startScript("test"); p.param("long").b().tx("long"); - p.sentenceForParams("This is a paragraph"); + p.execScript("This is a paragraph"); + p.closeScript(); Assertions.assertEquals("

This is a long paragraph

", new XhtmlComposer(true, false).compose(x)); } @@ -190,9 +192,11 @@ public class XhtmlNodeTest { public void testComposeScripted5() throws IOException { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); XhtmlNode p = x.para(); + p.startScript("test"); p.param("long").b().tx("long"); p.paramValue("count", "2"); - p.sentenceForParams("This is a paragraphs"); + p.execScript("This is a paragraphs"); + p.closeScript(); Assertions.assertEquals("

This is a long paragraphs

", new XhtmlComposer(true, false).compose(x)); } @@ -201,9 +205,11 @@ public class XhtmlNodeTest { public void testComposeScripted6() throws IOException { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); XhtmlNode p = x.para(); + p.startScript("test"); p.param("long").b().tx("long"); p.paramValue("count", "1"); - p.sentenceForParams("This is a paragraphs"); + p.execScript("This is a paragraphs"); + p.closeScript(); Assertions.assertEquals("

This is a long paragraph

", new XhtmlComposer(true, false).compose(x)); } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java index 5dd66f704..d62bd106c 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/Scanner.java @@ -30,6 +30,7 @@ import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.utilities.TextFile; import org.hl7.fhir.utilities.Utilities; @@ -260,7 +261,7 @@ public class Scanner { protected void genScanOutputItem(ScanOutputItem item, String filename) throws IOException, FHIRException, EOperationOutcome { RenderingContext rc = new RenderingContext(getContext(), null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); rc.setNoSlowLookup(true); - RendererFactory.factory(item.getOutcome(), rc).render(item.getOutcome()); + RendererFactory.factory(item.getOutcome(), rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), item.getOutcome())); String s = new XhtmlComposer(XhtmlComposer.HTML).compose(item.getOutcome().getText().getDiv()); String title = item.getTitle(); @@ -313,7 +314,7 @@ public class Scanner { OperationOutcome op = new OperationOutcome(); op.addIssue().setCode(OperationOutcome.IssueType.EXCEPTION).setSeverity(OperationOutcome.IssueSeverity.FATAL).getDetails().setText(ex.getMessage()); RenderingContext rc = new RenderingContext(getContext(), null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); - RendererFactory.factory(op, rc).render(op); + RendererFactory.factory(op, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), op)); return op; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index 77a27419b..1a6cfaaac 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -61,6 +61,7 @@ import org.hl7.fhir.r5.model.StructureMap; import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.utils.EOperationOutcome; @@ -800,7 +801,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP } } } else { - RendererFactory.factory(res, rc).render((DomainResource) res); + RendererFactory.factory(res, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), res)); } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorUtils.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorUtils.java index fe8482acc..29b7ce21f 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorUtils.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidatorUtils.java @@ -28,6 +28,7 @@ import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.utils.EOperationOutcome; import org.hl7.fhir.r5.utils.OperationOutcomeUtilities; import org.hl7.fhir.utilities.ByteProvider; @@ -151,7 +152,7 @@ public class ValidatorUtils { op.addIssue().setSeverity(OperationOutcome.IssueSeverity.INFORMATION).setCode(OperationOutcome.IssueType.INFORMATIONAL).getDetails().setText(context.formatMessage(I18nConstants.ALL_OK)); } RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); - RendererFactory.factory(op, rc).render(op); + RendererFactory.factory(op, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), op)); return op; } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java index 8505eee5b..9f1a7bb7c 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/comparison/tests/ComparisonTests.java @@ -54,6 +54,7 @@ import org.hl7.fhir.r5.renderers.CodeSystemRenderer; import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer; import org.hl7.fhir.r5.renderers.ValueSetRenderer; import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; import org.hl7.fhir.r5.renderers.utils.RenderingContext.StructureDefinitionRendererMode; @@ -179,7 +180,7 @@ public class ComparisonTests { String xml2 = new XhtmlComposer(true).compose(cs.renderConcepts(csc, "", "")); TextFile.stringToFile(HEADER + hd("Messages") + xmle + BREAK + hd("Metadata") + xml1 + BREAK + hd("Concepts") + xml2 + FOOTER, Utilities.path("[tmp]", "comparison", name + ".html")); checkOutcomes(csc.getMessages(), content); - new CodeSystemRenderer(lrc).render(right); + new CodeSystemRenderer(lrc).renderResource(ResourceWrapper.forResource(lrc.getContextUtilities(), right)); checkOutput(id, content.getJsonObject("version").asString("filename"), right); } else if (left instanceof ValueSet && right instanceof ValueSet) { ValueSetComparer cs = new ValueSetComparer(session); @@ -193,7 +194,7 @@ public class ComparisonTests { String xml3 = new XhtmlComposer(true).compose(cs.renderExpansion(csc, "", "")); TextFile.stringToFile(HEADER + hd("Messages") + xmle + BREAK + hd("Metadata") + xml1 + BREAK + hd("Definition") + xml2 + BREAK + hd("Expansion") + xml3 + FOOTER, Utilities.path("[tmp]", "comparison", name + ".html")); checkOutcomes(csc.getMessages(), content); - new ValueSetRenderer(lrc).render(right); + new ValueSetRenderer(lrc).renderResource(ResourceWrapper.forResource(lrc.getContextUtilities(), right)); checkOutput(id, content.getJsonObject("version").asString("filename"), right); } else if (left instanceof StructureDefinition && right instanceof StructureDefinition) { ProfileUtilities utils = new ProfileUtilities(context, null, null); @@ -213,11 +214,11 @@ public class ComparisonTests { lrc.setStructureMode(StructureDefinitionRendererMode.DATA_DICT); - new StructureDefinitionRenderer(lrc).render(right); + new StructureDefinitionRenderer(lrc).renderResource(ResourceWrapper.forResource(lrc.getContextUtilities(), right)); checkOutput(id, content.getJsonObject("version").asString("filename-dd"), right); lrc.setStructureMode(StructureDefinitionRendererMode.SUMMARY); - new StructureDefinitionRenderer(lrc).render(right); + new StructureDefinitionRenderer(lrc).renderResource(ResourceWrapper.forResource(lrc.getContextUtilities(), right)); checkOutput(id, content.getJsonObject("version").asString("filename-tree"), right); } else if (left instanceof CapabilityStatement && right instanceof CapabilityStatement) { CapabilityStatementComparer pc = new CapabilityStatementComparer(session); @@ -412,5 +413,11 @@ public class ComparisonTests { throw new NotImplementedException(); } + @Override + public String getCanonicalForDefaultContext() { + // TODO Auto-generated method stub + return null; + } + } } \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java index 5f1cb54c6..474093a69 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/conversion/tests/SnapShotGenerationXTests.java @@ -37,6 +37,7 @@ import org.hl7.fhir.r5.renderers.RendererFactory; import org.hl7.fhir.r5.renderers.utils.RenderingContext; import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules; import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; +import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; import org.hl7.fhir.r5.test.utils.TestingUtilities; import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.utilities.Utilities; @@ -270,6 +271,12 @@ public class SnapShotGenerationXTests { return null; } + @Override + public String getCanonicalForDefaultContext() { + // TODO Auto-generated method stub + return null; + } + } private static class SnapShotGenerationTestsContext implements IEvaluationContext { @@ -541,7 +548,7 @@ public class SnapShotGenerationXTests { RenderingContext rc = new RenderingContext(TestingUtilities.getSharedWorkerContext(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE); rc.setDestDir(makeTempDir()); rc.setProfileUtilities(new ProfileUtilities(TestingUtilities.getSharedWorkerContext(), null, new TestPKP())); - RendererFactory.factory(output, rc).render(output); + RendererFactory.factory(output, rc).renderResource(ResourceWrapper.forResource(rc.getContextUtilities(), output)); } if (!fail) { test.output = output; diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/loinc.cache b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/loinc.cache index 64e66562b..3c8f154c2 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/loinc.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/loinc.cache @@ -7500,6 +7500,28 @@ v: { "system" : "http://loinc.org", "version" : "2.77", "server" : "http://tx-dev.fhir.org/r4", + "issues" : { + "resourceType" : "OperationOutcome" +} + +} +------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://loinc.org", + "code" : "100066-0" +}, "url": "http://hl7.org/fhir/test/ValueSet/package-version-test-valueset--0", "version": "0.2.0", "langs":"", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": { + "resourceType" : "Parameters", + "parameter" : [{ + "name" : "profile-url", + "valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891" + }] +}}#### +v: { + "display" : "Specular microscopy panel", + "code" : "100066-0", + "system" : "http://loinc.org", + "version" : "2.77", + "server" : "http://tx-dev.fhir.org/r4", "unknown-systems" : "", "issues" : { "resourceType" : "OperationOutcome" diff --git a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/snomed.cache b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/snomed.cache index cc526e928..e730fd454 100644 --- a/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/snomed.cache +++ b/org.hl7.fhir.validation/src/test/resources/txCache/org.hl7.fhir.validation/4.0.1/snomed.cache @@ -494,6 +494,23 @@ v: { "location" : ["CodeableConcept.coding[0].code"], "expression" : ["CodeableConcept.coding[0].code"] }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", + "valueUrl" : "http://tx-dev.fhir.org/r4" + }], + "severity" : "information", + "code" : "invalid", + "details" : { + "coding" : [{ + "system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", + "code" : "code-rule" + }], + "text" : "The code '1419004' is valid but is not active" + }, + "location" : ["CodeableConcept.coding[0].code"], + "expression" : ["CodeableConcept.coding[0].code"] + }, { "extension" : [{ "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", @@ -833,6 +850,23 @@ v: { "location" : ["CodeableConcept.coding[0].code"], "expression" : ["CodeableConcept.coding[0].code"] }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", + "valueUrl" : "http://tx-dev.fhir.org/r4" + }], + "severity" : "information", + "code" : "invalid", + "details" : { + "coding" : [{ + "system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", + "code" : "code-rule" + }], + "text" : "The code '324252006' is valid but is not active" + }, + "location" : ["CodeableConcept.coding[0].code"], + "expression" : ["CodeableConcept.coding[0].code"] + }, { "extension" : [{ "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", @@ -1075,6 +1109,23 @@ v: { "location" : ["CodeableConcept.coding[0].code"], "expression" : ["CodeableConcept.coding[0].code"] }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", + "valueUrl" : "http://tx-dev.fhir.org/r4" + }], + "severity" : "information", + "code" : "invalid", + "details" : { + "coding" : [{ + "system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", + "code" : "code-rule" + }], + "text" : "The code '602001' is valid but is not active" + }, + "location" : ["CodeableConcept.coding[0].code"], + "expression" : ["CodeableConcept.coding[0].code"] + }, { "extension" : [{ "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", @@ -1639,6 +1690,23 @@ v: { "location" : ["CodeableConcept.coding[0].code"], "expression" : ["CodeableConcept.coding[0].code"] }, + { + "extension" : [{ + "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", + "valueUrl" : "http://tx-dev.fhir.org/r4" + }], + "severity" : "information", + "code" : "invalid", + "details" : { + "coding" : [{ + "system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type", + "code" : "code-rule" + }], + "text" : "The code '1419004' is valid but is not active" + }, + "location" : ["CodeableConcept.coding[0].code"], + "expression" : ["CodeableConcept.coding[0].code"] + }, { "extension" : [{ "url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server", @@ -8305,6 +8373,51 @@ v: { "system" : "http://snomed.info/sct", "version" : "http://snomed.info/sct/900000000000207008/version/20240201", "server" : "http://tx-dev.fhir.org/r4", + "issues" : { + "resourceType" : "OperationOutcome" +} + +} +------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://snomed.info/sct", + "code" : "252829002" +}, "valueSet" :null, "langs":"", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": { + "resourceType" : "Parameters", + "parameter" : [{ + "name" : "profile-url", + "valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891" + }] +}}#### +v: { + "display" : "Corneal specular microscopy", + "code" : "252829002", + "system" : "http://snomed.info/sct", + "version" : "http://snomed.info/sct/900000000000207008/version/20240201", + "server" : "http://tx-dev.fhir.org/r4", + "unknown-systems" : "", + "issues" : { + "resourceType" : "OperationOutcome" +} + +} +------------------------------------------------------------------------------------- +{"code" : { + "system" : "http://snomed.info/sct", + "code" : "252829002" +}, "url": "http://hl7.org/fhir/test/ValueSet/package-version-test-valueset--0", "version": "0.1.0", "langs":"", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": { + "resourceType" : "Parameters", + "parameter" : [{ + "name" : "profile-url", + "valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891" + }] +}}#### +v: { + "display" : "Corneal specular microscopy", + "code" : "252829002", + "system" : "http://snomed.info/sct", + "version" : "http://snomed.info/sct/900000000000207008/version/20240201", + "server" : "http://tx-dev.fhir.org/r4", "unknown-systems" : "", "issues" : { "resourceType" : "OperationOutcome"