Render extensions on some data types, and fix rendering of complex data types when doing profile rendering
This commit is contained in:
parent
a7e216e2c3
commit
38587eb508
|
@ -294,17 +294,28 @@ public class ProfileUtilities {
|
||||||
public static class SourcedChildDefinitions {
|
public static class SourcedChildDefinitions {
|
||||||
private StructureDefinition source;
|
private StructureDefinition source;
|
||||||
private List<ElementDefinition> list;
|
private List<ElementDefinition> list;
|
||||||
|
private String path;
|
||||||
public SourcedChildDefinitions(StructureDefinition source, List<ElementDefinition> list) {
|
public SourcedChildDefinitions(StructureDefinition source, List<ElementDefinition> list) {
|
||||||
super();
|
super();
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.list = list;
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
public SourcedChildDefinitions(StructureDefinition source, List<ElementDefinition> list, String path) {
|
||||||
|
super();
|
||||||
|
this.source = source;
|
||||||
|
this.list = list;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
public StructureDefinition getSource() {
|
public StructureDefinition getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
public List<ElementDefinition> getList() {
|
public List<ElementDefinition> getList() {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ElementDefinitionResolution {
|
public class ElementDefinitionResolution {
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.model.ValueSet;
|
import org.hl7.fhir.r5.model.ValueSet;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
|
||||||
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
|
||||||
|
import org.hl7.fhir.r5.renderers.Renderer.RenderingStatus;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
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.GenerationRules;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||||
|
@ -486,25 +487,46 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
public void renderExtensionsInText(RenderingStatus status, XhtmlNode div, ResourceWrapper element, String sep) throws FHIRFormatError, DefinitionException, IOException {
|
public void renderExtensionsInText(RenderingStatus status, XhtmlNode x, ResourceWrapper element, String sep) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (ResourceWrapper ext : element.extensions()) {
|
for (ResourceWrapper ext : element.extensions()) {
|
||||||
if (canRender(ext)) {
|
if (canRender(ext)) {
|
||||||
|
status.setExtensions(true);
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
div.tx(sep);
|
x.tx(sep);
|
||||||
div.tx(" ");
|
x.tx(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
String lbl = getExtensionLabel(ext);
|
String lbl = getExtensionLabel(ext);
|
||||||
div.tx(lbl);
|
x.tx(lbl);
|
||||||
div.tx(": ");
|
x.tx(": ");
|
||||||
renderDataType(status, div, ext.child("value"));
|
renderDataType(status, x, ext.child("value"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void checkRenderExtensions(RenderingStatus status, XhtmlNode x, ResourceWrapper element) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
|
if (element.has("extension")) {
|
||||||
|
boolean someCanRender = false;
|
||||||
|
for (ResourceWrapper ext : element.children("extension")) {
|
||||||
|
ResourceWrapper value = ext.child("value");
|
||||||
|
if (canRender(ext) && value.isPrimitive()) {
|
||||||
|
someCanRender = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (someCanRender) {
|
||||||
|
status.setExtensions(true);
|
||||||
|
x.tx(" (");
|
||||||
|
renderExtensionsInText(status, x, element, ", ");
|
||||||
|
x.tx(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// public void renderExtensionsInList(XhtmlNode div, BackboneType element, String sep) throws FHIRFormatError, DefinitionException, IOException {
|
// public void renderExtensionsInList(XhtmlNode div, BackboneType element, String sep) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
// boolean first = true;
|
// boolean first = true;
|
||||||
// for (Extension ext : element.getModifierExtension()) {
|
// for (Extension ext : element.getModifierExtension()) {
|
||||||
|
@ -742,13 +764,14 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canRenderDataType(String type) {
|
public boolean canRenderDataType(String type) {
|
||||||
return context.getContextUtilities().isPrimitiveType(type) || Utilities.existsInList(type, "Annotation", "Coding", "CodeableConcept", "Identifier", "HumanName", "Address",
|
return context.getContextUtilities().isPrimitiveType(type) || Utilities.existsInList(type, "Annotation", "Coding", "CodeableConcept", "Identifier", "HumanName", "Address", "Dosage",
|
||||||
"Expression", "Money", "ContactPoint", "Quantity", "Range", "Period", "Timing", "SampledData", "Reference", "UsageContext", "ContactDetail", "Ratio", "Attachment", "CodeableReference");
|
"Expression", "Money", "ContactPoint", "Quantity", "Range", "Period", "Timing", "SampledData", "Reference", "UsageContext", "ContactDetail", "Ratio", "Attachment", "CodeableReference");
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean renderDataType(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
public boolean renderDataType(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
return renderDataType(status, null, x, type);
|
return renderDataType(status, null, x, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean renderDataType(RenderingStatus status, XhtmlNode parent, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
public boolean renderDataType(RenderingStatus status, XhtmlNode parent, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -863,10 +886,11 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
renderUri(status, x, type);
|
renderUri(status, x, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRatio(RenderingStatus status, XhtmlNode x, ResourceWrapper type) {
|
private void renderRatio(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
renderQuantity(status, x, type.child("numerator"));
|
renderQuantity(status, x, type.child("numerator"));
|
||||||
x.tx("/");
|
x.tx("/");
|
||||||
renderQuantity(status, x, type.child("denominator"));
|
renderQuantity(status, x, type.child("denominator"));
|
||||||
|
checkRenderExtensions(status, x, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderAttachment(RenderingStatus status, XhtmlNode x, ResourceWrapper att) {
|
private void renderAttachment(RenderingStatus status, XhtmlNode x, ResourceWrapper att) {
|
||||||
|
@ -892,6 +916,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
private void renderDateTime(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
private void renderDateTime(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
if (!renderPrimitiveWithNoValue(status, x, type)) {
|
if (!renderPrimitiveWithNoValue(status, x, type)) {
|
||||||
x.tx(displayDateTime(type));
|
x.tx(displayDateTime(type));
|
||||||
|
checkRenderExtensions(status, x, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,7 +1027,11 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String tail(String url) {
|
protected String tail(String url) {
|
||||||
|
return url.substring(url.lastIndexOf(".")+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String utail(String url) {
|
||||||
return url.contains("/") ? url.substring(url.lastIndexOf("/")+1) : url;
|
return url.contains("/") ? url.substring(url.lastIndexOf("/")+1) : url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,6 +1068,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkRenderExtensions(status, x, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderAnnotation(RenderingStatus status, XhtmlNode x, ResourceWrapper a) throws FHIRException {
|
protected void renderAnnotation(RenderingStatus status, XhtmlNode x, ResourceWrapper a) throws FHIRException {
|
||||||
|
@ -1270,7 +1300,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
return new CodeResolution(null, null, null, code.getText(), code.getText());
|
return new CodeResolution(null, null, null, code.getText(), code.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected void renderCodingWithDetails(RenderingStatus status, XhtmlNode x, ResourceWrapper c) {
|
protected void renderCodingWithDetails(RenderingStatus status, XhtmlNode x, ResourceWrapper c) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
String s = "";
|
String s = "";
|
||||||
if (c.has("display"))
|
if (c.has("display"))
|
||||||
s = context.getTranslated(c.child("display"));
|
s = context.getTranslated(c.child("display"));
|
||||||
|
@ -1296,6 +1326,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
if (c.has("version")) {
|
if (c.has("version")) {
|
||||||
x.tx(" "+context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.primitiveValue("version"), ")"));
|
x.tx(" "+context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.primitiveValue("version"), ")"));
|
||||||
}
|
}
|
||||||
|
checkRenderExtensions(status, x, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c) {
|
protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c) {
|
||||||
|
@ -1435,6 +1466,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
|
|
||||||
x.span(null, context.formatPhrase(RenderingContext.DATA_REND_CODES) +b.toString()).addText(s);
|
x.span(null, context.formatPhrase(RenderingContext.DATA_REND_CODES) +b.toString()).addText(s);
|
||||||
}
|
}
|
||||||
|
checkRenderExtensions(status, x, cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String displayIdentifier(ResourceWrapper ii) {
|
protected String displayIdentifier(ResourceWrapper ii) {
|
||||||
|
@ -1477,7 +1509,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderIdentifier(RenderingStatus status, XhtmlNode x, ResourceWrapper ii) {
|
protected void renderIdentifier(RenderingStatus status, XhtmlNode x, ResourceWrapper ii) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
if (ii.has("type")) {
|
if (ii.has("type")) {
|
||||||
ResourceWrapper type = ii.child("type");
|
ResourceWrapper type = ii.child("type");
|
||||||
if (type.has("text")) {
|
if (type.has("text")) {
|
||||||
|
@ -1528,6 +1560,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
}
|
}
|
||||||
x.tx(")");
|
x.tx(")");
|
||||||
}
|
}
|
||||||
|
checkRenderExtensions(status, x, ii);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String displayHumanName(ResourceWrapper name) {
|
public static String displayHumanName(ResourceWrapper name) {
|
||||||
|
@ -1550,7 +1583,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void renderHumanName(RenderingStatus status, XhtmlNode x, ResourceWrapper name) {
|
protected void renderHumanName(RenderingStatus status, XhtmlNode x, ResourceWrapper name) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
StringBuilder s = new StringBuilder();
|
StringBuilder s = new StringBuilder();
|
||||||
if (name.has("text"))
|
if (name.has("text"))
|
||||||
s.append(context.getTranslated(name.child("text")));
|
s.append(context.getTranslated(name.child("text")));
|
||||||
|
@ -1568,6 +1601,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
s.append("("+context.getTranslatedCode(name.primitiveValue("use"), "http://hl7.org/fhir/name-use")+")");
|
s.append("("+context.getTranslatedCode(name.primitiveValue("use"), "http://hl7.org/fhir/name-use")+")");
|
||||||
}
|
}
|
||||||
x.addText(s.toString());
|
x.addText(s.toString());
|
||||||
|
checkRenderExtensions(status, x, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String displayAddress(ResourceWrapper address) {
|
private String displayAddress(ResourceWrapper address) {
|
||||||
|
@ -1604,8 +1638,9 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
return s.toString();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderAddress(RenderingStatus status, XhtmlNode x, ResourceWrapper address) {
|
protected void renderAddress(RenderingStatus status, XhtmlNode x, ResourceWrapper address) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
x.addText(displayAddress(address));
|
x.addText(displayAddress(address));
|
||||||
|
checkRenderExtensions(status, x, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1788,7 +1823,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
return s.toString();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderQuantity(RenderingStatus status, XhtmlNode x, ResourceWrapper q) {
|
protected void renderQuantity(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
if (q.has("comparator"))
|
if (q.has("comparator"))
|
||||||
x.addText(q.primitiveValue("comparator"));
|
x.addText(q.primitiveValue("comparator"));
|
||||||
if (q.has("value")) {
|
if (q.has("value")) {
|
||||||
|
@ -1806,6 +1841,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
if (context.isTechnicalMode() && q.has("code")) {
|
if (context.isTechnicalMode() && q.has("code")) {
|
||||||
x.span("background: LightGoldenRodYellow", null).tx(" "+ (context.formatPhrase(RenderingContext.DATA_REND_DETAILS, displaySystem(q.primitiveValue("system")))) +q.primitiveValue("code")+" = '"+lookupCode(q.primitiveValue("system"), null, q.primitiveValue("code"))+"')");
|
x.span("background: LightGoldenRodYellow", null).tx(" "+ (context.formatPhrase(RenderingContext.DATA_REND_DETAILS, displaySystem(q.primitiveValue("system")))) +q.primitiveValue("code")+" = '"+lookupCode(q.primitiveValue("system"), null, q.primitiveValue("code"))+"')");
|
||||||
}
|
}
|
||||||
|
checkRenderExtensions(status, x, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2073,7 +2109,7 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
||||||
st = st + "-"+rep.primitiveValue("frequencyMax");
|
st = st + "-"+rep.primitiveValue("frequencyMax");
|
||||||
}
|
}
|
||||||
if (rep.has("period")) {
|
if (rep.has("period")) {
|
||||||
st = st + " "+ (context.formatPhrase(RenderingContext.DATA_REND_PER))+rep.primitiveValue("period");
|
st = st + " "+ (context.formatPhrase(RenderingContext.DATA_REND_PER))+" "+rep.primitiveValue("period");
|
||||||
if (rep.has("periodMax"))
|
if (rep.has("periodMax"))
|
||||||
st = st + "-"+rep.primitiveValue("periodMax");
|
st = st + "-"+rep.primitiveValue("periodMax");
|
||||||
st = st + " "+displayTimeUnits(rep.primitiveValue("periodUnit"));
|
st = st + " "+displayTimeUnits(rep.primitiveValue("periodUnit"));
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.hl7.fhir.r5.renderers;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -19,6 +20,7 @@ import org.hl7.fhir.r5.model.ElementDefinition;
|
||||||
import org.hl7.fhir.r5.model.Resource;
|
import org.hl7.fhir.r5.model.Resource;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||||
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
|
||||||
|
import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.SourcedElementDefinition;
|
||||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||||
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
|
||||||
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper.NamedResourceWrapperList;
|
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper.NamedResourceWrapperList;
|
||||||
|
@ -49,7 +51,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
} else {
|
} else {
|
||||||
ElementDefinition ed = sd.getSnapshot().getElement().get(0);
|
ElementDefinition ed = sd.getSnapshot().getElement().get(0);
|
||||||
containedIds.clear();
|
containedIds.clear();
|
||||||
generateByProfile(status, r, sd, r, sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), context.isTechnicalMode(), 0);
|
generateByProfile(status, r, sd, r, ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), context.isTechnicalMode(), 0);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
|
@ -159,7 +161,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderLeaf(RenderingStatus status, ResourceWrapper res, ResourceWrapper ew, StructureDefinition sd, ElementDefinition defn, XhtmlNode parent, XhtmlNode x, boolean title, boolean showCodeDetails, Map<String, String> displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
private void renderLeaf(RenderingStatus status, ResourceWrapper res, ResourceWrapper ew, StructureDefinition sd, ElementDefinition defn, XhtmlNode parent, XhtmlNode x, boolean title, boolean showCodeDetails, Map<String, String> displayHints, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||||
if (ew == null)
|
if (ew == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -173,7 +175,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
} else if (!renderDataType(status, parent, x, ew)) {
|
} else if (!renderDataType(status, parent, x, ew)) {
|
||||||
// well, we have a cell (x) to render this thing, whatever it is
|
// well, we have a cell (x) to render this thing, whatever it is
|
||||||
// it's not a data type for which we have a built rendering, so we're going to get a list of it's renderable datatype properties, and render them in a list
|
// it's not a data type for which we have a built rendering, so we're going to get a list of it's renderable datatype properties, and render them in a list
|
||||||
SourcedChildDefinitions childDefs = context.getProfileUtilities().getChildMap(sd, defn);
|
// SourcedChildDefinitions childDefs = context.getProfileUtilities().getChildMap(sd, defn);
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
x.tx(" (");
|
x.tx(" (");
|
||||||
for (ResourceWrapper child : ew.children()) {
|
for (ResourceWrapper child : ew.children()) {
|
||||||
|
@ -199,24 +201,24 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean displayLeaf(ResourceWrapper res, ResourceWrapper ew, ElementDefinition defn, XhtmlNode x, String name, boolean showCodeDetails, boolean allowLinks) throws FHIRException, UnsupportedEncodingException, IOException {
|
// private boolean displayLeaf(ResourceWrapper res, ResourceWrapper ew, ElementDefinition defn, XhtmlNode x, String name, boolean showCodeDetails, boolean allowLinks) throws FHIRException, UnsupportedEncodingException, IOException {
|
||||||
if (ew == null)
|
// if (ew == null)
|
||||||
return false;
|
// return false;
|
||||||
|
//
|
||||||
Map<String, String> displayHints = readDisplayHints(defn);
|
// Map<String, String> displayHints = readDisplayHints(defn);
|
||||||
|
//
|
||||||
if (name.endsWith("[x]"))
|
// if (name.endsWith("[x]"))
|
||||||
name = name.substring(0, name.length() - 3);
|
// name = name.substring(0, name.length() - 3);
|
||||||
|
//
|
||||||
if (!showCodeDetails && ew.isPrimitive() && isDefault(displayHints, ew)) {
|
// if (!showCodeDetails && ew.isPrimitive() && isDefault(displayHints, ew)) {
|
||||||
return false;
|
// return false;
|
||||||
} else if (Utilities.existsInList(ew.fhirType(), "Extension")) {
|
// } else if (Utilities.existsInList(ew.fhirType(), "Extension")) {
|
||||||
return false;
|
// return false;
|
||||||
} else {
|
// } else {
|
||||||
x.addText(name+": "+ displayDataType(ew));
|
// x.addText(name+": "+ displayDataType(ew));
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,7 +252,8 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
return code != null && (code.equals("Element") || code.equals("BackboneElement"));
|
return code != null && (code.equals("Element") || code.equals("BackboneElement"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ElementDefinition> getChildrenForPath(StructureDefinition profile, List<ElementDefinition> elements, String path) throws DefinitionException {
|
private SourcedChildDefinitions getChildrenForPath(StructureDefinition profile, String path) throws DefinitionException {
|
||||||
|
var elements = profile.getSnapshot().getElement();
|
||||||
// do we need to do a name reference substitution?
|
// do we need to do a name reference substitution?
|
||||||
for (ElementDefinition e : elements) {
|
for (ElementDefinition e : elements) {
|
||||||
if (e.getPath().equals(path) && e.hasContentReference()) {
|
if (e.getPath().equals(path) && e.hasContentReference()) {
|
||||||
|
@ -279,45 +282,45 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
}
|
}
|
||||||
if (results.isEmpty() && t != null && t.getType().size() == 1) {
|
if (results.isEmpty() && t != null && t.getType().size() == 1) {
|
||||||
StructureDefinition tsd = context.getWorker().fetchTypeDefinition(t.getTypeFirstRep().getWorkingCode());
|
StructureDefinition tsd = context.getWorker().fetchTypeDefinition(t.getTypeFirstRep().getWorkingCode());
|
||||||
return getChildrenForPath(tsd, tsd.getSnapshot().getElement(), tsd.getType());
|
return getChildrenForPath(tsd, tsd.getType());
|
||||||
}
|
}
|
||||||
return results;
|
return new SourcedChildDefinitions(profile, results, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateByProfile(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, ResourceWrapper e, List<ElementDefinition> allElements, ElementDefinition defn, List<ElementDefinition> children, XhtmlNode x, String path, boolean showCodeDetails, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
private void generateByProfile(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, ResourceWrapper e, ElementDefinition defn, List<ElementDefinition> children, XhtmlNode x, String path, boolean showCodeDetails, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||||
if (children.isEmpty()) {
|
if (children.isEmpty()) {
|
||||||
StructureDefinition sdt = context.getWorker().fetchTypeDefinition(e.fhirType());
|
StructureDefinition sdt = context.getWorker().fetchTypeDefinition(e.fhirType());
|
||||||
if (sdt != null && (sdt.getKind() == StructureDefinitionKind.COMPLEXTYPE || sdt.getKind() == StructureDefinitionKind.PRIMITIVETYPE)) {
|
if (sdt != null && (sdt.getKind() == StructureDefinitionKind.COMPLEXTYPE || sdt.getKind() == StructureDefinitionKind.PRIMITIVETYPE)) {
|
||||||
renderLeaf(status, res, e, profile, defn, x, x, false, showCodeDetails, readDisplayHints(defn), path, indent);
|
renderLeaf(status, res, e, profile, defn, x, x, false, showCodeDetails, readDisplayHints(defn), indent);
|
||||||
} else {
|
} else {
|
||||||
// we don't have anything to render?
|
// we don't have anything to render?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
List<NamedResourceWrapperList> pl = splitExtensions(profile, e.childrenInGroups());
|
List<NamedResourceWrapperList> pl = splitExtensions(profile, e.childrenInGroups());
|
||||||
for (NamedResourceWrapperList p : pl) {
|
for (NamedResourceWrapperList p : pl) {
|
||||||
generateForProperty(status, res, profile, allElements, children, x, path, showCodeDetails, indent, false, p);
|
generateForProperty(status, res, profile, children, x, path, showCodeDetails, indent, false, p);
|
||||||
}
|
}
|
||||||
for (NamedResourceWrapperList p : pl) {
|
for (NamedResourceWrapperList p : pl) {
|
||||||
generateForProperty(status, res, profile, allElements, children, x, path, showCodeDetails, indent, true, p);
|
generateForProperty(status, res, profile, children, x, path, showCodeDetails, indent, true, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateForProperty(RenderingStatus status, ResourceWrapper res, StructureDefinition profile,
|
private void generateForProperty(RenderingStatus status, ResourceWrapper res, StructureDefinition profile,
|
||||||
List<ElementDefinition> allElements, List<ElementDefinition> children, XhtmlNode x, String path,
|
List<ElementDefinition> children, XhtmlNode x, String path,
|
||||||
boolean showCodeDetails, int indent, boolean round2, NamedResourceWrapperList p)
|
boolean showCodeDetails, int indent, boolean round2, NamedResourceWrapperList p)
|
||||||
throws UnsupportedEncodingException, IOException, EOperationOutcome {
|
throws UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||||
if (!p.getValues().isEmpty()) {
|
if (!p.getValues().isEmpty()) {
|
||||||
ElementDefinition child = getElementDefinition(children, path+"."+p.getName());
|
ElementDefinition child = getElementDefinition(children, path+"."+p.getName());
|
||||||
if (child != null) {
|
if (child != null) {
|
||||||
if (!child.getBase().hasPath() || !child.getBase().getPath().startsWith("Resource.")) {
|
if (!child.getBase().hasPath() || !child.getBase().getPath().startsWith("Resource.")) {
|
||||||
generateElementByProfile(status, res, profile, allElements, x, path, showCodeDetails, indent, p, child, round2);
|
generateElementByProfile(status, res, profile, x, path, showCodeDetails, indent, p, child, round2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateElementByProfile(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, List<ElementDefinition> allElements, XhtmlNode x, String path,
|
public void generateElementByProfile(RenderingStatus status, ResourceWrapper res, StructureDefinition profile, XhtmlNode x, String path,
|
||||||
boolean showCodeDetails, int indent, NamedResourceWrapperList p, ElementDefinition child, boolean round2) throws UnsupportedEncodingException, IOException, EOperationOutcome {
|
boolean showCodeDetails, int indent, NamedResourceWrapperList p, ElementDefinition child, boolean round2) throws UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||||
Map<String, String> displayHints = readDisplayHints(child);
|
Map<String, String> displayHints = readDisplayHints(child);
|
||||||
if ("DomainResource.contained".equals(child.getBase().getPath())) {
|
if ("DomainResource.contained".equals(child.getBase().getPath())) {
|
||||||
|
@ -336,8 +339,8 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
if (isExt) {
|
if (isExt) {
|
||||||
status.setExtensions(true);
|
status.setExtensions(true);
|
||||||
}
|
}
|
||||||
List<ElementDefinition> grandChildren = getChildrenForPath(profile, allElements, path+"."+p.getName());
|
SourcedChildDefinitions grandChildren = getChildrenForPath(profile, path+"."+p.getName());
|
||||||
filterGrandChildren(grandChildren, path+"."+p.getName(), p);
|
filterGrandChildren(grandChildren.getList(), path+"."+p.getName(), p);
|
||||||
if (p.getValues().size() > 0) {
|
if (p.getValues().size() > 0) {
|
||||||
if (isSimple(child) && !isExt) {
|
if (isSimple(child) && !isExt) {
|
||||||
XhtmlNode para = x.isPara() ? para = x : x.para();
|
XhtmlNode para = x.isPara() ? para = x : x.para();
|
||||||
|
@ -351,7 +354,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
if (renderAsList(child) && p.getValues().size() > 1) {
|
if (renderAsList(child) && p.getValues().size() > 1) {
|
||||||
XhtmlNode list = x.ul();
|
XhtmlNode list = x.ul();
|
||||||
for (ResourceWrapper v : p.getValues())
|
for (ResourceWrapper v : p.getValues())
|
||||||
renderLeaf(status, res, v, profile, child, x, list.li(), false, showCodeDetails, displayHints, path, indent);
|
renderLeaf(status, res, v, profile, child, x, list.li(), false, showCodeDetails, displayHints, indent);
|
||||||
} else {
|
} else {
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (ResourceWrapper v : p.getValues()) {
|
for (ResourceWrapper v : p.getValues()) {
|
||||||
|
@ -360,23 +363,23 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
} else {
|
} else {
|
||||||
para.tx(", ");
|
para.tx(", ");
|
||||||
}
|
}
|
||||||
renderLeaf(status, res, v, profile, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
renderLeaf(status, res, v, profile, child, x, para, false, showCodeDetails, displayHints, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (canDoTable(path, p, grandChildren, x)) {
|
} else if (canDoTable(path, p, grandChildren.getList(), x)) {
|
||||||
XhtmlNode xn = new XhtmlNode(NodeType.Element, getHeader());
|
XhtmlNode xn = new XhtmlNode(NodeType.Element, getHeader());
|
||||||
xn.addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
xn.addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
||||||
XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table");
|
XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table");
|
||||||
tbl.setAttribute("class", "grid");
|
tbl.setAttribute("class", "grid");
|
||||||
XhtmlNode tr = tbl.tr();
|
XhtmlNode tr = tbl.tr();
|
||||||
tr.td().style("display: none").tx("-"); // work around problem with empty table rows
|
tr.td().style("display: none").tx("-"); // work around problem with empty table rows
|
||||||
boolean add = addColumnHeadings(tr, grandChildren);
|
boolean add = addColumnHeadings(tr, grandChildren.getList());
|
||||||
for (ResourceWrapper v : p.getValues()) {
|
for (ResourceWrapper v : p.getValues()) {
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
tr = tbl.tr();
|
tr = tbl.tr();
|
||||||
tr.td().style("display: none").tx("*"); // work around problem with empty table rows
|
tr.td().style("display: none").tx("*"); // work around problem with empty table rows
|
||||||
add = addColumnValues(status, res, tr, profile, grandChildren, v, showCodeDetails, displayHints, path, indent) || add;
|
add = addColumnValues(status, res, tr, profile, grandChildren.getList(), v, showCodeDetails, displayHints, indent) || add;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (add) {
|
if (add) {
|
||||||
|
@ -393,7 +396,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
XhtmlNode para = x.para();
|
XhtmlNode para = x.para();
|
||||||
para.b().addText(labelforExtension(sd, p.getUrl()));
|
para.b().addText(labelforExtension(sd, p.getUrl()));
|
||||||
para.tx(": ");
|
para.tx(": ");
|
||||||
renderLeaf(status, res, vp, profile, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
renderLeaf(status, res, vp, profile, child, x, para, false, showCodeDetails, displayHints, indent);
|
||||||
} else if (!ev.isEmpty()) {
|
} else if (!ev.isEmpty()) {
|
||||||
XhtmlNode bq = x.addTag("blockquote");
|
XhtmlNode bq = x.addTag("blockquote");
|
||||||
bq.para().b().addText(labelforExtension(sd, p.getUrl()));
|
bq.para().b().addText(labelforExtension(sd, p.getUrl()));
|
||||||
|
@ -410,13 +413,13 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
XhtmlNode li = ul.li();
|
XhtmlNode li = ul.li();
|
||||||
li.tx(labelForSubExtension(vv.primitiveValue("url"), sd));
|
li.tx(labelForSubExtension(vv.primitiveValue("url"), sd));
|
||||||
li.tx(": ");
|
li.tx(": ");
|
||||||
renderLeaf(status, res, vv.child("value"), sd, child, x, li, isExt, showCodeDetails, displayHints, path, indent);
|
renderLeaf(status, res, vv.child("value"), sd, child, x, li, isExt, showCodeDetails, displayHints, indent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (ResourceWrapper vv : ev) {
|
for (ResourceWrapper vv : ev) {
|
||||||
StructureDefinition ex = context.getWorker().fetchTypeDefinition("Extension");
|
StructureDefinition ex = context.getWorker().fetchTypeDefinition("Extension");
|
||||||
List<ElementDefinition> children = getChildrenForPath(profile, ex.getSnapshot().getElement(), "Extension");
|
SourcedChildDefinitions children = getChildrenForPath(ex, "Extension");
|
||||||
generateByProfile(status, res, ex, vv, allElements, child, children, bq, "Extension", showCodeDetails, indent+1);
|
generateByProfile(status, res, ex, vv, child, children.getList(), bq, "Extension", showCodeDetails, indent+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,7 +430,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
XhtmlNode bq = x.addTag("blockquote");
|
XhtmlNode bq = x.addTag("blockquote");
|
||||||
bq.para().b().addText(p.getName());
|
bq.para().b().addText(p.getName());
|
||||||
generateByProfile(status, res, profile, v, allElements, child, grandChildren, bq, path+"."+p.getName(), showCodeDetails, indent+1);
|
generateByProfile(status, res, grandChildren.getSource(), v, child, grandChildren.getList(), bq, grandChildren.getPath(), showCodeDetails, indent+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,6 +438,29 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// private String getGrandChildBase(List<ElementDefinition> grandChildren) {
|
||||||
|
// if (grandChildren == null || grandChildren.isEmpty()) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// String[] path = grandChildren.get(0).getPath().split("\\.");
|
||||||
|
// for (int i = 1; i < grandChildren.size(); i++) {
|
||||||
|
// path = getSharedString(path, grandChildren.get(1).getPath().split("\\."));
|
||||||
|
// }
|
||||||
|
// return CommaSeparatedStringBuilder.join(".", path);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private String[] getSharedString(String[] path, String[] path2) {
|
||||||
|
// int m = -1;
|
||||||
|
// for (int i = 0; i < Integer.min(path.length, path2.length); i++) {
|
||||||
|
// if (path[i].equals(path2[i])) {
|
||||||
|
// m = i;
|
||||||
|
// } else {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return m == -1 ? new String[0] : Arrays.copyOfRange(path, 0, m+1);
|
||||||
|
// }
|
||||||
|
|
||||||
private String labelForSubExtension(String url, StructureDefinition sd) {
|
private String labelForSubExtension(String url, StructureDefinition sd) {
|
||||||
return url;
|
return url;
|
||||||
|
@ -530,7 +556,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addColumnValues(RenderingStatus status, ResourceWrapper res, XhtmlNode tr, StructureDefinition profile, List<ElementDefinition> grandChildren, ResourceWrapper v, boolean showCodeDetails, Map<String, String> displayHints, String path, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
private boolean addColumnValues(RenderingStatus status, ResourceWrapper res, XhtmlNode tr, StructureDefinition profile, List<ElementDefinition> grandChildren, ResourceWrapper v, boolean showCodeDetails, Map<String, String> displayHints, int indent) throws FHIRException, UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||||
boolean b = false;
|
boolean b = false;
|
||||||
for (ElementDefinition e : grandChildren) {
|
for (ElementDefinition e : grandChildren) {
|
||||||
List<ResourceWrapper> p = v.children(e.getPath().substring(e.getPath().lastIndexOf(".")+1));
|
List<ResourceWrapper> p = v.children(e.getPath().substring(e.getPath().lastIndexOf(".")+1));
|
||||||
|
@ -542,7 +568,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
for (ResourceWrapper vv : p) {
|
for (ResourceWrapper vv : p) {
|
||||||
b = true;
|
b = true;
|
||||||
td.sep(", ");
|
td.sep(", ");
|
||||||
renderLeaf(status, res, vv, profile, e, td, td, false, showCodeDetails, displayHints, path, indent);
|
renderLeaf(status, res, vv, profile, e, td, td, false, showCodeDetails, displayHints, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,6 +682,10 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||||
return path.substring(path.lastIndexOf(".")+1);
|
return path.substring(path.lastIndexOf(".")+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected String utail(String path) {
|
||||||
|
return path.contains("/") ? path.substring(path.lastIndexOf("/")+1) : path;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canRender(Resource resource) {
|
public boolean canRender(Resource resource) {
|
||||||
return context.getWorker().getResourceNames().contains(resource.fhirType());
|
return context.getWorker().getResourceNames().contains(resource.fhirType());
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||||
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
|
||||||
import org.hl7.fhir.utilities.Utilities;
|
import org.hl7.fhir.utilities.Utilities;
|
||||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
||||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
|
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
|
||||||
|
@ -369,8 +368,10 @@ public abstract class ResourceRenderer extends DataRenderer {
|
||||||
} else {
|
} else {
|
||||||
x.tx("??");
|
x.tx("??");
|
||||||
}
|
}
|
||||||
|
checkRenderExtensions(status, x, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void renderReference(ResourceWrapper res, HierarchicalTableGenerator gen, List<Piece> pieces, Reference r, boolean allowLinks) throws UnsupportedEncodingException, IOException {
|
public void renderReference(ResourceWrapper res, HierarchicalTableGenerator gen, List<Piece> pieces, Reference r, boolean allowLinks) throws UnsupportedEncodingException, IOException {
|
||||||
if (r == null) {
|
if (r == null) {
|
||||||
pieces.add(gen.new Piece(null, "null!", null));
|
pieces.add(gen.new Piece(null, "null!", null));
|
||||||
|
|
Loading…
Reference in New Issue