All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hl7.fhir.r5.renderers.DataRenderer Maven / Gradle / Ivy

package org.hl7.fhir.r5.renderers; 

import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.time.format.SignStyle;
import java.util.Currency;
import java.util.List;

import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.BackboneType;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.BaseDateTimeType;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.NamingSystem;
import org.hl7.fhir.r5.model.PrimitiveType;
import org.hl7.fhir.r5.model.Quantity;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceDesignationComponent;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
import org.hl7.fhir.r5.terminologies.JurisdictionUtilities;
import org.hl7.fhir.r5.terminologies.utilities.SnomedUtilities;
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.UserDataNames;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.utilities.xhtml.XhtmlParser;

import ca.uhn.fhir.model.api.TemporalPrecisionEnum; 

@MarkedToMoveToAdjunctPackage
public class DataRenderer extends Renderer implements CodeResolver { 

  // -- 1. context -------------------------------------------------------------- 

  public DataRenderer(RenderingContext context) { 
    super(context); 
  } 

  public DataRenderer(IWorkerContext worker) { 
    super(worker); 
  } 

  // -- 2. Markdown support ------------------------------------------------------- 

  public static String processRelativeUrls(String markdown, String path) { 
    if (markdown == null) { 
      return ""; 
    } 
    if (!Utilities.isAbsoluteUrl(path)) { 
      return markdown; 
    } 
    String basePath = path.contains("/") ? path.substring(0, path.lastIndexOf("/")+1) : path+"/"; 
    StringBuilder b = new StringBuilder(); 
    int i = 0; 
    while (i < markdown.length()) { 
      if (i < markdown.length()-3 && markdown.substring(i, i+2).equals("](")) { 
        int j = i + 2; 
        while (j < markdown.length() && markdown.charAt(j) != ')') 
          j++; 
        if (j < markdown.length()) { 
          String url = markdown.substring(i+2, j); 
          if (!Utilities.isAbsoluteUrl(url) && !url.startsWith("..")) { 
            // it's relative - so it's relative to the base URL 
            b.append("]("); 
            b.append(basePath); 
          } else { 
            b.append("]("); 
          } 
          i = i + 1; 
        } else  
          b.append(markdown.charAt(i)); 
      } else { 
        b.append(markdown.charAt(i)); 
      } 
      i++; 
    } 
    return b.toString(); 
  } 

  protected void addMarkdown(XhtmlNode x, String text, String path) throws FHIRFormatError, IOException, DefinitionException { 
    addMarkdown(x, processRelativeUrls(text, path)); 
  } 

  protected void addMarkdown(XhtmlNode x, String text) throws FHIRFormatError, IOException, DefinitionException { 
    if (text != null) { 
      // 1. custom FHIR extensions 
      while (text.contains("[[[")) { 
        String left = text.substring(0, text.indexOf("[[[")); 
        String link = text.substring(text.indexOf("[[[")+3, text.indexOf("]]]")); 
        String right = text.substring(text.indexOf("]]]")+3); 
        String path = null; 
        String url = link; 
        String[] parts = link.split("\\#"); 
        if (parts[0].contains(".")) { 
          path = parts[0]; 
          parts[0] = parts[0].substring(0, parts[0].indexOf(".")); 
        } 
        StructureDefinition p = getContext().getWorker().fetchResource(StructureDefinition.class, parts[0]); 
        if (p == null) { 
          p = getContext().getWorker().fetchTypeDefinition(parts[0]); 
        } 
        if (context.getTypeMap().containsKey(parts[0])) { 
          p = getContext().getWorker().fetchTypeDefinition(context.getTypeMap().get(parts[0]));           
        } 
        if (p == null) { 
          p = getContext().getWorker().fetchResource(StructureDefinition.class, link); 
        } 
        if (p != null) { 
          if ("Extension".equals(p.getType())) { 
            path = null; 
          } else if (p.hasSnapshot()) { 
            path = p.getSnapshot().getElementFirstRep().getPath(); 
          } else if (Utilities.isAbsoluteUrl(path)) { 
            path = null; 
          } 
          url = p.getWebPath(); 
          if (url == null) { 
            url = p.getUserString(UserDataNames.render_filename); 
          } 
        } else { 
          throw new DefinitionException(context.formatPhrase(RenderingContext.DATA_REND_MKDWN_LNK, link) + " "); 
        } 

        text = left+"["+link+"]("+url+(path == null ? "" : "#"+path)+")"+right; 
      } 

      // 2. markdown 
      String s = getContext().getMarkdown().process(text, "narrative generator"); 
      XhtmlParser p = new XhtmlParser(); 
      XhtmlNode m; 
      try { 
        m = p.parse("
"+s+"
", "div"); } catch (org.hl7.fhir.exceptions.FHIRFormatError e) { throw new FHIRFormatError(e.getMessage(), e); } x.addChildNodes(m.getChildNodes()); } } protected void smartAddText(XhtmlNode p, String text) { if (text == null) return; String[] lines = text.split("\\r\\n"); for (int i = 0; i < lines.length; i++) { if (i > 0) p.br(); p.addText(lines[i]); } } // -- 3. General Purpose Terminology Support ----------------------------------------- private static String snMonth(String m) { switch (m) { case "1" : return "Jan"; case "2" : return "Feb"; case "3" : return "Mar"; case "4" : return "Apr"; case "5" : return "May"; case "6" : return "Jun"; case "7" : return "Jul"; case "8" : return "Aug"; case "9" : return "Sep"; case "10" : return "Oct"; case "11" : return "Nov"; case "12" : return "Dec"; default: return null; } } public static String describeVersion(String version) { if (version.startsWith("http://snomed.info/sct")) { String[] p = version.split("\\/"); String ed = null; String dt = ""; if (p[p.length-2].equals("version")) { ed = p[p.length-3]; String y = p[p.length-3].substring(4, 8); String m = p[p.length-3].substring(2, 4); dt = " rel. "+snMonth(m)+" "+y; } else { ed = p[p.length-1]; } switch (ed) { case "900000000000207008": return "Intl"+dt; case "731000124108": return "US"+dt; case "32506021000036107": return "AU"+dt; case "449081005": return "ES/Intl"+dt; case "554471000005108": return "DK"+dt; case "11000146104": return "NL"+dt; case "45991000052106": return "SE"+dt; case "83821000000107": return "UK"+dt; case "11000172109": return "BE"+dt; case "11000221109" : return "AR"+dt; case "11000234105" : return "AT"+dt; case "20621000087109" : return "CA-EN"+dt; case "20611000087101" : return "CA-FR"+dt; case "11000181102 " : return "EE"+dt; case "11000229106" : return "FI"+dt; case "11000274103" : return "DE"+dt; case "1121000189102" : return "IN"+dt; case "11000220105" : return "IE"+dt; case "21000210109" : return "NZ"+dt; case "51000202101 " : return "NO"+dt; case "11000267109" : return "KR"+dt; case "900000001000122104" : return "ES-ES"+dt; case "2011000195101" : return "CH"+dt; case "999000021000000109" : return "UK+Clinical"+dt; case "5631000179106" : return "UY"+dt; case "5991000124107" : return "US+ICD10CM"+dt; default: return "??"+dt; } } else { return version; } } public String displaySystem(String system) { if (system == null) return (context.formatPhrase(RenderingContext.DATA_REND_NOT_STAT)); if (system.equals("http://loinc.org")) return (context.formatPhrase(RenderingContext.DATA_REND_LOINC)); if (system.startsWith("http://snomed.info")) return (context.formatPhrase(RenderingContext.DATA_REND_SNOMED)); if (system.equals("http://www.nlm.nih.gov/research/umls/rxnorm")) return (context.formatPhrase(RenderingContext.DATA_REND_RXNORM)); if (system.equals("http://hl7.org/fhir/sid/icd-9")) return (context.formatPhrase(RenderingContext.DATA_REND_ICD)); if (system.equals("http://dicom.nema.org/resources/ontology/DCM")) return (context.formatPhrase(RenderingContext.DATA_REND_DICOM)); if (system.equals("http://unitsofmeasure.org")) return (context.formatPhrase(RenderingContext.GENERAL_UCUM)); if (system.equals("http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl")) return (context.formatPhrase(RenderingContext.GENERAL_NCI_THES)); CodeSystem cs = context.getContext().fetchCodeSystem(system); if (cs != null) { return crPresent(cs); } return tails(system); } private String crPresent(CanonicalResource cr) { if (cr.hasUserData(UserDataNames.render_presentation)) { return cr.getUserString(UserDataNames.render_presentation); } if (cr.hasTitle()) return context.getTranslated(cr.getTitleElement()); if (cr.hasName()) return context.getTranslated(cr.getNameElement()); return cr.toString(); } private String tails(String system) { if (system.contains("/")) { return system.substring(system.lastIndexOf("/")+1); } else { return (context.formatPhrase(RenderingContext.DATA_REND_UNKNWN)); } } protected String makeAnchor(String codeSystem, String code) { String s = codeSystem+'-'+code; StringBuilder b = new StringBuilder(); for (char c : s.toCharArray()) { if (Utilities.isValidHtmlAnchorChar(c)) { b.append(c); } else { b.append("|"+Integer.toHexString(c)); // not % to save double coding confusing users } } return b.toString(); } public String lookupCode(String system, String version, String code) { if (JurisdictionUtilities.isJurisdiction(system)) { return JurisdictionUtilities.displayJurisdiction(system+"#"+code); } ValidationResult t = getContext().getWorker().validateCode(getContext().getTerminologyServiceOptions().withLanguage(context.getLocale().toLanguageTag()).withVersionFlexible(true), system, version, code, null); if (t != null && t.getDisplay() != null) return t.getDisplay(); else return code; } protected String describeLang(String lang) { // special cases: if ("fr-CA".equals(lang)) { return "French (Canadian)"; // this one was omitted from the value set } ValueSet v = getContext().getWorker().findTxResource(ValueSet.class, "http://hl7.org/fhir/ValueSet/languages"); if (v != null) { ConceptReferenceComponent l = null; for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) { if (cc.getCode().equals(lang)) l = cc; } if (l == null) { if (lang.contains("-")) { lang = lang.substring(0, lang.indexOf("-")); } for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) { if (cc.getCode().equals(lang)) { l = cc; break; } } if (l == null) { for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) { if (cc.getCode().startsWith(lang+"-")) { l = cc; break; } } } } if (l != null) { if (lang.contains("-")) lang = lang.substring(0, lang.indexOf("-")); String en = l.getDisplay(); String nativelang = null; for (ConceptReferenceDesignationComponent cd : l.getDesignation()) { if (cd.getLanguage().equals(lang)) nativelang = cd.getValue(); } if (nativelang == null) return en+" ("+lang+")"; else return nativelang+" ("+en+", "+lang+")"; } } return lang; } private boolean isCanonical(String path) { if (!path.endsWith(".url")) return false; String t = path.substring(0, path.length()-4); StructureDefinition sd = getContext().getWorker().fetchTypeDefinition(t); if (sd == null) return false; if (VersionUtilities.getCanonicalResourceNames(getContext().getWorker().getVersion()).contains(t)) { return true; } if (Utilities.existsInList(t, "ActivityDefinition", "CapabilityStatement", "ChargeItemDefinition", "Citation", "CodeSystem", "CompartmentDefinition", "ConceptMap", "ConditionDefinition", "EventDefinition", "Evidence", "EvidenceReport", "EvidenceVariable", "ExampleScenario", "GraphDefinition", "ImplementationGuide", "Library", "Measure", "MessageDefinition", "NamingSystem", "PlanDefinition" )) return true; return false; } // -- 4. Language support ------------------------------------------------------ public String gt(@SuppressWarnings("rawtypes") PrimitiveType value) { return context.getTranslated(value); } public String gt(ResourceWrapper value) { return context.getTranslated(value); } // -- 6. General purpose extension rendering ---------------------------------------------- public boolean hasRenderableExtensions(DataType element) { for (Extension ext : element.getExtension()) { if (canRender(ext)) { return true; } } return false; } public boolean hasRenderableExtensions(BackboneType element) { for (Extension ext : element.getExtension()) { if (canRender(ext)) { return true; } } return element.hasModifierExtension(); } public boolean hasRenderableExtensions(ResourceWrapper element) { for (ResourceWrapper ext : element.extensions()) { if (canRender(ext)) { return true; } } return false; } private String getExtensionLabel(Extension ext) { StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.getUrl()); if (sd != null && ext.hasValue() && ext.getValue().isPrimitive() && sd.hasSnapshot()) { for (ElementDefinition ed : sd.getSnapshot().getElement()) { if (Utilities.existsInList(ed.getPath(), "Extension", "Extension.value[x]") && ed.hasLabel()) { return context.getTranslated(ed.getLabelElement()); } } } return null; } private String getExtensionLabel(ResourceWrapper ext) { StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.primitiveValue("url")); if (sd != null && ext.has("value") && ext.child("value").isPrimitive() && sd.hasSnapshot()) { for (ElementDefinition ed : sd.getSnapshot().getElement()) { if (Utilities.existsInList(ed.getPath(), "Extension", "Extension.value[x]") && ed.hasLabel()) { return context.getTranslated(ed.getLabelElement()); } } } return null; } private boolean canRender(Extension ext) { return getExtensionLabel(ext) != null; } private boolean canRender(ResourceWrapper ext) { StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, ext.primitiveValue("url")); if (sd != null && ext.has("value") && ext.isPrimitive("value") && sd.hasSnapshot()) { for (ElementDefinition ed : sd.getSnapshot().getElement()) { if (Utilities.existsInList(ed.getPath(), "Extension", "Extension.value[x]") && ed.hasLabel()) { return true; } } } return false; } public void renderExtensionsInList(RenderingStatus status, XhtmlNode ul, ResourceWrapper element) throws FHIRFormatError, DefinitionException, IOException { for (ResourceWrapper ext : element.extensions()) { if (canRender(ext)) { String lbl = getExtensionLabel(ext); XhtmlNode li = ul.li(); li.tx(lbl); li.tx(": "); renderDataType(status, li, ext.child("value")); } } } // public void renderExtensionsInList(XhtmlNode ul, BackboneType element) throws FHIRFormatError, DefinitionException, IOException { // for (Extension ext : element.getModifierExtension()) { // if (canRender(ext)) { // String lbl = getExtensionLabel(ext); // XhtmlNode li = ul.li(); // li = li.b(); // li.tx(lbl); // li.tx(": "); // render(li, ext.getValue()); // } else { // // somehow have to do better than this // XhtmlNode li = ul.li(); // li.b().tx(context.formatPhrase(RenderingContext.DATA_REND_UNRD_EX)); // } // } // for (Extension ext : element.getExtension()) { // if (canRender(ext)) { // String lbl = getExtensionLabel(ext); // XhtmlNode li = ul.li(); // li.tx(lbl); // li.tx(": "); // render(li, ext.getValue()); // } // } // } // public void renderExtensionsInText(RenderingStatus status, XhtmlNode x, ResourceWrapper element, String sep) throws FHIRFormatError, DefinitionException, IOException { boolean first = true; for (ResourceWrapper ext : element.extensions()) { if (canRender(ext)) { status.setExtensions(true); if (first) { first = false; } else { x.tx(sep); x.tx(" "); } String lbl = getExtensionLabel(ext); x.tx(lbl); x.tx(": "); 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 { // boolean first = true; // for (Extension ext : element.getModifierExtension()) { // if (first) { // first = false; // } else { // div.tx(sep); // div.tx(" "); // } // if (canRender(ext)) { // String lbl = getExtensionLabel(ext); // XhtmlNode b = div.b(); // b.tx(lbl); // b.tx(": "); // render(div, ext.getValue()); // } else { // // somehow have to do better than this // div.b().tx(context.formatPhrase(RenderingContext.DATA_REND_UNRD_EX)); // } // } // for (Extension ext : element.getExtension()) { // if (canRender(ext)) { // if (first) { // first = false; // } else { // div.tx(sep); // div.tx(" "); // } // // String lbl = getExtensionLabel(ext); // div.tx(lbl); // div.tx(": "); // render(div, ext.getValue()); // } // } // // } // -- 6. Data type Rendering ---------------------------------------------- public static String display(IWorkerContext context, DataType type) { return new DataRenderer(new RenderingContext(context, null, null, "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.END_USER, GenerationRules.VALID_RESOURCE)).displayDataType(type); } public String displayBase(Base b) { if (b instanceof DataType) { return displayDataType((DataType) b); } else { return (context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, b.fhirType()) + " "); } } public String displayDataType(DataType type) { if (type == null) { return ""; } return displayDataType(wrapNC(type)); } public String displayDataType(ResourceWrapper type) { if (type == null || type.isEmpty()) { return ""; } switch (type.fhirType()) { case "Coding": return displayCoding(type); case "CodeableConcept": return displayCodeableConcept(type); case "CodeableReference": return displayCodeableReference(type); case "Identifier": return displayIdentifier(type); case "HumanName": return displayHumanName(type); case "Address": return displayAddress(type); case "ContactPoint": return displayContactPoint(type); case "Quantity": return displayQuantity(type); case "Range": return displayRange(type); case "Period": return displayPeriod(type); case "Timing": return displayTiming(type); case "SampledData": return displaySampledData(type); case "ContactDetail": return displayContactDetail(type); case "Annotation": return displayAnnotation(type); case "Ratio": return displayRatio(type); case "Reference" : return displayReference(type); case "Money" : return displayMoney(type); case "dateTime": case "date" : case "instant" : return displayDateTime(type); default: if (type.isPrimitive()) { return context.getTranslated(type); } else if (Utilities.existsInList(type.fhirType(), "Meta", "Dosage", "Signature", "UsageContext", "RelatedArtifact", "ElementDefinition", "Base64BinaryType", "Attachment")) { return ""; } else if ("Extension".equals(type.fhirType())) { return displayDataType(type.child("value")); } else { return (context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, type.fhirType()) + " "); } } } private String displayMoney(ResourceWrapper type) { String currency = type.primitiveValue("currency"); String value = type.primitiveValue("value"); return context.formatPhrase(RenderingContext.DATA_REND_CURRENCY, currency, value); } private String displayAnnotation(ResourceWrapper type) { return type.primitiveValue("text"); } private String displayCodeableReference(ResourceWrapper type) { if (type.has("reference")) { return displayReference(type.child("reference")); } else { return displayCodeableConcept(type.child("concept")); } } protected String displayReference(ResourceWrapper type) { if (type.has("display")) { return type.primitiveValue("display"); } else if (type.has("reference")) { // ResourceWithReference tr = resolveReference(res, r.getReference()); // x.addText(tr == null ? r.getReference() : "?ngen-3"); // getDisplayForReference(tr.getReference())); return "?ngen-3"; } else { return "?ngen-4?"; } } private String displayRatio(ResourceWrapper type) { return displayQuantity(type.child("numerator"))+" / "+displayQuantity(type.child("denominator")); } protected String displayDateTime(ResourceWrapper type) { if (!type.hasPrimitiveValue()) { return ""; } BaseDateTimeType t = new DateTimeType(type.primitiveValue()); // relevant inputs in rendering context: // timeZone, dateTimeFormat, locale, mode // timezone - application specified timezone to use. // null = default to the time of the date/time itself // dateTimeFormat - application specified format for date times // null = default to ... depends on mode // mode - if rendering mode is technical, format defaults to XML format // locale - otherwise, format defaults to SHORT for the Locale (which defaults to default Locale) if (isOnlyDate(t.getPrecision())) { DateTimeFormatter fmt = getDateFormatForPrecision(t); LocalDate date = LocalDate.of(t.getYear(), t.getMonth()+1, t.getDay()); return fmt.format(date); } DateTimeFormatter fmt = context.getDateTimeFormat(); if (fmt == null) { if (context.isTechnicalMode()) { fmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME; } else { fmt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(context.getLocale()); } } ZonedDateTime zdt = ZonedDateTime.parse(t.primitiveValue()); ZoneId zone = context.getTimeZoneId(); if (zone != null) { zdt = zdt.withZoneSameInstant(zone); } return fmt.format(zdt); } private DateTimeFormatter getDateFormatForPrecision(BaseDateTimeType type) { DateTimeFormatter fmt = getContextDateFormat(type); if (fmt != null) { 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; } // public void renderDataType(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { //// Base base = null; //// try { //// base = type.getBase(); //// } catch (FHIRException | IOException e) { //// x.tx(context.formatPhrase(RenderingContext.DATA_REND_ERROR, e.getMessage()) + " "); // this shouldn't happen - it's an error in the library itself //// return; //// } //// if (base instanceof DataType) { //// render(x, (DataType) base); //// } else { //// x.tx(context.formatPhrase(RenderingContext.DATA_REND_TO_DO, base.fhirType())); //// } // } public void renderBase(RenderingStatus status, XhtmlNode x, Base b) throws FHIRFormatError, DefinitionException, IOException { if (b instanceof DataType) { renderDataType(status, x, wrapNC((DataType) b)); } else { x.tx(context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, b.fhirType()) + " "); } } public boolean canRenderDataType(String type) { 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"); } public boolean renderDataType(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { return renderDataType(status, null, x, type); } public boolean renderDataType(RenderingStatus status, XhtmlNode parent, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { if (type == null) { return false; } switch (type.fhirType()) { case "dateTime": case "date" : case "instant" : renderDateTime(status, x, type); break; case "uri" : case "url" : renderUri(status, x, type); break; case "canonical" : renderCanonical(status, x, type); break; case "Annotation": renderAnnotation(status, x, type); break; case "Coding": renderCodingWithDetails(status, x, type); break; case "CodeableConcept": renderCodeableConcept(status, x, type); break; case "Identifier": renderIdentifier(status, x, type); break; case "HumanName": renderHumanName(status, x, type); break; case "Address": renderAddress(status, x, type); break; case "Expression": renderExpression(status, x, type); break; case "Money": renderMoney(status, x, type); break; case "ContactPoint": renderContactPoint(status, x, type); break; case "Quantity": case "Age": renderQuantity(status, x, type); break; case "Range": renderRange(status, x, type); break; case "Period": renderPeriod(status, x, type); break; case "Timing": renderTiming(status, x, type); break; case "SampledData": renderSampledData(status, x, type); break; case "Reference": renderReference(status, x, type); break; case "UsageContext": renderUsageContext(status, x, type); break; case "ContactDetail": renderContactDetail(status, x, type); break; case "Ratio": renderRatio(status, x, type); break; case "Attachment": renderAttachment(status, x, type); break; case "CodeableReference": if (type.has("concept")) { renderCodeableConcept(status, x, type.child("concept")); } else { renderReference(status, x, type.child("reference")); } break; case "code": x.tx(getTranslatedCode(type)); break; case "markdown": addMarkdown(parent == null ? x : parent, context.getTranslated(type)); // note parent not focus, because of paragraph issues and markdown break; case "base64Binary": int length = type.primitiveValue().length(); if (length >= context.getBase64Limit()) { x.tx(context.formatPhrase(RenderingContext.DATA_REND_BASE64, length)); } else { x.code(type.primitiveValue()); } break; default: if (type.isPrimitive()) { if (!renderPrimitiveWithNoValue(status, x, type)) { x.tx(context.getTranslated(type)); } } else { x.tx(context.formatPhrase(RenderingContext.DATA_REND_NO_DISP, type.fhirType()) + " "); return false; } } return true; } // overide in ResourceRenderer protected void renderCanonical(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { renderUri(status, x, type); } private void renderRatio(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { renderQuantity(status, x, type.child("numerator")); x.tx("/"); renderQuantity(status, x, type.child("denominator")); checkRenderExtensions(status, x, type); } private void renderAttachment(RenderingStatus status, XhtmlNode x, ResourceWrapper att) { String ct = att.primitiveValue("contentType"); if (att.has("url")) { x.tx(context.formatMessage(RenderingContext.DATA_REND_ATT_URL, ct, att.primitiveValue("url"))); } else if (att.has("data")) { x.tx(context.formatMessage(RenderingContext.DATA_REND_ATT_DATA, ct, displayDataType(att.child("data")))); } } private void renderContactDetail(RenderingStatus status, XhtmlNode x, ResourceWrapper cd) { if (cd.has("name")) { x.tx(cd.primitiveValue("name")+": "); } boolean first = true; for (ResourceWrapper c : cd.children("telecom")) { if (first) first = false; else x.tx(","); renderContactPoint(status, x, c); } } private void renderDateTime(RenderingStatus status, XhtmlNode x, ResourceWrapper type) throws FHIRFormatError, DefinitionException, IOException { if (!renderPrimitiveWithNoValue(status, x, type)) { x.tx(displayDateTime(type)); checkRenderExtensions(status, x, type); } } /** * this is overridden in ResourceRenderer where a better rendering is performed * @param status * @param x * @param ref * @throws IOException * @throws DefinitionException * @throws FHIRFormatError */ protected void renderReference(RenderingStatus status, XhtmlNode x, ResourceWrapper ref) throws FHIRFormatError, DefinitionException, IOException { if (ref.has("display")) { x.tx(context.getTranslated(ref.child("display"))); } else if (ref.has("reference")) { x.tx(ref.primitiveValue("reference")); } else { x.tx("??"); } } // // public void renderDateTime(RenderingStatus status, XhtmlNode x, Base e) { // if (e.hasPrimitiveValue()) { // x.addText(displayDateTime((DateTimeType) e)); // } // } // // public void renderDate(RenderingStatus status, XhtmlNode x, Base e) { // if (e.hasPrimitiveValue()) { // x.addText(displayDateTime((DateType) e)); // } // } // // public void renderDateTime(XhtmlNode x, String s) { // if (s != null) { // DateTimeType dt = new DateTimeType(s); // x.addText(displayDateTime(dt)); // } // } protected boolean renderPrimitiveWithNoValue(RenderingStatus status, XhtmlNode x, PrimitiveType prim) throws FHIRFormatError, DefinitionException, IOException { if (prim.hasPrimitiveValue()) { return false; } boolean first = true; for (Extension ext : prim.getExtension()) { if (first) first = false; else x.tx(", "); String url = ext.getUrl(); if (url.equals(ToolingExtensions.EXT_DAR)) { x.tx("Absent because : "); displayCode(x, wrapNC(ext.getValue())); } else if (url.equals(ToolingExtensions.EXT_NF)) { x.tx("Null because: "); displayCode(x, wrapNC(ext.getValue())); } else if (url.equals(ToolingExtensions.EXT_OT)) { x.code().tx("Text: "); displayCode(x, wrapNC(ext.getValue())); } else if (url.equals(ToolingExtensions.EXT_CQF_EXP)) { x.code().tx("Value calculated by: "); renderExpression(status, x, wrapNC(ext.getValue())); } else { StructureDefinition def = context.getContext().fetchResource(StructureDefinition.class, url); if (def == null) { x.code().tx(tail(url)+": "); } else { x.code().tx(def.present()+": "); } renderDataType(status, x, wrapNC(ext.getValue())); } } status.setExtensions(true); return true; } protected boolean renderPrimitiveWithNoValue(RenderingStatus status, XhtmlNode x, ResourceWrapper prim) throws FHIRFormatError, DefinitionException, IOException { if (prim.hasPrimitiveValue()) { return false; } boolean first = true; for (ResourceWrapper ext : prim.extensions()) { if (first) first = false; else x.tx(", "); String url = ext.primitiveValue("url"); if (url.equals(ToolingExtensions.EXT_DAR)) { x.tx("Absent because : "); displayCode(x, ext.child("value")); } else if (url.equals(ToolingExtensions.EXT_NF)) { x.tx("Null because: "); displayCode(x, ext.child("value")); } else if (url.equals(ToolingExtensions.EXT_OT)) { x.code().tx("Text: "); displayCode(x, ext.child("value")); } else if (url.equals(ToolingExtensions.EXT_CQF_EXP)) { x.code().tx("Value calculated by: "); renderExpression(status, x, ext.child("value")); } else { StructureDefinition def = context.getContext().fetchResource(StructureDefinition.class, url); if (def == null) { x.code().tx(tail(url)+": "); } else { x.code().tx(def.present()+": "); } renderDataType(status, x, ext.child("value")); } } status.setExtensions(true); return true; } 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; } private void displayCode(XhtmlNode x, ResourceWrapper code) { x.tx(code.primitiveValue()); } protected void renderUri(RenderingStatus status, XhtmlNode x, ResourceWrapper uri) throws FHIRFormatError, DefinitionException, IOException { if (!renderPrimitiveWithNoValue(status, x, uri)) { String v = uri.primitiveValue(); if (v != null) { if (context.getContextUtilities().isResource(v)) { v = "http://hl7.org/fhir/"+v; } if (v.startsWith("mailto:")) { x.ah(v).addText(v.substring(7)); } else { Resource r = context.getContext().fetchResource(Resource.class, v); if (r != null && r.getWebPath() != null) { if (r instanceof CanonicalResource) { x.ah(context.prefixLocalHref(r.getWebPath())).addText(crPresent((CanonicalResource) r)); } else { x.ah(context.prefixLocalHref(r.getWebPath())).addText(v); } } else { String url = context.getResolver() != null ? context.getResolver().resolveUri(context, v) : null; if (url != null) { x.ah(context.prefixLocalHref(url)).addText(v); } else if (Utilities.isAbsoluteUrlLinkable(v) && !uri.fhirType().equals("id")) { x.ah(context.prefixLocalHref(v)).addText(v); } else { x.addText(v); } } } } } checkRenderExtensions(status, x, uri); } protected void renderAnnotation(RenderingStatus status, XhtmlNode x, ResourceWrapper a) throws FHIRException { StringBuilder b = new StringBuilder(); if (a.has("text")) { b.append(context.getTranslated(a.child("text"))); } if (a.has("text") && (a.has("author") || a.has("time"))) { b.append(" ("); } if (a.has("author")) { b.append(context.formatPhrase(RenderingContext.DATA_REND_BY) + " "); ResourceWrapper auth = a.child("author"); if (auth.fhirType().equals("Reference")) { b.append(auth.primitiveValue("reference")); } else if (auth.fhirType().equals("string")) { b.append(context.getTranslated(auth)); } } if (a.has("time")) { if (b.length() > 0) { b.append(" "); } b.append("@").append(displayDateTime(a.child("time"))); } if (a.has("text") && (a.has("author") || a.has("time"))) { b.append(")"); } x.addText(b.toString()); } public String displayCoding(ResourceWrapper c) { String s = ""; if (context.isTechnicalMode()) { s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) { s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); } if (Utilities.noString(s)) { s = displayCodeTriple(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); } else if (c.has("system")) { s = s + " ("+displayCodeTriple(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code"))+")"; } else if (c.has("code")) { s = s + " ("+c.primitiveValue("code")+")"; } } else { if (c.has("display")) return context.getTranslated(c.child("display")); if (Utilities.noString(s)) s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (Utilities.noString(s)) s = c.primitiveValue("code"); } return s; } public String displayCodeSource(String system, String version) { String s = displaySystem(system); if (version != null) { s = s + "["+describeVersion(version)+"]"; } return s; } private String displayCodeTriple(String system, String version, String code) { if (system == null) { if (code == null) { return ""; } else { return "#"+code; } } else { String s = displayCodeSource(system, version); if (code != null) { s = s + "#"+code; } return s; } } public String displayCoding(List list) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (Coding c : list) { b.append(displayCoding(wrapNC(c))); } return b.toString(); } protected void renderCoding(HierarchicalTableGenerator gen, List pieces, Coding c) { if (c.isEmpty()) { return; } String url = getLinkForSystem(c.getSystem(), c.getVersion()); String name = displayCodeSource(c.getSystem(), c.getVersion()); if (!Utilities.noString(url)) { pieces.add(gen.new Piece(url, name, c.getSystem()+(c.hasVersion() ? "#"+c.getVersion() : ""))); } else { pieces.add(gen.new Piece(null, name, c.getSystem()+(c.hasVersion() ? "#"+c.getVersion() : ""))); } pieces.add(gen.new Piece(null, "#"+c.getCode(), null)); String s = context.getTranslated(c.getDisplayElement()); if (Utilities.noString(s)) { s = lookupCode(c.getSystem(), c.getVersion(), c.getCode()); } if (!Utilities.noString(s)) { pieces.add(gen.new Piece(null, " \""+s+"\"", null)); } } protected void renderCoding(HierarchicalTableGenerator gen, List pieces, ResourceWrapper c) { if (c.isEmpty()) { return; } String url = getLinkForSystem(c.primitiveValue("system"), c.primitiveValue("version")); String name = displayCodeSource(c.primitiveValue("system"), c.primitiveValue("version")); if (!Utilities.noString(url)) { pieces.add(gen.new Piece(url, name, c.primitiveValue("system")+(c.has("version") ? "#"+c.primitiveValue("version") : ""))); } else { pieces.add(gen.new Piece(null, name, c.primitiveValue("system")+(c.has("version") ? "#"+c.primitiveValue("version") : ""))); } pieces.add(gen.new Piece(null, "#"+c.primitiveValue("code"), null)); String s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) { s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); } if (!Utilities.noString(s)) { pieces.add(gen.new Piece(null, " \""+s+"\"", null)); } } public String getLinkForSystem(String system, String version) { if ("http://snomed.info/sct".equals(system)) { return "https://browser.ihtsdotools.org/"; } else if ("http://loinc.org".equals(system)) { return "https://loinc.org/"; } else if ("http://unitsofmeasure.org".equals(system)) { return "http://ucum.org"; } else if ("http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl".equals(system)) { return "https://ncit.nci.nih.gov/ncitbrowser/pages/home.jsf"; } else { String url = system; if (version != null) { url = url + "|"+version; } CodeSystem cs = context.getWorker().fetchCodeSystem(url); if (cs != null && cs.hasWebPath()) { return cs.getWebPath(); } return null; } } public String getLinkForCode(String system, String version, String code) { if ("http://snomed.info/sct".equals(system)) { return SnomedUtilities.getSctLink(version, code, context.getContext().getExpansionParameters()); } else if ("http://loinc.org".equals(system)) { if (!Utilities.noString(code)) { return "https://loinc.org/"+code; } else { return "https://loinc.org/"; } } else if ("http://www.nlm.nih.gov/research/umls/rxnorm".equals(system)) { if (!Utilities.noString(code)) { return "https://mor.nlm.nih.gov/RxNav/search?searchBy=RXCUI&searchTerm="+code; } else { return "https://www.nlm.nih.gov/research/umls/rxnorm/index.html"; } } else if ("http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl".equals(system)) { if (!Utilities.noString(code)) { return "https://ncit.nci.nih.gov/ncitbrowser/ConceptReport.jsp?code="+code; } else { return "https://ncit.nci.nih.gov/ncitbrowser/pages/home.jsf"; } } else if ("urn:iso:std:iso:3166".equals(system)) { if (!Utilities.noString(code)) { return "https://en.wikipedia.org/wiki/ISO_3166-2:"+code; } else { return "https://en.wikipedia.org/wiki/ISO_3166-2"; } } else { CodeSystem cs = context.getWorker().fetchCodeSystem(system, version); if (cs != null && cs.hasWebPath()) { if (!Utilities.noString(code)) { return cs.getWebPath()+"#"+cs.getId()+"-"+Utilities.nmtokenize(code); } else { return cs.getWebPath(); } } } return null; } public CodeResolution resolveCode(String system, String code) { return resolveCode(new Coding().setSystem(system).setCode(code)); } public CodeResolution resolveCode(ResourceWrapper c) { String systemName; String systemLink; String link; String display = null; String hint; if (c.has("display")) display = context.getTranslated(c.child("display")); if (Utilities.noString(display)) display = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (Utilities.noString(display)) { display = c.primitiveValue("code"); } CodeSystem cs = context.getWorker().fetchCodeSystem(c.primitiveValue("system")); systemLink = cs != null ? cs.getWebPath() : null; systemName = cs != null ? crPresent(cs) : displaySystem(c.primitiveValue("system")); link = getLinkForCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); hint = systemName+": "+display+(c.has("version") ? " "+ context.formatPhrase(RenderingContext.DATA_REND_VERSION, c.primitiveValue("version"), ")") : ""); return new CodeResolution(systemName, systemLink, link, display, hint); } public CodeResolution resolveCode(Coding code) { return resolveCode(wrapNC(code)); } public CodeResolution resolveCode(CodeableConcept code) { if (code.hasCoding()) { return resolveCode(code.getCodingFirstRep()); } else { return new CodeResolution(null, null, null, code.getText(), code.getText()); } } protected void renderCodingWithDetails(RenderingStatus status, XhtmlNode x, ResourceWrapper c) throws FHIRFormatError, DefinitionException, IOException { String s = ""; if (c.has("display")) s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); String sn = displaySystem(c.primitiveValue("system")); String link = getLinkForCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); XhtmlNode xi = link != null ? x.ah(context.prefixLocalHref(link)) : x; xi.tx(sn); xi.tx(" "); xi.tx(c.primitiveValue("code")); if (!Utilities.noString(s)) { x.tx(": "); x.tx(s); } if (c.has("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) { renderCoding(status, x, c, true); } protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c, boolean details) { String s = ""; if (c.has("display")) s = context.getTranslated(c.child("display")); if (Utilities.noString(s)) s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (Utilities.noString(s)) s = c.primitiveValue("code"); if (context.isTechnicalMode() && details) { String d = c.primitiveValue("display") == null ? lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")): c.primitiveValue("display"); d = context.formatPhrase(d == null || d.equals(c.primitiveValue("code")) ? RenderingContext.DATA_REND_DETAILS_STATED_ND : RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.primitiveValue("system")), c.primitiveValue("code"), d); x.addText(s+" "+d); } else { x.span(null, "{"+c.primitiveValue("system")+" "+c.primitiveValue("code")+"}").addText(s); } } public String displayCodeableConcept(ResourceWrapper cc) { String s = context.getTranslated(cc.child("Text")); if (Utilities.noString(s)) { for (ResourceWrapper c : cc.children("coding")) { if (c.has("display")) { s = context.getTranslated(c.child("display")); break; } } } if (Utilities.noString(s)) { // still? ok, let's try looking it up for (ResourceWrapper c : cc.children("coding")) { if (c.has("code") && c.has("system")) { s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (!Utilities.noString(s)) break; } } } if (Utilities.noString(s)) { if (!cc.has("coding")) s = ""; else s = cc.children("coding").get(0).primitiveValue("code"); } return s; } protected void renderCodeableReference(RenderingStatus status, XhtmlNode x, ResourceWrapper e) throws FHIRFormatError, DefinitionException, IOException { if (e.has("concept")) { renderCodeableConcept(status, x, e.child("concept")); } if (e.has("reference")) { renderReference(status, x, e.child("reference")); } } protected void renderCodeableConcept(RenderingStatus status, XhtmlNode x, ResourceWrapper cc) throws FHIRFormatError, DefinitionException, IOException { if (cc.isEmpty()) { return; } String s = context.getTranslated(cc.child("text")); if (Utilities.noString(s)) { for (ResourceWrapper c : cc.children("coding")) { if (c.has("display")) { s = context.getTranslated(c.child("display")); break; } } } if (Utilities.noString(s)) { // still? ok, let's try looking it up for (ResourceWrapper c : cc.children("coding")) { if (c.has("code") && c.has("system")) { s = lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")); if (!Utilities.noString(s)) break; } } } if (Utilities.noString(s)) { if (!cc.has("coding")) s = ""; else s = cc.children("coding").get(0).primitiveValue("code"); } if (status.isShowCodeDetails()) { x.addText(s+" "); XhtmlNode sp = x.span("background: LightGoldenRodYellow; margin: 4px; border: 1px solid khaki", null); sp.tx(" ("); boolean first = true; for (ResourceWrapper c : cc.children("coding")) { if (first) { first = false; } else { sp.tx("; "); } String url = getLinkForSystem(c.primitiveValue("system"), c.primitiveValue("version")); if (url != null) { sp.ah(context.prefixLocalHref(url)).tx(displayCodeSource(c.primitiveValue("system"), c.primitiveValue("version"))); } else { sp.tx(displayCodeSource(c.primitiveValue("system"), c.primitiveValue("version"))); } if (c.has("code")) { sp.tx("#"+c.primitiveValue("code")); } if (c.has("display") && !s.equals(c.primitiveValue("display"))) { sp.tx(" \""+context.getTranslated(c.child("display"))+"\""); } } if (hasRenderableExtensions(cc)) { if (!first) { sp.tx("; "); } renderExtensionsInText(status, sp, cc, ";"); } sp.tx(")"); } else { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (ResourceWrapper c : cc.children("coding")) { if (c.has("code") && c.has("system")) { b.append("{"+c.primitiveValue("system")+" "+c.primitiveValue("code")+"}"); } } x.span(null, context.formatPhrase(RenderingContext.DATA_REND_CODES) +b.toString()).addText(s); } checkRenderExtensions(status, x, cc); } protected String displayIdentifier(ResourceWrapper ii) { String s = Utilities.noString(ii.primitiveValue("value")) ? "?ngen-9?" : ii.primitiveValue("value"); if ("urn:ietf:rfc:3986".equals(ii.primitiveValue("system")) && s.startsWith("urn:oid:")) { s = "OID:"+s.substring(8); } else if ("urn:ietf:rfc:3986".equals(ii.primitiveValue("system")) && s.startsWith("urn:uuid:")) { s = "UUID:"+s.substring(9); } else { NamingSystem ns = context.getContext().getNSUrlMap().get(ii.primitiveValue("system")); if (ns != null) { s = crPresent(ns)+"#"+s; } if (ii.has("type")) { ResourceWrapper type = ii.child("type"); if (type.has("text")) s = context.getTranslated(type.child("text"))+":\u00A0"+s; else if (type.has("coding") && type.children("coding").get(0).has("display")) s = context.getTranslated(type.children("coding").get(0).child("display"))+": "+s; else if (type.has("coding") && type.children("coding").get(0).has("code")) s = lookupCode(type.children("coding").get(0).primitiveValue("system"), type.children("coding").get(0).primitiveValue("version"), type.children("coding").get(0).primitiveValue("code")); } else if (ii.has("system")) { s = ii.primitiveValue("system")+"#"+s; } } if (ii.has("use") || ii.has("period")) { s = s + "\u00A0("; if (ii.has("use")) { s = s + "use:\u00A0"+ii.primitiveValue("use"); } if (ii.has("use") || ii.has("period")) { s = s + ",\u00A0"; } if (ii.has("period")) { s = s + "period:\u00A0"+displayPeriod(ii.child("period")); } s = s + ")"; } return s; } protected void renderIdentifier(RenderingStatus status, XhtmlNode x, ResourceWrapper ii) throws FHIRFormatError, DefinitionException, IOException { if (ii.has("type")) { ResourceWrapper type = ii.child("type"); if (type.has("text")) { x.tx(context.getTranslated(type.child("text"))); } else if (type.has("coding") && type.children("coding").get(0).has("display")) { x.tx(context.getTranslated(type.children("coding").get(0).child("display"))); } else if (type.has("coding") && type.children("coding").get(0).has("code")) { x.tx(lookupCode(type.children("coding").get(0).primitiveValue("system"), type.children("coding").get(0).primitiveValue("version"), type.children("coding").get(0).primitiveValue("code"))); } x.tx("/"); } else if (ii.has("system")) { NamingSystem ns = context.getContext().getNSUrlMap().get(ii.primitiveValue("system")); if (ns != null) { if (ns.hasWebPath()) { x.ah(context.prefixLocalHref(ns.getWebPath()), ns.getDescription()).tx(crPresent(ns)); } else { x.tx(crPresent(ns)); } } else { switch (ii.primitiveValue("system")) { case "urn:oid:2.51.1.3": x.ah("https://www.gs1.org/standards/id-keys/gln", context.formatPhrase(RenderingContext.DATA_REND_GLN)).tx("GLN"); break; default: x.code(ii.primitiveValue("system")); } } x.tx("/"); } x.tx(Utilities.noString(ii.primitiveValue("value")) ? "?ngen-9?" : ii.primitiveValue("value")); if (ii.has("use") || ii.has("period")) { x.nbsp(); x.tx("("); if (ii.has("use")) { x.tx(context.formatPhrase(RenderingContext.DATA_REND_USE)); x.nbsp(); x.tx(ii.primitiveValue("use")); } if (ii.has("use") || ii.has("period")) { x.tx(","); x.nbsp(); } if (ii.has("period")) { x.tx(context.formatPhrase(RenderingContext.DATA_REND_PERIOD)); x.nbsp(); x.tx(displayPeriod(ii.child("period"))); } x.tx(")"); } checkRenderExtensions(status, x, ii); } public static String displayHumanName(ResourceWrapper name) { StringBuilder s = new StringBuilder(); if (name.has("text")) s.append(name.primitiveValue("text")); else { for (ResourceWrapper p : name.children("given")) { s.append(p.primitiveValue()); s.append(" "); } if (name.has("family")) { s.append(name.primitiveValue("family")); s.append(" "); } } if (name.has("use") && !"usual".equals(name.primitiveValue("use"))) s.append("("+name.primitiveValue("use")+")"); return s.toString(); } protected void renderHumanName(RenderingStatus status, XhtmlNode x, ResourceWrapper name) throws FHIRFormatError, DefinitionException, IOException { StringBuilder s = new StringBuilder(); if (name.has("text")) s.append(context.getTranslated(name.child("text"))); else { for (ResourceWrapper p : name.children("given")) { s.append(context.getTranslated(p)); s.append(" "); } if (name.has("family")) { s.append(context.getTranslated(name.child("family"))); s.append(" "); } } if (name.has("use") && !"usual".equals(name.primitiveValue("use"))) { s.append("("+context.getTranslatedCode(name.primitiveValue("use"), "http://hl7.org/fhir/name-use")+")"); } x.addText(s.toString()); checkRenderExtensions(status, x, name); } private String displayAddress(ResourceWrapper address) { StringBuilder s = new StringBuilder(); if (address.has("text")) s.append(context.getTranslated(address.child("text"))); else { for (ResourceWrapper p : address.children("line")) { s.append(context.getTranslated(p)); s.append(" "); } if (address.has("city")) { s.append(context.getTranslated(address.child("city"))); s.append(" "); } if (address.has("state")) { s.append(context.getTranslated(address.child("state"))); s.append(" "); } if (address.has("postalCode")) { s.append(context.getTranslated(address.child("postalCode"))); s.append(" "); } if (address.has("country")) { s.append(context.getTranslated(address.child("country"))); s.append(" "); } } if (address.has("use")) { s.append("("+address.primitiveValue("use")+")"); } return s.toString(); } protected void renderAddress(RenderingStatus status, XhtmlNode x, ResourceWrapper address) throws FHIRFormatError, DefinitionException, IOException { x.addText(displayAddress(address)); checkRenderExtensions(status, x, address); } public String displayContactPoint(ResourceWrapper contact) { StringBuilder s = new StringBuilder(); s.append(describeSystem(contact.primitiveValue("system"))); if (Utilities.noString(contact.primitiveValue("value"))) s.append("-unknown-"); else s.append(contact.primitiveValue("value")); if (contact.has("use")) s.append("("+getTranslatedCode(contact.child("use"))+")"); return s.toString(); } public String displayContactDetail(ResourceWrapper contact) { CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder(); for (ResourceWrapper cp : contact.children("telecom")) { s.append(displayContactPoint(cp)); } return contact.primitiveValue("name")+(s.length() == 0 ? "" : " ("+s.toString()+")"); } protected String getLocalizedBigDecimalValue(BigDecimal input, Currency c) { NumberFormat numberFormat = NumberFormat.getNumberInstance(context.getLocale()); numberFormat.setGroupingUsed(true); numberFormat.setMaximumFractionDigits(c.getDefaultFractionDigits()); numberFormat.setMinimumFractionDigits(c.getDefaultFractionDigits()); return numberFormat.format(input); } protected void renderMoney(RenderingStatus status, XhtmlNode x, ResourceWrapper money) { if (x.getName().equals("blockquote")) { x = x.para(); } Currency c = money.has("currency") ? Currency.getInstance(money.primitiveValue("currency")) : null; if (c != null) { XhtmlNode s = x.span(null, c.getDisplayName()); s.tx(c.getSymbol(context.getLocale())); s.tx(getLocalizedBigDecimalValue(new BigDecimal(money.primitiveValue("value")), c)); x.tx(" ("+c.getCurrencyCode()+")"); } else { if (money.has("currency")) { x.tx(money.primitiveValue("currency")); } x.tx(money.primitiveValue("value")); } } protected void renderExpression(RenderingStatus status, XhtmlNode x, ResourceWrapper expr) { // there's two parts: what the expression is, and how it's described. // we start with what it is, and then how it's described XhtmlNode p = x; if (p.getName().equals("blockquote")) { p = p.para(); } if (expr.has("expression")) { if (expr.has("reference")) { p = x.ah(context.prefixLocalHref(expr.primitiveValue("reference"))); } XhtmlNode c = p; if (expr.has("language")) { c = c.span(null, expr.primitiveValue("language")); } c.code().tx(expr.primitiveValue("expression")); } else if (expr.has("reference")) { p.ah(context.prefixLocalHref(expr.primitiveValue("reference"))).tx(context.formatPhrase(RenderingContext.DATA_REND_SOURCE)); } if (expr.has("name") || expr.has("description")) { p.tx("("); if (expr.has("name")) { p.b().tx(expr.primitiveValue("name")); } if (expr.has("description")) { p.tx("\""); p.tx(context.getTranslated(expr.child("description"))); p.tx("\""); } p.tx(")"); } } protected void renderContactPoint(RenderingStatus status, XhtmlNode x, ResourceWrapper contact) { if (contact != null) { if (!contact.has("system")) { x.addText(displayContactPoint(contact)); } else { String v = contact.primitiveValue("value"); switch (contact.primitiveValue("system")) { case "email": x.ah("mailto:"+v).tx(v); break; case "fax": x.addText(displayContactPoint(contact)); break; case "other": x.addText(displayContactPoint(contact)); break; case "pager": x.addText(displayContactPoint(contact)); break; case "phone": if (contact.has("value") && v != null && v.startsWith("+")) { x.ah("tel:"+v.replace(" ", "")).tx(v); } else { x.addText(displayContactPoint(contact)); } break; case "sms": x.addText(displayContactPoint(contact)); break; case "url": x.ah(context.prefixLocalHref(v)).tx(v); break; default: break; } } } } protected void displayContactPoint(XhtmlNode p, ContactPoint c) { if (c != null) { if (c.getSystem() == ContactPointSystem.PHONE) { p.tx(context.formatPhrase(RenderingContext.DATA_REND_PHONE, c.getValue()) + " "); } else if (c.getSystem() == ContactPointSystem.FAX) { p.tx(context.formatPhrase(RenderingContext.DATA_REND_FAX, c.getValue()) + " "); } else if (c.getSystem() == ContactPointSystem.EMAIL) { p.tx(c.getValue()); } else if (c.getSystem() == ContactPointSystem.URL) { if (c.getValue().length() > 30) { p.addText(c.getValue().substring(0, 30)+"..."); } else { p.addText(c.getValue()); } } } } protected void addTelecom(XhtmlNode p, ResourceWrapper c) { String sys = c.primitiveValue("system"); String value = c.primitiveValue("value"); if (sys.equals("phone")) { p.tx(context.formatPhrase(RenderingContext.DATA_REND_PHONE, value) + " "); } else if (sys.equals("fax")) { p.tx(context.formatPhrase(RenderingContext.DATA_REND_FAX, value) + " "); } else if (sys.equals("email")) { p.ah("mailto:"+value).addText(value); } else if (sys.equals("url")) { if (value.length() > 30) p.ah(context.prefixLocalHref(value)).addText(value.substring(0, 30)+"..."); else p.ah(context.prefixLocalHref(value)).addText(value); } } private static String describeSystem(String system) { if (system == null) return ""; switch (system) { case "phone": return "ph: "; case "fax": return "fax: "; default: return ""; } } protected String displayQuantity(ResourceWrapper q) { if (q == null) { return ""; } StringBuilder s = new StringBuilder(); s.append(q.has("value") ? q.primitiveValue("value") : "?"); if (q.has("unit")) s.append(" ").append(q.primitiveValue("unit")); else if (q.has("code")) s.append(" ").append(q.primitiveValue("code")); return s.toString(); } protected void renderQuantity(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRFormatError, DefinitionException, IOException { if (q.has("comparator")) x.addText(q.primitiveValue("comparator")); if (q.has("value")) { x.addText(context.getTranslated(q.child("value"))); } if (q.has("unit")) x.tx(" "+context.getTranslated(q.child("unit"))); else if (q.has("code") && q.has("system")) { // if there's a code there *shall* be a system, so if we've got one and not the other, things are invalid and we won't bother trying to render if (q.has("system") && q.primitiveValue("system").equals("http://unitsofmeasure.org")) x.tx(" "+q.primitiveValue("code")); else x.tx("(unit "+q.primitiveValue("code")+" from "+q.primitiveValue("system")+")"); } 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"))+"')"); } checkRenderExtensions(status, x, q); } protected void renderQuantity(HierarchicalTableGenerator gen, List pieces, ResourceWrapper q, boolean showCodeDetails) { pieces.add(gen.new Piece(null, displayQuantity(q), null)); } protected void renderQuantity(HierarchicalTableGenerator gen, List pieces, Quantity q, boolean showCodeDetails) { pieces.add(gen.new Piece(null, displayQuantity(wrapNC(q)), null)); } public String displayRange(ResourceWrapper q) { if (!q.has("low") && !q.has("high")) return "?"; StringBuilder b = new StringBuilder(); ResourceWrapper lowC = q.child("low"); ResourceWrapper highC = q.child("high"); boolean sameUnits = (lowC != null && highC != null) && ((lowC.has("unit") && highC.has("unit") && lowC.child("unit").matches(highC.child("unit"))) || (lowC.has("code") && highC.has("code") && lowC.child("code").matches(highC.child("code")))); String low = "?"; if (q.has("low") && lowC.has("value")) low = sameUnits ? lowC.primitiveValue("value").toString() : displayQuantity(lowC); String high = displayQuantity(highC); if (high.isEmpty()) high = "?"; b.append(low).append("\u00A0to\u00A0").append(high); return b.toString(); } protected void renderRange(RenderingStatus status, XhtmlNode x, ResourceWrapper q) { if (q.has("low")) x.addText(q.child("low").primitiveValue("value").toString()); else x.tx("?"); x.tx("-"); if (q.has("high")) x.addText(q.child("high").primitiveValue("value").toString()); else x.tx("?"); if (q.has("low") && q.child("low").has("unit")) x.tx(" "+q.child("low").primitiveValue("unit")); } public String displayPeriod(ResourceWrapper p) { String s = !p.has("start") ? "(?)" : displayDateTime(p.child("start")); s = s + " --> "; return s + (!p.has("end") ? context.formatPhrase(RenderingContext.DATA_REND_ONGOING) : displayDateTime(p.child("end"))); } public void renderPeriod(RenderingStatus status, XhtmlNode x, ResourceWrapper p) { x.addText(!p.has("start") ? "??" : displayDateTime(p.child("start"))); x.tx(" --> "); x.addText(!p.has("end") ? context.formatPhrase(RenderingContext.DATA_REND_ONGOING) : displayDateTime(p.child("end"))); } public void renderUsageContext(RenderingStatus status, XhtmlNode x, ResourceWrapper u) throws FHIRFormatError, DefinitionException, IOException { renderCoding(status, x, u.child("code"), false); x.tx(" = "); renderDataType(status, x, u.child("value")); } public void renderTriggerDefinition(RenderingStatus status, XhtmlNode x, ResourceWrapper td) throws FHIRFormatError, DefinitionException, IOException { if (x.isPara()) { x.b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE)); x.tx(": "); x.tx(td.child("type").primitiveValue("display")); if (td.has("name")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.GENERAL_NAME)); x.tx(": "); x.tx(context.getTranslated(td.child("name"))); } if (td.has("code")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE)); x.tx(": "); renderCodeableConcept(status, x, td.child("code")); } if (td.has("timing")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.DATA_REND_TIMING)); x.tx(": "); renderDataType(status, x, td.child("timing")); } if (td.has("condition")) { x.tx(", "); x.b().tx(context.formatPhrase(RenderingContext.DATA_REND_COND)); x.tx(": "); renderExpression(status, x, td.child("condition")); } } else { XhtmlNode tbl = x.table("grid", false); XhtmlNode tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE)); tr.td().tx(td.child("type").primitiveValue("display")); if (td.has("name")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_NAME)); tr.td().tx(context.getTranslated(td.child("name"))); } if (td.has("code")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE)); renderCodeableConcept(status, tr.td(), td.child("code")); } if (td.has("timing")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.DATA_REND_TIMING)); renderDataType(status, tr.td(), td.child("timing")); } if (td.has("condition")) { tr = tbl.tr(); tr.td().b().tx(context.formatPhrase(RenderingContext.DATA_REND_COND)); renderExpression(status, tr.td(), td.child("condition")); } } } public void renderDataRequirement(RenderingStatus status, XhtmlNode x, ResourceWrapper dr) throws FHIRFormatError, DefinitionException, IOException { XhtmlNode tbl = x.table("grid", false); XhtmlNode tr = tbl.tr(); XhtmlNode td = tr.td().colspan("2"); td.b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE)); td.tx(": "); StructureDefinition sd = context.getWorker().fetchTypeDefinition(dr.primitiveValue("type")); if (sd != null && sd.hasWebPath()) { td.ah(context.prefixLocalHref(sd.getWebPath())).tx(dr.primitiveValue("type")); } else { td.tx(dr.primitiveValue("type")); } if (dr.has("profile")) { td.tx(" ("); boolean first = true; for (ResourceWrapper p : dr.children("profile")) { if (first) first = false; else td.tx(" | "); sd = context.getWorker().fetchResource(StructureDefinition.class, p.primitiveValue()); if (sd != null && sd.hasWebPath()) { td.ah(context.prefixLocalHref(sd.getWebPath())).tx(crPresent(sd)); } else { td.tx(p.primitiveValue()); } } td.tx(")"); } if (dr.has("subject")) { tr = tbl.tr(); td = tr.td().colspan("2"); td.b().tx(context.formatPhrase(RenderingContext.GENERAL_SUBJ)); ResourceWrapper subj = dr.child("subject"); if (subj.fhirType().equals("reference")) { renderReference(status, td, subj); } else { renderCodeableConcept(status, td, subj); } } if (dr.has("codeFilter") || dr.has("dateFilter")) { tr = tbl.tr().backgroundColor("#efefef"); tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_FILTER)); tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_VALUE)); } for (ResourceWrapper cf : dr.children("codeFilter")) { tr = tbl.tr(); if (cf.has("path")) { tr.td().tx(cf.primitiveValue("path")); } else { tr.td().tx(context.formatPhrase(RenderingContext.DATA_REND_SEARCH, cf.primitiveValue("searchParam")) + " "); } if (cf.has("valueSet")) { td = tr.td(); td.tx(context.formatPhrase(RenderingContext.DATA_REND_VALUESET) + " "); renderDataType(status, td, cf.child("valueSet")); } else { boolean first = true; td = tr.td(); td.tx(context.formatPhrase(RenderingContext.DATA_REND_THESE_CODES) + " "); for (ResourceWrapper c : cf.children("code")) { if (first) first = false; else td.tx(", "); renderDataType(status, td, c); } } } for (ResourceWrapper cf : dr.children("dateFilter")) { tr = tbl.tr(); if (cf.has("path")) { tr.td().tx(cf.primitiveValue("path")); } else { tr.td().tx(context.formatPhrase(RenderingContext.DATA_REND_SEARCH, cf.primitiveValue("searchParam")) + " "); } renderDataType(status, tr.td(), cf.child("value")); } if (dr.has("sort") || dr.has("limit")) { tr = tbl.tr(); td = tr.td().colspan("2"); if (dr.has("limit")) { td.b().tx(context.formatPhrase(RenderingContext.DATA_REND_LIMIT)); td.tx(": "); td.tx(dr.primitiveValue("limit")); if (dr.has("sort")) { td.tx(", "); } } if (dr.has("sort")) { td.b().tx(context.formatPhrase(RenderingContext.DATA_REND_SORT)); td.tx(": "); boolean first = true; for (ResourceWrapper p : dr.children("sort")) { if (first) first = false; else td.tx(" | "); td.tx(p.primitiveValue("direction").equals("ascending") ? "+" : "-"); td.tx(p.primitiveValue("path")); } } } } private String displayTiming(ResourceWrapper s) throws FHIRException { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); if (s.has("code")) { b.append(context.formatPhrase(RenderingContext.GENERAL_CODE, displayCodeableConcept(s.child("code"))) + " "); } if (s.has("event")) { CommaSeparatedStringBuilder c = new CommaSeparatedStringBuilder(); for (ResourceWrapper p : s.children("event")) { if (p.hasPrimitiveValue()) { c.append(displayDateTime(p)); } else if (!renderExpression(c, p)) { c.append("??"); } } b.append(context.formatPhrase(RenderingContext.DATA_REND_EVENTS, c.toString()) + " "); } if (s.has("repeat")) { ResourceWrapper rep = s.child("repeat"); if (rep.has("boundsPeriod") && rep.child("boundsPeriod").has("start")) b.append(context.formatPhrase(RenderingContext.DATA_REND_STARTING, displayDateTime(rep.child("boundsPeriod").child("start"))) + " "); if (rep.has("count")) b.append(context.formatPhrase(RenderingContext.DATA_REND_COUNT, rep.primitiveValue("count")) + " " + " times"); if (rep.has("duration")) b.append(context.formatPhrase(RenderingContext.DATA_REND_DURATION, rep.primitiveValue("duration")+displayTimeUnits(rep.primitiveValue("periodUnit"), "1".equals(rep.primitiveValue("duration")))) + " "); String st = ""; if (rep.has("offset")) { st = rep.primitiveValue("offset")+"min "; } if (!Utilities.noString(st)) { b.append(st); } for (ResourceWrapper wh : rep.children("when")) { b.append(displayEventCode(wh.primitiveValue())); } st = ""; if (!rep.has("frequency") || (!rep.has("frequencyMax") && rep.primitiveValue("frequency").equals("1"))) { st = context.formatPhrase(RenderingContext.DATA_REND_ONCE); } else { st = rep.primitiveValue("frequency"); if (rep.has("frequencyMax")) st = st + "-"+rep.primitiveValue("frequencyMax"); } if (rep.has("period")) { st = st + " "+ (context.formatPhrase(RenderingContext.DATA_REND_PER))+" "+rep.primitiveValue("period"); if (rep.has("periodMax")) { st = st + "-"+rep.primitiveValue("periodMax"); } st = st + " "+displayTimeUnits(rep.primitiveValue("periodUnit"), "1".equals(rep.primitiveValue("period"))); } if (!Utilities.noString(st)) { b.append(st); } if (rep.has("boundsPeriod") && rep.child("boundsPeriod").has("end")) { b.append(context.formatPhrase(RenderingContext.DATA_REND_UNTIL, displayDateTime(rep.child("boundsPeriod").child("end"))) + " "); } } return b.toString(); } private boolean renderExpression(CommaSeparatedStringBuilder c, ResourceWrapper p) { ResourceWrapper exp = p.extensionValue("http://hl7.org/fhir/StructureDefinition/cqf-expression"); if (exp == null || !exp.has("value")) { return false; } c.append(exp.child("value").primitiveValue("expression")); return true; } private String displayEventCode(String when) { if (when == null) return "??"; switch (when.toLowerCase()) { case "c": return (context.formatPhrase(RenderingContext.DATA_REND_MEALS)); case "cd": return (context.formatPhrase(RenderingContext.DATA_REND_ATLUNCH)); case "cm": return (context.formatPhrase(RenderingContext.DATA_REND_ATBKFST)); case "cv": return (context.formatPhrase(RenderingContext.DATA_REND_ATDINR)); case "ac": return (context.formatPhrase(RenderingContext.DATA_REND_BFMEALS)); case "acd": return (context.formatPhrase(RenderingContext.DATA_REND_BFLUNCH)); case "acm": return (context.formatPhrase(RenderingContext.DATA_REND_BFBKFST)); case "acv": return (context.formatPhrase(RenderingContext.DATA_REND_BFDINR)); case "hs": return (context.formatPhrase(RenderingContext.DATA_REND_BFSLEEP)); case "pc": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRMEALS)); case "pcd": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRLUNCH)); case "pcm": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRBKFST)); case "pcv": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRDINR)); case "wake": return (context.formatPhrase(RenderingContext.DATA_REND_AFTRWKNG)); case "morn": return (context.formatPhrase(RenderingContext.DATA_REND_MORNING)); case "morn.early": return (context.formatPhrase(RenderingContext.DATA_REND_MORNING_EARLY)); case "morn.late": return (context.formatPhrase(RenderingContext.DATA_REND_MORNING_LATE)); case "noon": return (context.formatPhrase(RenderingContext.DATA_REND_NOON)); case "aft": return (context.formatPhrase(RenderingContext.DATA_REND_AFTERNOON)); case "aft.early": return (context.formatPhrase(RenderingContext.DATA_REND_AFTERNOON_EARLY)); case "aft.late": return (context.formatPhrase(RenderingContext.DATA_REND_AFTERNOON_LATE)); case "eve": return (context.formatPhrase(RenderingContext.DATA_REND_EVENING)); case "eve.early": return (context.formatPhrase(RenderingContext.DATA_REND_EVENING_EARLY)); case "eve.late": return (context.formatPhrase(RenderingContext.DATA_REND_EVENING_LATE)); case "night": return (context.formatPhrase(RenderingContext.DATA_REND_NIGHT)); case "phs": return (context.formatPhrase(RenderingContext.DATA_REND_AFTER_SLEEP)); case "imd": return (context.formatPhrase(RenderingContext.DATA_REND_IMMEDIATE)); default: return "?"+when+"?"; } } private String displayTimeUnits(String units, boolean singular) { if (units == null) return "??"; switch (units) { case "a": return singular ? "year" : "years"; case "d": return singular ? "day" : "days"; case "h": return singular ? "hour" : "hours"; case "min": return singular ? "minute" : "minutes"; case "mo": return singular ? "month" : "months"; case "s": return singular ? "second" : "seconds"; case "wk": return singular ? "week" : "weeks"; default: return "?"+units+"?"; } } protected void renderTiming(RenderingStatus status, XhtmlNode x, ResourceWrapper s) throws FHIRException { x.addText(displayTiming(s)); } private String displaySampledData(ResourceWrapper s) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); if (s.has("origin")) b.append(context.formatPhrase(RenderingContext.DATA_REND_ORIGIN, displayQuantity(s.child("origin"))) + " "); if (s.has("interval")) { b.append(context.formatPhrase(RenderingContext.DATA_REND_INT, s.primitiveValue("interval")) + " "); if (s.has("intervalUnit")) b.append(s.primitiveValue("intervalUnit")); } if (s.has("factor")) b.append(context.formatPhrase(RenderingContext.DATA_REND_FACT, s.primitiveValue("factor")) + " "); if (s.has("lowerLimit")) b.append(context.formatPhrase(RenderingContext.DATA_REND_LOWER, s.primitiveValue("lowerLimit")) + " "); if (s.has("upperLimit")) b.append(context.formatPhrase(RenderingContext.DATA_REND_UP, s.primitiveValue("upperLimit")) + " "); if (s.has("dimensions")) b.append(context.formatPhrase(RenderingContext.DATA_REND_DIM, s.primitiveValue("dimensions")) + " "); if (s.has("data")) b.append(context.formatPhrase(RenderingContext.DATA_REND_DATA, s.primitiveValue("data")) + " "); return b.toString(); } protected void renderSampledData(RenderingStatus status, XhtmlNode x, ResourceWrapper sampledData) { x.addText(displaySampledData(sampledData)); } public RenderingContext getContext() { return context; } public XhtmlNode makeExceptionXhtml(Exception e, String function) { XhtmlNode xn; xn = new XhtmlNode(NodeType.Element, "div"); XhtmlNode p = xn.para(); p.b().tx((context.formatPhrase(RenderingContext.DATA_REND_EXCEPTION)) +function+": "+e.getMessage()); p.addComment(getStackTrace(e)); return xn; } private String getStackTrace(Exception e) { StringBuilder b = new StringBuilder(); b.append("\r\n"); for (StackTraceElement t : e.getStackTrace()) { b.append(t.getClassName()+"."+t.getMethodName()+" ("+t.getFileName()+":"+t.getLineNumber()); b.append("\r\n"); } return b.toString(); } protected String systemFromCanonical(String system) { if (system == null) { return null; } else if (system.contains("|")) { return system.substring(0, system.indexOf("|")); } else { return null; } } protected String versionFromCanonical(String system) { if (system == null) { return null; } else if (system.contains("|")) { return system.substring(system.indexOf("|")+1); } else { return system; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy