migrate r5 changes to r4b

This commit is contained in:
Grahame Grieve 2022-08-09 22:29:59 +10:00
parent e2d1cbfffa
commit 1aab88f6a7
10 changed files with 389 additions and 70 deletions

View File

@ -624,6 +624,8 @@ public class ProfileUtilities extends TranslatingUtilities {
throw new DefinitionException(context.formatMessage(I18nConstants.BASE__DERIVED_PROFILES_HAVE_DIFFERENT_TYPES____VS___, base.getUrl(), base.getType(), derived.getUrl(), derived.getType()));
}
fixTypeOfResourceId(base);
if (snapshotStack.contains(derived.getUrl())) {
throw new DefinitionException(context.formatMessage(I18nConstants.CIRCULAR_SNAPSHOT_REFERENCES_DETECTED_CANNOT_GENERATE_SNAPSHOT_STACK__, snapshotStack.toString()));
}
@ -803,6 +805,25 @@ public class ProfileUtilities extends TranslatingUtilities {
}
}
private void fixTypeOfResourceId(StructureDefinition base) {
if (base.getKind() == StructureDefinitionKind.RESOURCE && (base.getFhirVersion() == null || VersionUtilities.isR4Plus(base.getFhirVersion().toCode()))) {
fixTypeOfResourceId(base.getSnapshot().getElement());
fixTypeOfResourceId(base.getDifferential().getElement());
}
}
private void fixTypeOfResourceId(List<ElementDefinition> list) {
for (ElementDefinition ed : list) {
if (ed.hasBase() && ed.getBase().getPath().equals("Resource.id")) {
for (TypeRefComponent tr : ed.getType()) {
tr.setCode("http://hl7.org/fhirpath/System.String");
tr.removeExtension(ToolingExtensions.EXT_FHIR_TYPE);
ToolingExtensions.addUrlExtension(tr, ToolingExtensions.EXT_FHIR_TYPE, "id");
}
}
}
}
public void checkDifferentialBaseType(StructureDefinition derived) throws Error {
if (derived.hasDifferential() && !derived.getDifferential().getElementFirstRep().getPath().contains(".") && !derived.getDifferential().getElementFirstRep().getType().isEmpty()) {
if (wantFixDifferentialFirstElementType && typeMatchesAncestor(derived.getDifferential().getElementFirstRep().getType(), derived.getBaseDefinition())) {
@ -3740,7 +3761,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
} else if (Utilities.isAbsoluteUrl(u)) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u);
if (sd != null) {
if (sd != null && pkp != null) {
String disp = sd.hasTitle() ? sd.getTitle() : sd.getName();
String ref = pkp.getLinkForProfile(null, sd.getUrl());
if (ref != null && ref.contains("|"))
@ -4214,6 +4235,7 @@ public class ProfileUtilities extends TranslatingUtilities {
Row currRow = row;
List<ElementChoiceGroup> groups = readChoices(element, children);
boolean isExtension = Utilities.existsInList(tail(element.getPath()), "extension", "modifierExtension");
if (!element.prohibited()) {
for (ElementDefinition child : children) {
if (!child.hasSliceName()) {
currRow = row;
@ -4224,6 +4246,7 @@ public class ProfileUtilities extends TranslatingUtilities {
currRow = genElement(defPath, gen, childRow.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, currRow, mustSupport, rc);
}
}
}
// if (!snapshot && (extensions == null || !extensions))
// for (ElementDefinition child : children)
// if (child.getPath().endsWith(".extension") || child.getPath().endsWith(".modifierExtension"))
@ -4334,7 +4357,7 @@ public class ProfileUtilities extends TranslatingUtilities {
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(DERIVATION_POINTER), used.used, profile == null ? "" : profile.getUrl(), eurl, profile, corePath, imagePath, root, logicalModel, allInvariants, snapshot, mustSupport, allowSubRows, rc));
} else {
String name = urltail(eurl);
String name = element.hasSliceName() ? element.getSliceName() : urltail(eurl);
nameCell.getPieces().get(0).setText(name);
// left.getPieces().get(0).setReference((String) extDefn.getExtensionStructure().getTag("filename"));
nameCell.getPieces().get(0).setHint(translate("sd.table", "Extension URL")+" = "+extDefn.getUrl());

View File

@ -11464,6 +11464,26 @@ When pattern[x] is used to constrain a complex object, it means that each proper
return getType().size() == 1 && Utilities.existsInList(getType().get(0).getCode(), "Element", "BackboneElement");
}
public boolean prohibited() {
return "0".equals(getMax());
}
public boolean hasFixedOrPattern() {
return hasFixed() || hasPattern();
}
public DataType getFixedOrPattern() {
return hasFixed() ? getFixed() : getPattern();
}
public boolean isProhibited() {
return "0".equals(getMax());
}
public boolean isRequired() {
return getMin() == 1;
}
// end addition

View File

@ -1,5 +1,9 @@
package org.hl7.fhir.r4b.renderers;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
@ -9,8 +13,12 @@ import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.time.format.ResolverStyle;
import java.time.format.SignStyle;
import java.util.Currency;
import java.util.List;
import java.util.TimeZone;
@ -22,6 +30,7 @@ import org.hl7.fhir.r4b.context.IWorkerContext;
import org.hl7.fhir.r4b.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r4b.model.Address;
import org.hl7.fhir.r4b.model.Annotation;
import org.hl7.fhir.r4b.model.BackboneType;
import org.hl7.fhir.r4b.model.Base;
import org.hl7.fhir.r4b.model.BaseDateTimeType;
import org.hl7.fhir.r4b.model.CanonicalResource;
@ -39,6 +48,8 @@ import org.hl7.fhir.r4b.model.DataRequirement.SortDirection;
import org.hl7.fhir.r4b.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.r4b.model.DataType;
import org.hl7.fhir.r4b.model.DateTimeType;
import org.hl7.fhir.r4b.model.DateType;
import org.hl7.fhir.r4b.model.ElementDefinition;
import org.hl7.fhir.r4b.model.Enumeration;
import org.hl7.fhir.r4b.model.Expression;
import org.hl7.fhir.r4b.model.Extension;
@ -69,6 +80,7 @@ import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r4b.renderers.utils.RenderingContext;
import org.hl7.fhir.r4b.renderers.utils.RenderingContext.ResourceRendererMode;
import org.hl7.fhir.r4b.utils.ToolingExtensions;
import org.hl7.fhir.r4b.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
@ -348,8 +360,138 @@ public class DataRenderer extends Renderer {
return value.primitiveValue();
}
// -- 6. General purpose extension rendering ----------------------------------------------
// -- 5. Data type Rendering ----------------------------------------------
public boolean hasRenderableExtensions(DataType element) {
for (Extension ext : element.getExtension()) {
if (canRender(ext)) {
return true;
}
}
return false;
}
public boolean hasRenderableExtensions(BackboneType element) {
for (Extension ext : element.getExtension()) {
if (canRender(ext)) {
return true;
}
}
return element.hasModifierExtension();
}
private String getExtensionLabel(Extension ext) {
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.getUrl());
if (sd != null && ext.getValue().isPrimitive() && sd.hasSnapshot()) {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (Utilities.existsInList(ed.getPath(), "Extension", "Extension.value[x]") && ed.hasLabel()) {
return ed.getLabel();
}
}
}
return null;
}
private boolean canRender(Extension ext) {
return getExtensionLabel(ext) != null;
}
public void renderExtensionsInList(XhtmlNode ul, DataType element) throws FHIRFormatError, DefinitionException, IOException {
for (Extension ext : element.getExtension()) {
if (canRender(ext)) {
String lbl = getExtensionLabel(ext);
XhtmlNode li = ul.li();
li.tx(lbl);
li.tx(": ");
render(li, ext.getValue());
}
}
}
public void renderExtensionsInList(XhtmlNode ul, BackboneType element) throws FHIRFormatError, DefinitionException, IOException {
for (Extension ext : element.getModifierExtension()) {
if (canRender(ext)) {
String lbl = getExtensionLabel(ext);
XhtmlNode li = ul.li();
li = li.b();
li.tx(lbl);
li.tx(": ");
render(li, ext.getValue());
} else {
// somehow have to do better than this
XhtmlNode li = ul.li();
li.b().tx("WARNING: Unrenderable Modifier Extension!");
}
}
for (Extension ext : element.getExtension()) {
if (canRender(ext)) {
String lbl = getExtensionLabel(ext);
XhtmlNode li = ul.li();
li.tx(lbl);
li.tx(": ");
render(li, ext.getValue());
}
}
}
public void renderExtensionsInText(XhtmlNode div, DataType element, String sep) throws FHIRFormatError, DefinitionException, IOException {
boolean first = true;
for (Extension ext : element.getExtension()) {
if (canRender(ext)) {
if (first) {
first = false;
} else {
div.tx(sep);
div.tx(" ");
}
String lbl = getExtensionLabel(ext);
div.tx(lbl);
div.tx(": ");
render(div, ext.getValue());
}
}
}
public void renderExtensionsInList(XhtmlNode div, BackboneType element, String sep) throws FHIRFormatError, DefinitionException, IOException {
boolean first = true;
for (Extension ext : element.getModifierExtension()) {
if (first) {
first = false;
} else {
div.tx(sep);
div.tx(" ");
}
if (canRender(ext)) {
String lbl = getExtensionLabel(ext);
XhtmlNode b = div.b();
b.tx(lbl);
b.tx(": ");
render(div, ext.getValue());
} else {
// somehow have to do better than this
div.b().tx("WARNING: Unrenderable Modifier Extension!");
}
}
for (Extension ext : element.getExtension()) {
if (canRender(ext)) {
if (first) {
first = false;
} else {
div.tx(sep);
div.tx(" ");
}
String lbl = getExtensionLabel(ext);
div.tx(lbl);
div.tx(": ");
render(div, ext.getValue());
}
}
}
// -- 6. Data type Rendering ----------------------------------------------
public static String display(IWorkerContext context, DataType type) {
return new DataRenderer(new RenderingContext(context, null, null, "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.END_USER)).display(type);
@ -413,15 +555,8 @@ public class DataRenderer extends Renderer {
// mode - if rendering mode is technical, format defaults to XML format
// locale - otherwise, format defaults to SHORT for the Locale (which defaults to default Locale)
if (isOnlyDate(type.getPrecision())) {
DateTimeFormatter fmt = context.getDateFormat();
if (fmt == null) {
if (context.isTechnicalMode()) {
fmt = DateTimeFormatter.ISO_DATE;
} else {
fmt = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(context.getLocale());
}
}
DateTimeFormatter fmt = getDateFormatForPrecision(type);
LocalDate date = LocalDate.of(type.getYear(), type.getMonth()+1, type.getDay());
return fmt.format(date);
}
@ -442,6 +577,43 @@ public class DataRenderer extends Renderer {
return fmt.format(zdt);
}
private DateTimeFormatter getDateFormatForPrecision(BaseDateTimeType type) {
DateTimeFormatter fmt = getContextDateFormat(type);
if (fmt != null) {
return fmt;
}
if (context.isTechnicalMode()) {
switch (type.getPrecision()) {
case YEAR:
return new DateTimeFormatterBuilder().appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD).toFormatter();
case MONTH:
return new DateTimeFormatterBuilder().appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD).appendLiteral('-').appendValue(MONTH_OF_YEAR, 2).toFormatter();
default:
return DateTimeFormatter.ISO_DATE;
}
} else {
switch (type.getPrecision()) {
case YEAR:
return DateTimeFormatter.ofPattern("uuuu");
case MONTH:
return DateTimeFormatter.ofPattern("MMM uuuu");
default:
return DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(context.getLocale());
}
}
}
private DateTimeFormatter getContextDateFormat(BaseDateTimeType type) {
switch (type.getPrecision()) {
case YEAR:
return context.getDateYearFormat();
case MONTH:
return context.getDateYearMonthFormat();
default:
return context.getDateFormat();
}
}
private boolean isOnlyDate(TemporalPrecisionEnum temporalPrecisionEnum) {
return temporalPrecisionEnum == TemporalPrecisionEnum.YEAR || temporalPrecisionEnum == TemporalPrecisionEnum.MONTH || temporalPrecisionEnum == TemporalPrecisionEnum.DAY;
}
@ -533,6 +705,12 @@ public class DataRenderer extends Renderer {
}
}
public void renderDate(XhtmlNode x, Base e) {
if (e.hasPrimitiveValue()) {
x.addText(displayDateTime((DateType) e));
}
}
public void renderDateTime(XhtmlNode x, String s) {
if (s != null) {
DateTimeType dt = new DateTimeType(s);
@ -739,7 +917,7 @@ public class DataRenderer extends Renderer {
CodeSystem cs = context.getWorker().fetchCodeSystem(system, version);
if (cs != null && cs.hasUserData("path")) {
if (!Utilities.noString(code)) {
return cs.getUserString("path")+"#"+Utilities.nmtokenize(code);
return cs.getUserString("path")+"#"+cs.getId()+"-"+Utilities.nmtokenize(code);
} else {
return cs.getUserString("path");
}
@ -755,8 +933,9 @@ public class DataRenderer extends Renderer {
if (Utilities.noString(s))
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
CodeSystem cs = context.getWorker().fetchCodeSystem(c.getSystem());
String sn = describeSystem(c.getSystem());
String sn = cs != null ? cs.present() : describeSystem(c.getSystem());
String link = getLinkForCode(c.getSystem(), c.getVersion(), c.getCode());
if (link != null) {
x.ah(link).tx(sn);
@ -821,11 +1000,11 @@ public class DataRenderer extends Renderer {
return s;
}
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc) {
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc) throws FHIRFormatError, DefinitionException, IOException {
renderCodeableConcept(x, cc, false);
}
protected void renderCodeableReference(XhtmlNode x, CodeableReference e, boolean showCodeDetails) {
protected void renderCodeableReference(XhtmlNode x, CodeableReference e, boolean showCodeDetails) throws FHIRFormatError, DefinitionException, IOException {
if (e.hasConcept()) {
renderCodeableConcept(x, e.getConcept(), showCodeDetails);
}
@ -834,7 +1013,7 @@ public class DataRenderer extends Renderer {
}
}
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc, boolean showCodeDetails) {
protected void renderCodeableConcept(XhtmlNode x, CodeableConcept cc, boolean showCodeDetails) throws FHIRFormatError, DefinitionException, IOException {
if (cc.isEmpty()) {
return;
}
@ -890,6 +1069,12 @@ public class DataRenderer extends Renderer {
sp.tx(" \""+c.getDisplay()+"\"");
}
}
if (hasRenderableExtensions(cc)) {
if (!first) {
sp.tx("; ");
}
renderExtensionsInText(sp, cc, ";");
}
sp.tx(")");
} else {
@ -1139,9 +1324,11 @@ public class DataRenderer extends Renderer {
protected String displayQuantity(Quantity q) {
StringBuilder s = new StringBuilder();
s.append("(system = '").append(TerminologyRenderer.describeSystem(q.getSystem()))
.append("' code ").append(q.getCode())
.append(" = '").append(lookupCode(q.getSystem(), null, q.getCode())).append("')");
s.append(q.hasValue() ? q.getValue() : "?");
if (q.hasUnit())
s.append(" ").append(q.getUnit());
else if (q.hasCode())
s.append(" ").append(q.getCode());
return s.toString();
}
@ -1158,26 +1345,33 @@ public class DataRenderer extends Renderer {
}
if (q.hasUnit())
x.tx(" "+q.getUnit());
else if (q.hasCode())
else if (q.hasCode() && q.hasSystem()) {
// if there's a code there *shall* be a system, so if we've got one and not the other, things are invalid and we won't bother trying to render
if (q.hasSystem() && q.getSystem().equals("http://unitsofmeasure.org"))
x.tx(" "+q.getCode());
else
x.tx("(unit "+q.getCode()+" from "+q.getSystem()+")");
}
if (showCodeDetails && q.hasCode()) {
x.span("background: LightGoldenRodYellow", null).tx(" (Details: "+TerminologyRenderer.describeSystem(q.getSystem())+" code "+q.getCode()+" = '"+lookupCode(q.getSystem(), null, q.getCode())+"')");
}
}
public String displayRange(Range q) {
if (!q.hasLow() && !q.hasHigh())
return "?";
StringBuilder b = new StringBuilder();
if (q.hasLow())
b.append(q.getLow().getValue().toString());
else
b.append("?");
b.append("-");
if (q.hasHigh())
b.append(q.getHigh().getValue().toString());
else
b.append("?");
if (q.getLow().hasUnit())
b.append(" "+q.getLow().getUnit());
boolean sameUnits = (q.getLow().hasUnit() && q.getHigh().hasUnit() && q.getLow().getUnit().equals(q.getHigh().getUnit()))
|| (q.getLow().hasCode() && q.getHigh().hasCode() && q.getLow().getCode().equals(q.getHigh().getCode()));
String low = "?";
if (q.hasLow() && q.getLow().hasValue())
low = sameUnits ? q.getLow().getValue().toString() : displayQuantity(q.getLow());
String high = displayQuantity(q.getHigh());
if (high.isEmpty())
high = "?";
b.append(low).append("\u00A0to\u00A0").append(high);
return b.toString();
}

View File

@ -106,7 +106,10 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
if (context.isAddGeneratedNarrativeHeader()) {
x.para().b().tx("Generated Narrative: "+r.fhirType());
}
if (context.isTechnicalMode()) {
if (!Utilities.noString(r.getId())) {
x.an(r.getId());
}
if (context.isTechnicalMode() && !context.isContained()) {
renderResourceHeader(r, x);
}
try {
@ -312,9 +315,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
x.addText(new Base64().encodeAsString(((Base64BinaryType) e).getValue()));
else if (e instanceof org.hl7.fhir.r4b.model.DateType) {
org.hl7.fhir.r4b.model.DateType dt = ((org.hl7.fhir.r4b.model.DateType) e);
if (((org.hl7.fhir.r4b.model.DateType) e).hasValue()) {
x.addText(((org.hl7.fhir.r4b.model.DateType) e).toHumanDisplay());
}
renderDate(x, dt);
} else if (e instanceof Enumeration) {
Object ev = ((Enumeration<?>) e).getValue();
x.addText(ev == null ? "" : ev.toString()); // todo: look up a display name if there is one
@ -397,9 +398,17 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
if (rw == null) {
renderReference(res, x, r);
} else {
String ref = context.getResolver().urlForContained(context, res.fhirType(), res.getId(), rw.fhirType(), rw.getId());
if (ref == null) {
x.an(rw.getId());
ResourceRenderer rr = RendererFactory.factory(rw, context.copy().setAddGeneratedNarrativeHeader(false));
RenderingContext ctxtc = context.copy();
ctxtc.setAddGeneratedNarrativeHeader(false);
ctxtc.setContained(true);
ResourceRenderer rr = RendererFactory.factory(rw, ctxtc);
rr.render(parent.blockquote(), rw);
} else {
x.ah(ref).tx("See "+rw.fhirType());
}
}
}
} else {
@ -649,7 +658,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
private boolean generateByProfile(StructureDefinition profile, boolean showCodeDetails) {
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
if(context.isAddGeneratedNarrativeHeader()) {
x.para().b().tx("Generated Narrative"+(showCodeDetails ? " with Details" : ""));
x.para().b().tx("Generated Narrative: "+profile.present()+(showCodeDetails ? " with Details" : ""));
}
try {
generateByProfile(rcontext.getResourceResource(), profile, rcontext.getResourceResource(), profile.getSnapshot().getElement(), profile.getSnapshot().getElement().get(0), getChildrenForPath(profile.getSnapshot().getElement(), rcontext.getResourceResource().getResourceType().toString()), x, rcontext.getResourceResource().getResourceType().toString(), showCodeDetails);
@ -689,10 +698,13 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
boolean showCodeDetails, int indent, PropertyWrapper p, ElementDefinition child) throws UnsupportedEncodingException, IOException, EOperationOutcome {
Map<String, String> displayHints = readDisplayHints(child);
if ("DomainResource.contained".equals(child.getBase().getPath())) {
// if (p.getValues().size() > 0 && child != null) {
// for (BaseWrapper v : p.getValues()) {
// x.an(v.get("id").primitiveValue());
// }
// x.hr();
// RenderingContext ctxt = context.clone();
// ctxt.setContained(true);
// ResourceRenderer rnd = RendererFactory.factory(v.fhirType(), ctxt);
// ResourceWrapper rw = new ElementWrappers.ResourceWrapperMetaElement(ctxt, (org.hl7.fhir.r5.elementmodel.Element) v.getBase());
// rnd.render(x.blockquote(), rw);
// }
} else if (!exemptFromRendering(child)) {
if (isExtension(p)) {

View File

@ -53,7 +53,10 @@ public class Renderer {
protected static final String RENDER_BUNDLE_IF_MOD = "RENDER_BUNDLE_IF_MOD";
protected static final String RENDER_BUNDLE_IF_MATCH = "RENDER_BUNDLE_IF_MATCH";
protected static final String RENDER_BUNDLE_IF_NONE = "RENDER_BUNDLE_IF_NONE";
protected static final String RENDER_BUNDLE_DOCUMENT_CONTENT = "RENDER_BUNDLE_DOCUMENT_CONTENT";
protected static final String RENDER_BUNDLE_HEADER_DOC_ENTRY_URD = "RENDER_BUNDLE_HEADER_DOC_ENTRY_URD";
protected static final String RENDER_BUNDLE_HEADER_DOC_ENTRY_U = "RENDER_BUNDLE_HEADER_DOC_ENTRY_U";
protected static final String RENDER_BUNDLE_HEADER_DOC_ENTRY_RD = "RENDER_BUNDLE_HEADER_DOC_ENTRY_RD";
/** the plan here is to make this have it's own implementation of messages, rather than using the
* validator messages, for better alignment with publisher I18n strategy

View File

@ -114,6 +114,9 @@ public class RendererFactory {
if ("Library".equals(resource.getName())) {
return new LibraryRenderer(context);
}
if ("Patient".equals(resource.getName())) {
return new PatientRenderer(context);
}
if ("DiagnosticReport".equals(resource.getName())) {
return new DiagnosticReportRenderer(context);
}

View File

@ -158,9 +158,8 @@ public abstract class ResourceRenderer extends DataRenderer {
if (target.hasUserData("path")) {
x.ah(target.getUserString("path")).tx(cr.present());
} else {
url = url.substring(0, url.indexOf("|"));
x.code().tx(url);
x.tx(": "+cr.present());
x.tx(" ("+cr.present()+")");
}
}
}
@ -414,6 +413,8 @@ public abstract class ResourceRenderer extends DataRenderer {
if (id != null || lang != null || versionId != null || lastUpdated != null) {
XhtmlNode p = plateStyle(div.para());
p.tx("Resource ");
p.tx(r.fhirType());
p.tx(" ");
if (id != null) {
p.tx("\""+id+"\" ");
}
@ -489,4 +490,16 @@ public abstract class ResourceRenderer extends DataRenderer {
private String getPrimitiveValue(ResourceWrapper r, String name) throws UnsupportedEncodingException, FHIRException, IOException {
return r.has(name) && r.getChildByName(name).hasValues() ? r.getChildByName(name).getValues().get(0).getBase().primitiveValue() : null;
}
public void renderOrError(DomainResource dr) {
try {
render(dr);
} catch (Exception e) {
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
x.para().tx("Error rendering: "+e.getMessage());
dr.setText(null);
inject(dr, x, NarrativeStatus.GENERATED);
}
}
}

View File

@ -105,6 +105,7 @@ public class RenderingContext {
private boolean canonicalUrlsAsLinks;
private boolean pretty;
private boolean header;
private boolean contained;
private ValidationOptions terminologyServiceOptions = new ValidationOptions();
private boolean noSlowLookup;
@ -127,6 +128,8 @@ public class RenderingContext {
private ZoneId timeZoneId;
private DateTimeFormatter dateTimeFormat;
private DateTimeFormatter dateFormat;
private DateTimeFormatter dateYearFormat;
private DateTimeFormatter dateYearMonthFormat;
/**
*
@ -151,6 +154,46 @@ public class RenderingContext {
this.locale = new Locale.Builder().setLanguageTag("en-US").build();
profileUtilities = new ProfileUtilities(worker, null, null);
}
public RenderingContext copy() {
RenderingContext res = new RenderingContext(worker, markdown, terminologyServiceOptions, specificationLink, localPrefix, lang, mode);
res.resolver = resolver;
res.templateProvider = templateProvider;
res.services = services;
res.parser = parser;
res.headerLevelContext = headerLevelContext;
res.canonicalUrlsAsLinks = canonicalUrlsAsLinks;
res.pretty = pretty;
res.contained = contained;
res.noSlowLookup = noSlowLookup;
res.tooCostlyNoteEmpty = tooCostlyNoteEmpty;
res.tooCostlyNoteNotEmpty = tooCostlyNoteNotEmpty;
res.tooCostlyNoteEmptyDependent = tooCostlyNoteEmptyDependent;
res.tooCostlyNoteNotEmptyDependent = tooCostlyNoteNotEmptyDependent;
res.codeSystemPropList.addAll(codeSystemPropList);
res.profileUtilities = profileUtilities;
res.definitionsTarget = definitionsTarget;
res.destDir = destDir;
res.addGeneratedNarrativeHeader = addGeneratedNarrativeHeader;
res.questionnaireMode = questionnaireMode;
res.header = header;
res.selfLink = selfLink;
res.inlineGraphics = inlineGraphics;
res.timeZoneId = timeZoneId;
res.dateTimeFormat = dateTimeFormat;
res.dateFormat = dateFormat;
res.dateYearFormat = dateYearFormat;
res.dateYearMonthFormat = dateYearMonthFormat;
res.targetVersion = targetVersion;
res.locale = locale;
res.terminologyServiceOptions = terminologyServiceOptions.copy();
return res;
}
public IWorkerContext getContext() {
return worker;
@ -336,32 +379,6 @@ public class RenderingContext {
return this;
}
public RenderingContext copy() {
RenderingContext res = new RenderingContext(worker, markdown, terminologyServiceOptions, specificationLink, localPrefix, lang, mode);
res.resolver = resolver;
res.templateProvider = templateProvider;
res.services = services;
res.parser = parser;
res.headerLevelContext = headerLevelContext;
res.canonicalUrlsAsLinks = canonicalUrlsAsLinks;
res.pretty = pretty;
res.noSlowLookup = noSlowLookup;
res.tooCostlyNoteEmpty = tooCostlyNoteEmpty;
res.tooCostlyNoteNotEmpty = tooCostlyNoteNotEmpty;
res.tooCostlyNoteEmptyDependent = tooCostlyNoteEmptyDependent;
res.tooCostlyNoteNotEmptyDependent = tooCostlyNoteNotEmptyDependent;
res.codeSystemPropList.addAll(codeSystemPropList);
res.profileUtilities = profileUtilities;
res.definitionsTarget = definitionsTarget;
res.destDir = destDir;
res.addGeneratedNarrativeHeader = addGeneratedNarrativeHeader;
return res;
}
public boolean isInlineGraphics() {
return inlineGraphics;
@ -514,6 +531,30 @@ public class RenderingContext {
this.dateFormat = DateTimeFormatter.ofPattern(dateFormat);
}
public DateTimeFormatter getDateYearFormat() {
return dateYearFormat;
}
public void setDateYearFormat(DateTimeFormatter dateYearFormat) {
this.dateYearFormat = dateYearFormat;
}
public void setDateYearFormatString(String dateYearFormat) {
this.dateYearFormat = DateTimeFormatter.ofPattern(dateYearFormat);
}
public DateTimeFormatter getDateYearMonthFormat() {
return dateYearMonthFormat;
}
public void setDateYearMonthFormat(DateTimeFormatter dateYearMonthFormat) {
this.dateYearMonthFormat = dateYearMonthFormat;
}
public void setDateYearMonthFormatString(String dateYearMonthFormat) {
this.dateYearMonthFormat = DateTimeFormatter.ofPattern(dateYearMonthFormat);
}
public ResourceRendererMode getMode() {
return mode;
}
@ -522,5 +563,13 @@ public class RenderingContext {
this.mode = mode;
}
public boolean isContained() {
return contained;
}
public void setContained(boolean contained) {
this.contained = contained;
}
}

View File

@ -18,6 +18,9 @@ public class Resolver {
public interface IReferenceResolver {
ResourceWithReference resolve(RenderingContext context, String url);
// returns null if contained resource is inlined
String urlForContained(RenderingContext context, String containingType, String containingId, String containedType, String containedId);
}
public static class ResourceContext {

View File

@ -699,7 +699,6 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
boolean showCodeDetails, int indent, PropertyWrapper p, ElementDefinition child) throws UnsupportedEncodingException, IOException, EOperationOutcome {
Map<String, String> displayHints = readDisplayHints(child);
if ("DomainResource.contained".equals(child.getBase().getPath())) {
System.out.print("-");
// for (BaseWrapper v : p.getValues()) {
// x.hr();
// RenderingContext ctxt = context.clone();