Merge pull request #1666 from hapifhir/2024-06-gg-rewrite-rendering

2024 06 gg rewrite rendering
This commit is contained in:
Grahame Grieve 2024-06-25 23:13:03 +10:00 committed by GitHub
commit 0b845c69b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
105 changed files with 7571 additions and 7289 deletions

View File

@ -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<String> 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;
}
}

View File

@ -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<String> 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;
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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 --------------------------------------------------------------

View File

@ -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 {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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<String> containedIds = new HashSet<>();

View File

@ -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) {

View File

@ -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";

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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<Row> rows, StructuralMatch<ElementDefinitionNode> 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<ElementDefinition>()), 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<ElementDefinition>(), 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<ElementDefinition>()), 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<ElementDefinition>(), 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;
}
}

View File

@ -16,4 +16,5 @@ public interface ProfileKnowledgeProvider {
String getLinkForProfile(StructureDefinition profile, String url);
boolean prependLinks();
String getLinkForUrl(String corePath, String s);
String getCanonicalForDefaultContext();
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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<String> done = new HashSet<String>();
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<String> done = new HashSet<String>();
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<String> done, Element child, String tgtPath) throws IOException {
private void compose(String path, Element e, Set<String> 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<Element> list = e.getChildrenByName(child.getName());
composeList(path, list, tgtPath);
composeList(path, list);
}
}
}
private void composeList(String path, List<Element> list, String tgtPath) throws IOException {
private void composeList(String path, List<Element> 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<String> done = new HashSet<String>();
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<String> done = new HashSet<String>();
for (Element child : element.getChildren()) {
compose(path+"."+element.getName(), element, done, child, tgtPath);
compose(path+"."+element.getName(), element, done, child);
}
close();
}

View File

@ -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<ElementDecoration> decorations = (List<ElementDecoration>) 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);
}
}
}

View File

@ -70,7 +70,7 @@ public class Extension extends BaseExtension implements IBaseExtension<Extension
@Override
public String toString() {
return url + "=" + value.toString();
return url + "=" + (value == null ? "null" : value.toString());
}
private static final long serialVersionUID = 465890108L;

View File

@ -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.ActorDefinition;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Library;
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.ResourceWrapper;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class ActorDefinitionRenderer extends ResourceRenderer {
public ActorDefinitionRenderer(RenderingContext context) {
super(context);
}
public ActorDefinitionRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
public ActorDefinitionRenderer(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, (ActorDefinition) r.getBase());
render(status, x, (ActorDefinition) r.getBase(), r);
} else {
throw new Error("ActorDefinitionRenderer only renders native resources directly");
}
}
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
return render(x, (ActorDefinition) dr);
@Override
public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return canonicalTitle(r);
}
public boolean render(XhtmlNode x, ActorDefinition acd) throws FHIRFormatError, DefinitionException, IOException {
public void render(RenderingStatus status, XhtmlNode x, ActorDefinition acd, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
XhtmlNode tbl = x.table("grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_ACT, acd.getName()) + " ");
@ -44,18 +52,13 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
boolean first = true;
for (UrlType t : acd.getReference()) {
if (first) first = false; else x.br();
render(td, t);
renderUri(status, td, wrapWC(r, t));
}
}
if (acd.hasCapabilities()) {
tbl.tr().td().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_CAP));
td = tr.td().colspan("2");
CapabilityStatement cs = context.getWorker().fetchResource(CapabilityStatement.class, acd.getCapabilities(), acd);
if (cs != null) {
td.ah(cs.getWebPath()).tx(cs.present());
} else {
render(td, acd.getCapabilitiesElement());
}
renderCanonical(status, r, td, CapabilityStatement.class, acd.getCapabilitiesElement());
}
if (acd.hasDerivedFrom()) {
tbl.tr().td().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_DER));
@ -63,15 +66,9 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
boolean first = true;
for (UrlType t : acd.getReference()) {
if (first) first = false; else x.br();
ActorDefinition df = context.getWorker().fetchResource(ActorDefinition.class, t.getValue(), acd);
if (df != null) {
td.ah(df.getWebPath()).tx(df.present());
} else {
render(td, t);
}
renderUri(status, r, td, t);
}
}
return false;
}
public void describe(XhtmlNode x, Library lib) {
@ -81,18 +78,5 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
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 "??";
}
}

View File

@ -4,27 +4,22 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
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.Coding;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
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.Renderer.RenderingStatus;
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.utilities.xhtml.HierarchicalTableGenerator;
@ -259,7 +254,7 @@ public class AdditionalBindingsRenderer {
if (binding.compare!=null && binding.valueSet.equals(binding.compare.valueSet))
valueset.style(STYLE_UNCHANGED);
if (br.url != null) {
XhtmlNode a = valueset.ah(determineUrl(br.url), br.uri);
XhtmlNode a = valueset.ah(context.prefixLocalHref(determineUrl(br.url)), br.uri);
a.tx(br.display);
if (br.external) {
a.tx(" ");
@ -272,7 +267,7 @@ public class AdditionalBindingsRenderer {
valueset.br();
valueset = valueset.span(STYLE_REMOVED, null);
if (compBr.url != null) {
valueset.ah(determineUrl(compBr.url), binding.compare.valueSet).tx(compBr.display);
valueset.ah(context.prefixLocalHref(determineUrl(compBr.url)), binding.compare.valueSet).tx(compBr.display);
} else {
valueset.span(null, binding.compare.valueSet).tx(compBr.display);
}
@ -290,7 +285,7 @@ public class AdditionalBindingsRenderer {
if (usage) {
if (binding.usage != null) {
// TODO: This isn't rendered at all yet. Ideally, we want it to render with comparison...
new DataRenderer(context).render(tr.td(), binding.usage);
new DataRenderer(context).renderBase(new RenderingStatus(), tr.td(), binding.usage);
} else {
tr.td();
}
@ -349,37 +344,33 @@ public class AdditionalBindingsRenderer {
case "extensible" :
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-extensible" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_VALID_EXT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_EX_BIND));
break;
case "preferred" :
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-preferred" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_RECOM_VALUE_SET)).tx(context.formatPhrase(RenderingContext.ADD_BIND_PREF_BIND));
break;
case "current" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-current" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_NEW_REC)).tx(context.formatPhrase(RenderingContext.ADD_BIND_CURR_BIND));
td.ah(corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-current", context.formatPhrase(RenderingContext.ADD_BIND_NEW_REC)).tx(context.formatPhrase(RenderingContext.ADD_BIND_CURR_BIND));
} else {
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_NEW_REC)).tx(context.formatPhrase(RenderingContext.GENERAL_REQUIRED));
}
break;
case "preferred" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-preferred" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_RECOM_VALUE_SET)).tx(context.formatPhrase(RenderingContext.ADD_BIND_PREF_BIND));
} else {
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_RECOM_VALUE_SET)).tx(context.formatPhrase(RenderingContext.GENERAL_PREFERRED));
}
break;
case "ui" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-ui" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_GIVEN_CONT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_UI_BIND));
td.ah(corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-ui", context.formatPhrase(RenderingContext.ADD_BIND_GIVEN_CONT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_UI_BIND));
} else {
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_GIVEN_CONT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_UI));
}
break;
case "starter" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-starter" : corePath+"terminologies.html#strength", "This value set is a good set of codes to start with when designing your system").tx("Starter Set");
td.ah(corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-starter", "This value set is a good set of codes to start with when designing your system").tx("Starter Set");
} else {
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_DESIG_SYS)).tx(context.formatPhrase(RenderingContext.GENERAL_STARTER));
}
break;
case "component" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-component" : corePath+"terminologies.html#strength", "This value set is a component of the base value set").tx("Component");
td.ah(corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-component", "This value set is a component of the base value set").tx("Component");
} else {
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_VALUE_COMP)).tx(context.formatPhrase(RenderingContext.GENERAL_COMPONENT));
}
@ -439,7 +430,7 @@ public class AdditionalBindingsRenderer {
children.tx("=");
}
CodeResolution ccr = 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(")");
}

View File

@ -7,171 +7,195 @@ 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.Bundle;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r5.model.Bundle.BundleEntryRequestComponent;
import org.hl7.fhir.r5.model.Bundle.BundleEntryResponseComponent;
import org.hl7.fhir.r5.model.Bundle.BundleEntrySearchComponent;
import org.hl7.fhir.r5.model.Bundle.BundleType;
import org.hl7.fhir.r5.model.Composition;
import org.hl7.fhir.r5.model.Composition.SectionComponent;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Provenance;
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.ResourceWrapper;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.utilities.DebugUtilities;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class BundleRenderer extends ResourceRenderer {
public BundleRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public BundleRenderer(RenderingContext context) {
super(context);
public BundleRenderer(RenderingContext context) {
super(context);
}
@Override
public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return context.formatPhrase(RenderingContext.BUNDLE_SUMMARY, getTranslatedCode(r.child("type")), r.children("entry").size());
}
public BundleRenderer setMultiLangMode(boolean multiLangMode) {
this.multiLangMode = multiLangMode;
return this;
}
@Override
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
XhtmlNode n = render((Bundle) r);
x.addChildren(n.getChildNodes());
return false;
}
@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 b) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
List<BaseWrapper> 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<ResourceWrapper> 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<BaseWrapper> entries) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome {
private void renderDocument(RenderingStatus status, XhtmlNode x, ResourceWrapper b, List<ResourceWrapper> 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<BaseWrapper> sections = comp.children("section");
for (BaseWrapper section : sections) {
addSection(x, section, 2, false);
List<ResourceWrapper> 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<BaseWrapper> sections = section.children("section");
for (BaseWrapper child : sections) {
List<ResourceWrapper> 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<BaseWrapper> entries, Base base) throws UnsupportedEncodingException, FHIRException, IOException {
private ResourceWrapper resolveReference(List<ResourceWrapper> 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<SectionComponent> 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<BaseWrapper> entries) throws UnsupportedEncodingException, FHIRException, IOException {
for (BaseWrapper be : entries) {
if (!"Provenance".equals(be.get("resource").fhirType())) {
public static boolean allEntriesAreHistoryProvenance(List<ResourceWrapper> 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()) {

View File

@ -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, "");
}

View File

@ -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<UsedConceptMap> maps = new ArrayList<UsedConceptMap>();
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<UsedConceptMap> maps, boolean props) throws FHIRFormatError, DefinitionException, IOException {
private void generateCodeSystemContent(RenderingStatus status, XhtmlNode x, CodeSystem cs, List<UsedConceptMap> 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<CodeSystemHierarchyMeaning> 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<UsedConceptMap> maps, String system, CodeSystem cs, List<PropertyComponent> properties, CodeSystemNavigator csNav, List<String> 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<UsedConceptMap> maps, String system, CodeSystem cs, List<PropertyComponent> properties, CodeSystemNavigator csNav, List<String> 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<ConceptDefinitionComponent> 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());
}
}
}

View File

@ -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()+
"</ul></div>\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 "??";
}
}

View File

@ -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) {

View File

@ -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<ObservationNode> 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<ResourceWrapper> 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<ObservationNode> observations = fetchObservations(pw.getValues(), dr);
buildObservationsTable(x, observations, eff, iss);
List<ResourceWrapper> items = dr.children("result");
if (!items.isEmpty()) {
List<ObservationNode> 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<ResourceWrapper> 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<ResourceWrapper> 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<ObservationNode> fetchObservations(List<BaseWrapper> list, ResourceWrapper rw) throws UnsupportedEncodingException, FHIRException, IOException {
private List<ObservationNode> fetchObservations(List<ResourceWrapper> list) throws UnsupportedEncodingException, FHIRException, IOException {
List<ObservationNode> res = new ArrayList<ObservationNode>();
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<ResourceWrapper> 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<ObservationNode> observations, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
private void buildObservationsTable(RenderingStatus status, XhtmlNode root, List<ObservationNode> 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<ObservationNode> 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<ObservationNode> 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<ObservationNode> 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<ObservationNode> observations, DataType eff) throws UnsupportedEncodingException, FHIRException, IOException {
private boolean scanObsForIssued(List<ObservationNode> 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<ObservationNode> 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<ObservationNode> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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());
}
}
}
}
}
}

View File

@ -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");
}
}

View File

@ -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<String, String> actorKeys = new HashMap<String, String>();
@ -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<String, String> actorKeys) throws IOException {
protected String toPlantUml(RenderingStatus status, ResourceWrapper res, ExampleScenarioProcessComponent process, String prefix, ExampleScenario scen, Map<String, String> actorKeys) throws IOException {
String plantUml = "group " + process.getTitle() + " " + creolLink("details", "#p_" + prefix, process.getDescription()) + "\r\n";
Map<String,Boolean> actorsActive = new HashMap<String, Boolean>();
@ -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<String,Boolean> actorsActive, Map<String, String> actorKeys) throws IOException {
protected String toPlantUml(RenderingStatus status, ResourceWrapper res, ExampleScenarioProcessStepComponent step, String prefix, ExampleScenario scen, Map<String,Boolean> actorsActive, Map<String, String> 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<String, ExampleScenarioActorComponent> 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<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> instances) throws IOException {
public void renderProcess(RenderingStatus status, XhtmlNode x, ExampleScenarioProcessComponent process, String prefix, Map<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> 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<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> instances) throws IOException {
private void stepSubProcesses(RenderingStatus status, XhtmlNode x, ExampleScenarioProcessStepComponent step, String prefix, Map<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> 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<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> instances) throws IOException {
private boolean renderStep(RenderingStatus status, XhtmlNode tbl, ExampleScenarioProcessStepComponent step, String stepLabel, Map<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> 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());
}
}

View File

@ -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 "??";
}
}

View File

@ -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<ResourceWrapper> authors = lib.children("author");
List<ResourceWrapper> editors = lib.children("editor");
List<ResourceWrapper> reviewers = lib.children("reviewer");
List<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> list, String type) throws UnsupportedEncodingException, FHIRException, IOException {
for (ResourceWrapper cd : list) {
List<ResourceWrapper> telecoms = cd.children("telecom");
if (hasContactPoint(telecoms, type)) {
return true;
}
}
return false;
}
private boolean hasContactPoint(List<ResourceWrapper> 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<ContactDetail> list, String type) {
for (ContactDetail cd : list) {
for (ContactPoint t : cd.getTelecom()) {
if (type.equals(t.getSystem().toCode())) {
return true;
private ResourceWrapper getContactPoint(List<ResourceWrapper> 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<ResourceWrapper> 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";
}
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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 "??";
}
}

View File

@ -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<String> codes = new ArrayList<>();
private List<String> 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<ElementDefinition> inScopeElements) throws IOException {
public String render(RenderingStatus status, ResourceWrapper res, String defPath, String anchorPrefix, List<ElementDefinition> 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<ElementDefinition> inScopeElements) throws FHIRFormatError, DefinitionException, IOException {
public void renderTable(RenderingStatus status, ResourceWrapper res, HierarchicalTableGenerator gen, Cell c, List<ElementDefinition> 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<XhtmlNode> children, boolean fullDoco, String defPath, String anchorPrefix, List<ElementDefinition> inScopeElements) throws FHIRFormatError, DefinitionException, IOException {
public void renderTable(RenderingStatus status, ResourceWrapper res, List<XhtmlNode> children, boolean fullDoco, String defPath, String anchorPrefix, List<ElementDefinition> 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);
}

View File

@ -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();

View File

@ -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<ResourceWrapper> 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()) {

View File

@ -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<ResourceWrapper> 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<BaseWrapper> list, int indent) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
for (BaseWrapper p : list) {
private void params(RenderingStatus status, XhtmlNode tbl, List<ResourceWrapper> 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<ParametersParameterComponent> 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);
}
}
}

View File

@ -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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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));
}
}

View File

@ -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<BaseWrapper> items = qr.children("item");
for (BaseWrapper i : items) {
hasExt = renderTreeItem(gen, row.getSubRows(), qr, i) || hasExt;
List<ResourceWrapper> 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<Row> 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<Row> 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<Row> rows, ResourceWrapper q, BaseWrapper i) throws IOException {
private boolean renderTreeItem(RenderingStatus status, HierarchicalTableGenerator gen, List<Row> rows, ResourceWrapper qr, ResourceWrapper i) throws IOException {
Row r = gen.new Row();
rows.add(r);
boolean hasExt = false;
List<BaseWrapper> items = i.children("item");
List<BaseWrapper> answers = i.children("answer");
List<ResourceWrapper> items = i.children("item");
List<ResourceWrapper> 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<BaseWrapper> 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);
}
}

View File

@ -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());
}
}

View File

@ -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");
}
}

View File

@ -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<ResourceWrapper> 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<ResourceWrapper> 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<ConformanceExpectation> 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 "??";
}
}

View File

@ -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<VersionIndependentResourceTypesAll> 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<Enumeration<VersionIndependentResourceTypesAll>> list) {

View File

@ -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<String, Map<String, ElementDefinition>> 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<String, Map<String, ElementDefinition>> 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<String> 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<String> 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<ElementDefinition> 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<Row> rows, ElementDefinition element, List<ElementDefinition> all, List<StructureDefinition> 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<Column> columns) throws IOException, FHIRException {
private Row genElement(RenderingStatus status, String defPath, HierarchicalTableGenerator gen, List<Row> rows, ElementDefinition element, List<ElementDefinition> all, List<StructureDefinition> 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<Column> 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<Cell> genElementCells(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath,
public List<Cell> 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<ElementDefinition> 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<ElementDefinition> inScopeElements, ResourceWrapper resource) throws IOException {
List<Cell> 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<ElementDefinition>());
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<ElementDefinition>(), 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<ElementDefinition> 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<ElementDefinition> 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<ElementDefinition> 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<ElementDefinition> 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<String> 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<String> 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<StructureDefinition> 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<ElementDefinition> children = new ArrayList<ElementDefinition>();
@ -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<ElementDefinition>());
generateDescription(status, gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc, new ArrayList<ElementDefinition>(), res);
}
}
} else {
@ -3295,7 +3280,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
return null;
}
public void renderDict(StructureDefinition sd, List<ElementDefinition> elements, XhtmlNode t, boolean incProfiledOut, int mode, String anchorPrefix) throws FHIRException, IOException {
public void renderDict(RenderingStatus status, StructureDefinition sd, List<ElementDefinition> elements, XhtmlNode t, boolean incProfiledOut, int mode, String anchorPrefix, ResourceWrapper res) throws FHIRException, IOException {
int i = 0;
Map<String, ElementDefinition> allAnchors = new HashMap<>();
List<ElementDefinition> 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<ElementDefinition>());
generateElementInner(status, t, sd, ec, mode, null, null, null, true, defPath, anchorPrefix, new ArrayList<ElementDefinition>(), 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<ElementDefinition> 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<ElementDefinition> 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<ElementDefinition> inScopeElements) throws IOException {
private XhtmlNode describeObligations(RenderingStatus status, ElementDefinition d, boolean root, StructureDefinition sdx, String defPath, String anchorPrefix, List<ElementDefinition> 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(" ");

View File

@ -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());
}

View File

@ -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<InteractionTrigger> 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<SearchComparator> t : rt.getComparator()) {
for (ResourceWrapper t : rt.children("comparator")) {
tr.value(context.formatPhrase(RenderingContext.GENERAL_COMPARATORS), t);
}
for (Enumeration<SearchModifierCode> 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 "??";
}
}

View File

@ -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 {

View File

@ -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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> 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 "??";
}
}

View File

@ -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<UsedConceptMap> 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<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
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<UsedConceptMap> 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<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
boolean hasExtensions = false;
private void generateExpansion(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ValueSet vs, boolean header, List<UsedConceptMap> maps) throws FHIRFormatError, DefinitionException, IOException {
List<String> langs = new ArrayList<String>();
Map<String, String> 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<String, String> 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<UsedConceptMap> maps, List<String> langs, Map<String, String> designations, boolean doDesignations, Map<String, String> properties) throws FHIRFormatError, DefinitionException, IOException {
private void addExpansionRowToTable(XhtmlNode t, ValueSet vs, ValueSetExpansionContainsComponent c, int i, boolean doLevel, boolean doDefinition, boolean doInactive, List<UsedConceptMap> maps, List<String> langs, Map<String, String> designations, boolean doDesignations, Map<String, String> 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<UsedConceptMap> maps) throws FHIRException, IOException {
boolean hasExtensions = false;
private void generateComposition(RenderingStatus status, ResourceWrapper res, XhtmlNode x, ValueSet vs, boolean header, List<UsedConceptMap> maps) throws FHIRException, IOException {
List<String> langs = new ArrayList<String>();
Map<String, String> 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<String, ConceptDefinitionComponent> definitions) throws FHIRException, IOException {
@ -1166,8 +1162,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
}
}
private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index, ValueSet vsRes) throws FHIRException, IOException {
boolean hasExtensions = false;
private void genInclude(RenderingStatus status, XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index, ValueSet vsRes) throws FHIRException, IOException {
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<String> 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)));
}
}
}

View File

@ -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());

View File

@ -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()));
}
}

View File

@ -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());

View File

@ -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()));
}
}

View File

@ -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<BaseWrapper> 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<BaseWrapper> children(String name) throws UnsupportedEncodingException, FHIRException, IOException;
public List<PropertyWrapper> children();
public String fhirType();
}
public interface ResourceWrapper extends WrapperBase {
public List<ResourceWrapper> 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<BaseWrapper> children(String name) throws UnsupportedEncodingException, FHIRException, IOException {
for (PropertyWrapper p : children()) {
if (p.getName().equals(name) || p.getName().equals(name+"[x]")) {
List<BaseWrapper> res = new ArrayList<>();
for (BaseWrapper b : p.getValues()) {
res.add(b);
}
return res;
}
}
return null;
}
}
}

View File

@ -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<ElementDefinition> children;
private List<PropertyWrapper> 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<PropertyWrapper> 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<PropertyWrapper>();
for (ElementDefinition child : children) {
List<Element> elements = new ArrayList<Element>();
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<Element> values;
private List<BaseWrapper> list;
public PropertyWrapperElement(RenderingContext context, StructureDefinition structure, ElementDefinition definition, List<Element> 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<BaseWrapper> getValues() {
if (list == null) {
list = new ArrayList<BaseWrapper>();
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<ResourceWrapper> list;
private List<PropertyWrapper> list2;
public ResourceWrapperElement(RenderingContext context, Element wrapped, StructureDefinition definition) {
super(context);
this.wrapped = wrapped;
this.definition = definition;
}
@Override
public List<ResourceWrapper> getContained() {
if (list == null) {
List<Element> children = new ArrayList<Element>();
XMLUtil.getNamedChildren(wrapped, "contained", children);
list = new ArrayList<ResourceWrapper>();
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<PropertyWrapper> children() {
if (list2 == null) {
List<ElementDefinition> children = context.getProfileUtilities().getChildList(definition, definition.getSnapshot().getElement().get(0));
list2 = new ArrayList<PropertyWrapper>();
for (ElementDefinition child : children) {
List<Element> elements = new ArrayList<Element>();
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;
}
}
}

View File

@ -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<BaseWrapper> 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<BaseWrapper> getValues() {
if (list == null) {
list = new ArrayList<BaseWrapper>();
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<PropertyWrapper> 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<PropertyWrapper> children() {
if (list == null) {
list = new ArrayList<PropertyWrapper>();
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<ResourceWrapper> getContained() {
List<ResourceWrapper> list = new ArrayList<ResourceWrapper>();
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<PropertyWrapper> children() {
List<PropertyWrapper> list = new ArrayList<PropertyWrapper>();
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;
}
}
}

View File

@ -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<ElementDefinition> children;
private List<PropertyWrapper> 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<PropertyWrapper> 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<PropertyWrapper>();
for (ElementDefinition child : children) {
List<Element> elements = new ArrayList<Element>();
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<ResourceWrapper> list;
private List<PropertyWrapper> list2;
private StructureDefinition definition;
public ResourceWrapperMetaElement(RenderingContext context, Element wrapped) {
super(context);
this.wrapped = wrapped;
this.definition = wrapped.getProperty().getStructure();
}
@Override
public List<ResourceWrapper> getContained() {
if (list == null) {
List<Element> children = wrapped.getChildrenByName("contained");
list = new ArrayList<ResourceWrapper>();
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<PropertyWrapper> children() {
if (list2 == null) {
List<ElementDefinition> children = context.getProfileUtilities().getChildList(definition, definition.getSnapshot().getElement().get(0));
list2 = new ArrayList<PropertyWrapper>();
for (ElementDefinition child : children) {
List<Element> elements = new ArrayList<Element>();
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<Element> values;
private List<BaseWrapper> list;
public PropertyWrapperMetaElement(RenderingContext context, StructureDefinition structure, ElementDefinition definition, List<Element> 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<BaseWrapper> getValues() {
if (list == null) {
list = new ArrayList<BaseWrapper>();
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;
}
}
}

View File

@ -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<String> 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<String, String> namedLinks = new HashMap<>();
private boolean addName = false;
private Map<String, String> 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;
}
}

View File

@ -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() {

View File

@ -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<ResourceWrapper> values = new ArrayList<ResourceWrapper>();
public NamedResourceWrapperList(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public List<ResourceWrapper> 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<ResourceWrapper> 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<ResourceWrapper> children() {
loadChildren();
return children;
}
public List<NamedResourceWrapperList> childrenInGroups() {
loadChildren();
List<NamedResourceWrapperList> list = new ArrayList<ResourceWrapper.NamedResourceWrapperList>();
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<ResourceWrapper> children(String name) {
loadChildren();
List<ResourceWrapper> list = new ArrayList<ResourceWrapper>();
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<ResourceWrapper> childrenMN(String... names) {
loadChildren();
List<ResourceWrapper> list = new ArrayList<ResourceWrapper>();
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<ResourceWrapper> extensions(String url) {
List<ResourceWrapper> res = new ArrayList<ResourceWrapper>();
loadChildren();
for (ResourceWrapper e : children) {
if ("Extension".equals(e.fhirType()) && url.equals(e.primitiveValue("url"))) {
res.add(e);
}
}
return res;
}
public List<ResourceWrapper> extensions() {
List<ResourceWrapper> res = new ArrayList<ResourceWrapper>();
loadChildren();
for (ResourceWrapper e : children) {
if ("Extension".equals(e.fhirType())) {
res.add(e);
}
}
return res;
}
public List<ResourceWrapper> extensionValues(String url) {
List<ResourceWrapper> res = new ArrayList<ResourceWrapper>();
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<ResourceWrapper> 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<ResourceWrapper> 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<String> 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();
}

View File

@ -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<String> 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;
}
}

View File

@ -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<String> 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;
}
}

View File

@ -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);
// }
}
}

View File

@ -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("<p>"));
Assert.assertTrue(actual.endsWith("</p>"));

View File

@ -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);
}

View File

@ -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;

View File

@ -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<ValidatedFragment> 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<ResourceWrapper> 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());
}
}

View File

@ -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

View File

@ -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";
}

View File

@ -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);
}
}

View File

@ -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: <param name="{name}"/> - replace this tag with the named parameter (or delete it if no value)
* if: <if test="{condition}"/> - 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("<div>"+structure+"</div>");
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) {

View File

@ -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: <param name="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 = <param name="status"/> Document at <param name="date"/> by <param name="author"/> for <param name="subject"/> <if test="has-encounter = true"> in encounter <param name="encounter"/></if>

View File

@ -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 <b>is</b> a <param name='long'/> paragraph");
p.execScript("This <b>is</b> a <param name='long'/> paragraph");
p.closeScript();
Assertions.assertEquals("<div><p>This <b>is</b> a <b>long</b> paragraph</p></div>", 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 <b>is</b> a <param name='long'/> paragraph<if test='count != 1'>s</if>");
p.execScript("This <b>is</b> a <param name='long'/> paragraph<if test='count != 1'>s</if>");
p.closeScript();
Assertions.assertEquals("<div><p>This <b>is</b> a <b>long</b> paragraphs</p></div>", 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 <b>is</b> a <param name='long'/> paragraph<if test='count != 1'>s</if>");
p.execScript("This <b>is</b> a <param name='long'/> paragraph<if test='count != 1'>s</if>");
p.closeScript();
Assertions.assertEquals("<div><p>This <b>is</b> a <b>long</b> paragraph</p></div>", new XhtmlComposer(true, false).compose(x));
}

View File

@ -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;
}

View File

@ -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));
}
}

Some files were not shown because too many files have changed in this diff Show More