001package org.hl7.fhir.r5.renderers; 002 003import java.io.IOException; 004import java.io.UnsupportedEncodingException; 005import java.util.List; 006 007import org.hl7.fhir.exceptions.DefinitionException; 008import org.hl7.fhir.exceptions.FHIRException; 009import org.hl7.fhir.exceptions.FHIRFormatError; 010import org.hl7.fhir.r5.model.OperationOutcome; 011import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; 012import org.hl7.fhir.r5.renderers.utils.RenderingContext; 013import org.hl7.fhir.r5.renderers.utils.ResourceWrapper; 014import org.hl7.fhir.r5.utils.EOperationOutcome; 015import org.hl7.fhir.r5.utils.ToolingExtensions; 016import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; 017import org.hl7.fhir.utilities.xhtml.XhtmlNode; 018 019public class OperationOutcomeRenderer extends ResourceRenderer { 020 021 022 public OperationOutcomeRenderer(RenderingContext context) { 023 super(context); 024 } 025 026 027 @Override 028 public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException { 029 List<ResourceWrapper> issues = r.children("issue"); 030 int hint = 0; 031 int warn = 0; 032 int err = 0; 033 for (ResourceWrapper issue : issues) { 034 switch (issue.primitiveValue("severity")) { 035 case "information" : 036 hint++; 037 break; 038 case "warning" : 039 warn++; 040 break; 041 case "error" : 042 case "fatal" : 043 err++; 044 break; 045 } 046 } 047 if (hint + warn + err == 0) { 048 return context.formatPhrase(RenderingContext.OP_OUT_SUMM_ALL_OK); 049 } else if (hint == 0) { 050 return context.formatPhrase(RenderingContext.OP_OUT_SUMM_NOHINT, err, warn); 051 } else { 052 return context.formatPhrase(RenderingContext.OP_OUT_SUMM, err, warn, hint); 053 } 054 } 055 056 @Override 057 public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper op) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { 058 renderResourceTechDetails(op, x); 059 boolean hasSource = false; 060 boolean success = true; 061 for (ResourceWrapper i : op.children("issue")) { 062 success = success && "information".equals(i.primitiveValue("severity")); 063 hasSource = hasSource || i.hasExtension(ToolingExtensions.EXT_ISSUE_SOURCE); 064 } 065 if (success) { 066 x.para().tx(context.formatPhrase(RenderingContext.OP_OUT_OK)); 067 } 068 if (op.has("issue")) { 069 XhtmlNode tbl = x.table("grid"); // on the basis that we'll most likely be rendered using the standard fhir css, but it doesn't really matter 070 XhtmlNode tr = tbl.tr(); 071 tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SEV)); 072 tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_LOCATION)); 073 tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE)); 074 tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_DETAILS)); 075 tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_DIAG)); 076 if (hasSource) { 077 tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SRC)); 078 } 079 for (ResourceWrapper i : op.children("issue")) { 080 tr = tbl.tr(); 081 tr.td().addText(getTranslatedCode(i.child("severity"))); 082 XhtmlNode td = tr.td(); 083 boolean d = false; 084 for (ResourceWrapper s : i.has("expression") ? i.children("expression") : i.children("location")) { 085 if (d) 086 td.tx(", "); 087 else 088 d = true; 089 td.addText(s.primitiveValue()); 090 } 091 tr.td().addText(getTranslatedCode(i.child("code"))); 092 if (i.has("details")) 093 tr.td().addText(i.child("details").primitiveValue("text")); 094 smartAddText(tr.td(), i.primitiveValue("diagnostics")); 095 if (hasSource) { 096 ResourceWrapper ext = i.extension(ToolingExtensions.EXT_ISSUE_SOURCE); 097 tr.td().addText(ext == null || !ext.has("value") ? "" : displayDataType(ext.child("value"))); 098 } 099 } 100 } 101 } 102 103 104 public void describe(XhtmlNode x, OperationOutcome oo) { 105 x.tx(display(oo)); 106 } 107 108 public String display(OperationOutcome oo) { 109 return (context.formatPhrase(RenderingContext.GENERAL_TODO)); 110 } 111 112 public static String toString(OperationOutcome oo) { 113 CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); 114 for (OperationOutcomeIssueComponent issue : oo.getIssue()) { 115 b.append(issue.getSeverity().toCode()+": "+issue.getDetails().getText()); 116 } 117 return b.toString(); 118 } 119}