Improve Library rendering

This commit is contained in:
Grahame Grieve 2020-09-21 07:08:05 +10:00
commit 4a4105413f
25 changed files with 779 additions and 21 deletions

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -0,0 +1,26 @@
public ContactPoint getEmail() {
for (ContactPoint cp : getTelecom()) {
if (cp.getSystem() == ContactPointSystem.EMAIL) {
return cp;
}
}
return null;
}
public ContactPoint getPhone() {
for (ContactPoint cp : getTelecom()) {
if (cp.getSystem() == ContactPointSystem.PHONE) {
return cp;
}
}
return null;
}
public ContactPoint getUrl() {
for (ContactPoint cp : getTelecom()) {
if (cp.getSystem() == ContactPointSystem.URL) {
return cp;
}
}
return null;
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.r5.model.Enumerations.*; import org.hl7.fhir.r5.model.Enumerations.*;
import org.hl7.fhir.instance.model.api.IBaseDatatypeElement; import org.hl7.fhir.instance.model.api.IBaseDatatypeElement;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
@ -308,6 +309,32 @@ public class ContactDetail extends DataType implements ICompositeType {
return super.isEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty(name, telecom); return super.isEmpty() && ca.uhn.fhir.util.ElementUtil.isEmpty(name, telecom);
} }
public ContactPoint getEmail() {
for (ContactPoint cp : getTelecom()) {
if (cp.getSystem() == ContactPointSystem.EMAIL) {
return cp;
}
}
return null;
}
public ContactPoint getPhone() {
for (ContactPoint cp : getTelecom()) {
if (cp.getSystem() == ContactPointSystem.PHONE) {
return cp;
}
}
return null;
}
public ContactPoint getUrl() {
for (ContactPoint cp : getTelecom()) {
if (cp.getSystem() == ContactPointSystem.URL) {
return cp;
}
}
return null;
}
} }

View File

@ -689,10 +689,42 @@ public class DataRenderer extends Renderer {
} }
protected void renderContactPoint(XhtmlNode x, ContactPoint contact) { protected void renderContactPoint(XhtmlNode x, ContactPoint contact) {
x.addText(displayContactPoint(contact)); if (contact != null) {
switch (contact.getSystem()) {
case EMAIL:
x.ah("mailto:"+contact.getValue()).tx(contact.getValue());
break;
case FAX:
x.addText(displayContactPoint(contact));
break;
case NULL:
x.addText(displayContactPoint(contact));
break;
case OTHER:
x.addText(displayContactPoint(contact));
break;
case PAGER:
x.addText(displayContactPoint(contact));
break;
case PHONE:
if (contact.hasValue() && contact.getValue().startsWith("+")) {
x.ah("tel:"+contact.getValue()).tx(contact.getValue());
} else {
x.addText(displayContactPoint(contact));
}
break;
case SMS:
x.addText(displayContactPoint(contact));
break;
case URL:
x.ah(contact.getValue()).tx(contact.getValue());
break;
default:
break;
}
}
} }
protected void addTelecom(XhtmlNode p, ContactPoint c) { protected void addTelecom(XhtmlNode p, ContactPoint c) {
if (c.getSystem() == ContactPointSystem.PHONE) { if (c.getSystem() == ContactPointSystem.PHONE) {
p.tx("Phone: "+c.getValue()); p.tx("Phone: "+c.getValue());

View File

@ -0,0 +1,533 @@
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Annotation;
import org.hl7.fhir.r5.model.Attachment;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ContactDetail;
import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.DataRequirement;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Library;
import org.hl7.fhir.r5.model.ListResource;
import org.hl7.fhir.r5.model.ListResource.ListResourceEntryComponent;
import org.hl7.fhir.r5.model.ParameterDefinition;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.RelatedArtifact;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class LibraryRenderer extends ResourceRenderer {
private static final int DATA_IMG_SIZE_CUTOFF = 4000;
public LibraryRenderer(RenderingContext context) {
super(context);
}
public LibraryRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
return render(x, (Library) dr);
}
public boolean render(XhtmlNode x, ResourceWrapper lib) throws FHIRFormatError, DefinitionException, IOException {
PropertyWrapper authors = lib.getChildByName("author");
PropertyWrapper editors = lib.getChildByName("editor");
PropertyWrapper reviewers = lib.getChildByName("reviewer");
PropertyWrapper endorsers = lib.getChildByName("endorser");
if ((authors != null && authors.hasValues()) || (editors != null && editors.hasValues()) || (reviewers != null && reviewers.hasValues()) || (endorsers != null && endorsers.hasValues())) {
boolean email = hasCT(authors, "email") || hasCT(editors, "email") || hasCT(reviewers, "email") || hasCT(endorsers, "email");
boolean phone = hasCT(authors, "phone") || hasCT(editors, "phone") || hasCT(reviewers, "phone") || hasCT(endorsers, "phone");
boolean url = hasCT(authors, "url") || hasCT(editors, "url") || hasCT(reviewers, "url") || hasCT(endorsers, "url");
x.h2().tx("Participants");
XhtmlNode t = x.table("grid");
if (authors != null) {
for (BaseWrapper cd : authors.getValues()) {
participantRow(t, "Author", cd, email, phone, url);
}
}
if (authors != null) {
for (BaseWrapper cd : editors.getValues()) {
participantRow(t, "Editor", cd, email, phone, url);
}
}
if (authors != null) {
for (BaseWrapper cd : reviewers.getValues()) {
participantRow(t, "Reviewer", cd, email, phone, url);
}
}
if (authors != null) {
for (BaseWrapper cd : endorsers.getValues()) {
participantRow(t, "Endorser", cd, email, phone, url);
}
}
}
PropertyWrapper artifacts = lib.getChildByName("relatedArtifact");
if (artifacts != null && artifacts.hasValues()) {
x.h2().tx("Related Artifacts");
XhtmlNode t = x.table("grid");
boolean label = false;
boolean display = false;
boolean citation = false;
for (BaseWrapper ra : artifacts.getValues()) {
label = label || ra.has("label");
display = display || ra.has("display");
citation = citation || ra.has("citation");
}
for (BaseWrapper ra : artifacts.getValues()) {
renderArtifact(t, ra, lib, label, display, citation);
}
}
PropertyWrapper parameters = lib.getChildByName("parameter");
if (parameters != null && parameters.hasValues()) {
x.h2().tx("Parameters");
XhtmlNode t = x.table("grid");
boolean doco = false;
for (BaseWrapper p : parameters.getValues()) {
doco = doco || p.has("documentation");
}
for (BaseWrapper p : parameters.getValues()) {
renderParameter(t, p, doco);
}
}
PropertyWrapper dataRequirements = lib.getChildByName("dataRequirement");
if (dataRequirements != null && dataRequirements.hasValues()) {
x.h2().tx("Data Requirements");
for (BaseWrapper p : dataRequirements.getValues()) {
renderDataRequirement(x, (DataRequirement) p.getBase());
}
}
PropertyWrapper contents = lib.getChildByName("content");
if (contents != null) {
x.h2().tx("Contents");
boolean isCql = false;
int counter = 0;
for (BaseWrapper p : contents.getValues()) {
Attachment att = (Attachment) p.getBase();
renderAttachment(x, att, isCql, counter, lib.getId());
isCql = isCql || (att.hasContentType() && att.getContentType().startsWith("text/cql"));
counter++;
}
}
return false;
}
private boolean hasCT(PropertyWrapper prop, String type) throws UnsupportedEncodingException, FHIRException, IOException {
if (prop != null) {
for (BaseWrapper cd : prop.getValues()) {
PropertyWrapper telecoms = cd.getChildByName("telecom");
if (getContactPoint(telecoms, type) != null) {
return true;
}
}
}
return false;
}
private boolean hasCT(List<ContactDetail> list, String type) {
for (ContactDetail cd : list) {
for (ContactPoint t : cd.getTelecom()) {
if (type.equals(t.getSystem().toCode())) {
return true;
}
}
}
return false;
}
public boolean render(XhtmlNode x, Library lib) throws FHIRFormatError, DefinitionException, IOException {
if (lib.hasAuthor() || lib.hasEditor() || lib.hasReviewer() || lib.hasEndorser()) {
boolean email = hasCT(lib.getAuthor(), "email") || hasCT(lib.getEditor(), "email") || hasCT(lib.getReviewer(), "email") || hasCT(lib.getEndorser(), "email");
boolean phone = hasCT(lib.getAuthor(), "phone") || hasCT(lib.getEditor(), "phone") || hasCT(lib.getReviewer(), "phone") || hasCT(lib.getEndorser(), "phone");
boolean url = hasCT(lib.getAuthor(), "url") || hasCT(lib.getEditor(), "url") || hasCT(lib.getReviewer(), "url") || hasCT(lib.getEndorser(), "url");
x.h2().tx("Participants");
XhtmlNode t = x.table("grid");
for (ContactDetail cd : lib.getAuthor()) {
participantRow(t, "Author", cd, email, phone, url);
}
for (ContactDetail cd : lib.getEditor()) {
participantRow(t, "Editor", cd, email, phone, url);
}
for (ContactDetail cd : lib.getReviewer()) {
participantRow(t, "Reviewer", cd, email, phone, url);
}
for (ContactDetail cd : lib.getEndorser()) {
participantRow(t, "Endorser", cd, email, phone, url);
}
}
if (lib.hasRelatedArtifact()) {
x.h2().tx("Related Artifacts");
XhtmlNode t = x.table("grid");
boolean label = false;
boolean display = false;
boolean citation = false;
for (RelatedArtifact ra : lib.getRelatedArtifact()) {
label = label || ra.hasLabel();
display = display || ra.hasDisplay();
citation = citation || ra.hasCitation();
}
for (RelatedArtifact ra : lib.getRelatedArtifact()) {
renderArtifact(t, ra, lib, label, display, citation);
}
}
if (lib.hasParameter()) {
x.h2().tx("Parameters");
XhtmlNode t = x.table("grid");
boolean doco = false;
for (ParameterDefinition p : lib.getParameter()) {
doco = doco || p.hasDocumentation();
}
for (ParameterDefinition p : lib.getParameter()) {
renderParameter(t, p, doco);
}
}
if (lib.hasDataRequirement()) {
x.h2().tx("Data Requirements");
for (DataRequirement p : lib.getDataRequirement()) {
renderDataRequirement(x, p);
}
}
if (lib.hasContent()) {
x.h2().tx("Contents");
boolean isCql = false;
int counter = 0;
for (Attachment att : lib.getContent()) {
renderAttachment(x, att, isCql, counter, lib.getId());
isCql = isCql || (att.hasContentType() && att.getContentType().startsWith("text/cql"));
counter++;
}
}
return false;
}
private void renderParameter(XhtmlNode t, BaseWrapper p, boolean doco) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tr = t.tr();
tr.td().tx(p.has("name") ? p.get("name").primitiveValue() : null);
tr.td().tx(p.has("use") ? p.get("use").primitiveValue() : null);
tr.td().tx(p.has("min") ? p.get("min").primitiveValue() : null);
tr.td().tx(p.has("max") ? p.get("max").primitiveValue() : null);
tr.td().tx(p.has("type") ? p.get("type").primitiveValue() : null);
if (doco) {
tr.td().tx(p.has("documentation") ? p.get("documentation").primitiveValue() : null);
}
}
private void renderParameter(XhtmlNode t, ParameterDefinition p, boolean doco) {
XhtmlNode tr = t.tr();
tr.td().tx(p.getName());
tr.td().tx(p.getUse().getDisplay());
tr.td().tx(p.getMin());
tr.td().tx(p.getMax());
tr.td().tx(p.getType().getDisplay());
if (doco) {
tr.td().tx(p.getDocumentation());
}
}
private void renderArtifact(XhtmlNode t, BaseWrapper ra, ResourceWrapper lib, boolean label, boolean display, boolean citation) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tr = t.tr();
tr.td().tx(ra.has("type") ? ra.get("type").primitiveValue() : null);
if (label) {
tr.td().tx(ra.has("label") ? ra.get("label").primitiveValue() : null);
}
if (display) {
tr.td().tx(ra.has("display") ? ra.get("display").primitiveValue() : null);
}
if (citation) {
tr.td().markdown(ra.has("citation") ? ra.get("citation").primitiveValue() : null, "Citation");
}
if (ra.has("resource")) {
renderCanonical(lib, tr.td(), ra.get("resource").primitiveValue());
} else {
tr.td().tx(ra.has("url") ? ra.get("url").primitiveValue() : null);
}
}
private void renderArtifact(XhtmlNode t, RelatedArtifact ra, Resource lib, boolean label, boolean display, boolean citation) throws IOException {
XhtmlNode tr = t.tr();
tr.td().tx(ra.getType().getDisplay());
if (label) {
tr.td().tx(ra.getLabel());
}
if (display) {
tr.td().tx(ra.getDisplay());
}
if (citation) {
tr.td().markdown(ra.getCitation(), "Citation");
}
if (ra.hasResource()) {
renderCanonical(lib, tr.td(), ra.getResource());
} else {
tr.td().tx(ra.getUrl());
}
}
private void participantRow(XhtmlNode t, String label, BaseWrapper cd, boolean email, boolean phone, boolean url) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tr = t.tr();
tr.td().tx(label);
tr.td().tx(cd.get("name") != null ? cd.get("name").primitiveValue() : null);
PropertyWrapper telecoms = cd.getChildByName("telecom");
if (email) {
renderContactPoint(tr.td(), getContactPoint(telecoms, "email"));
}
if (phone) {
renderContactPoint(tr.td(), getContactPoint(telecoms, "phone"));
}
if (url) {
renderContactPoint(tr.td(), getContactPoint(telecoms, "url"));
}
}
private ContactPoint getContactPoint(PropertyWrapper telecoms, String value) throws UnsupportedEncodingException, FHIRException, IOException {
for (BaseWrapper t : telecoms.getValues()) {
if (t.has("system")) {
String system = t.get("system").primitiveValue();
if (value.equals(system)) {
return (ContactPoint) t.getBase();
}
}
}
return null;
}
private void participantRow(XhtmlNode t, String label, ContactDetail cd, boolean email, boolean phone, boolean url) {
XhtmlNode tr = t.tr();
tr.td().tx(label);
tr.td().tx(cd.getName());
if (email) {
renderContactPoint(tr.td(), cd.getEmail());
}
if (phone) {
renderContactPoint(tr.td(), cd.getPhone());
}
if (url) {
renderContactPoint(tr.td(), cd.getUrl());
}
}
public void describe(XhtmlNode x, Library lib) {
x.tx(display(lib));
}
public String display(Library lib) {
return lib.present();
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return ((Library) r).present();
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
if (r.has("title")) {
return r.children("title").get(0).getBase().primitiveValue();
}
return "??";
}
private void renderAttachment(XhtmlNode x, Attachment att, boolean noShowData, int counter, String baseId) {
boolean ref = !att.hasData() && att.hasUrl();
if (ref) {
XhtmlNode p = x.para();
if (att.hasTitle()) {
p.tx(att.getTitle());
p.tx(": ");
}
p.code().ah(att.getUrl()).tx(att.getUrl());
p.tx(" (");
p.code().tx(att.getContentType());
p.tx(lang(att));
p.tx(")");
} else if (!att.hasData()) {
XhtmlNode p = x.para();
if (att.hasTitle()) {
p.tx(att.getTitle());
p.tx(": ");
}
p.code().tx("No Content");
p.tx(" (");
p.code().tx(att.getContentType());
p.tx(lang(att));
p.tx(")");
} else {
String txt = getText(att);
if (isImage(att.getContentType())) {
XhtmlNode p = x.para();
if (att.hasTitle()) {
p.tx(att.getTitle());
p.tx(": (");
p.code().tx(att.getContentType());
p.tx(lang(att));
p.tx(")");
}
else {
p.code().tx(att.getContentType()+lang(att));
}
if (att.getData().length < LibraryRenderer.DATA_IMG_SIZE_CUTOFF) {
x.img("data: "+att.getContentType()+">;base64,"+b64(att.getData()));
} else {
String filename = "Library-"+baseId+(counter == 0 ? "" : "-"+Integer.toString(counter))+"."+imgExtension(att.getContentType());
x.img(filename);
}
} else if (txt != null && !noShowData) {
XhtmlNode p = x.para();
if (att.hasTitle()) {
p.tx(att.getTitle());
p.tx(": (");
p.code().tx(att.getContentType());
p.tx(lang(att));
p.tx(")");
}
else {
p.code().tx(att.getContentType()+lang(att));
}
String prismCode = determinePrismCode(att);
if (prismCode != null) {
x.pre().code().setAttribute("class", "language-"+prismCode).tx(txt);
} else {
x.pre().code().tx(txt);
}
} else {
XhtmlNode p = x.para();
if (att.hasTitle()) {
p.tx(att.getTitle());
p.tx(": ");
}
p.code().tx("Content not shown - (");
p.code().tx(att.getContentType());
p.tx(lang(att));
p.tx(", size = "+Utilities.describeSize(att.getData().length)+")");
}
}
}
private String imgExtension(String contentType) {
if (contentType != null && contentType.startsWith("image/")) {
if (contentType.startsWith("image/png")) {
return "png";
}
if (contentType.startsWith("image/jpeg")) {
return "jpg";
}
}
return null;
}
private String b64(byte[] data) {
byte[] encodeBase64 = Base64.encodeBase64(data);
return new String(encodeBase64);
}
private boolean isImage(String contentType) {
return imgExtension(contentType) != null;
}
private String lang(Attachment att) {
if (att.hasLanguage()) {
return ", language = "+describeLang(att.getLanguage());
}
return "";
}
private String getText(Attachment att) {
try {
try {
String src = new String(att.getData(), "UTF-8");
if (checkString(src)) {
return src;
}
} catch (Exception e) {
// ignore
}
try {
String src = new String(att.getData(), "UTF-16");
if (checkString(src)) {
return src;
}
} catch (Exception e) {
// ignore
}
try {
String src = new String(att.getData(), "ASCII");
if (checkString(src)) {
return src;
}
} catch (Exception e) {
// ignore
}
return null;
} catch (Exception e) {
return null;
}
}
public boolean checkString(String src) {
for (char ch : src.toCharArray()) {
if (ch < ' ' && ch != '\r' && ch != '\n' && ch != '\t') {
return false;
}
}
return true;
}
private String determinePrismCode(Attachment att) {
if (att.hasContentType()) {
String ct = att.getContentType();
if (ct.contains(";")) {
ct = ct.substring(0, ct.indexOf(";"));
}
switch (ct) {
case "text/html" : return "html";
case "text/xml" : return "xml";
case "application/xml" : return "xml";
case "text/markdown" : return "markdown";
case "application/js" : return "JavaScript";
case "application/css" : return "css";
case "text/x-csrc" : return "c";
case "text/x-csharp" : return "csharp";
case "text/x-c++src" : return "cpp";
case "application/graphql" : return "graphql";
case "application/x-java" : return "java";
case "application/json" : return "json";
case "text/json" : return "json";
case "application/liquid" : return "liquid";
case "text/x-pascal" : return "pascal";
case "text/x-python" : return "python";
case "text/x-rsrc" : return "r";
case "text/x-ruby" : return "ruby";
case "text/x-sas" : return "sas";
case "text/x-sql" : return "sql";
case "application/typescript" : return "typescript";
case "text/cql" : return "sql"; // not that bad...
}
if (att.getContentType().contains("json+") || att.getContentType().contains("+json")) {
return "json";
}
if (att.getContentType().contains("xml+") || att.getContentType().contains("+xml")) {
return "xml";
}
}
return null;
}
}

View File

@ -392,6 +392,8 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
} else if (e instanceof DataRequirement) { } else if (e instanceof DataRequirement) {
DataRequirement p = (DataRequirement) e; DataRequirement p = (DataRequirement) e;
renderDataRequirement(x, p); renderDataRequirement(x, p);
} else if (e instanceof PrimitiveType) {
x.tx(((PrimitiveType) e).primitiveValue());
} else if (e instanceof ElementDefinition) { } else if (e instanceof ElementDefinition) {
x.tx("todo-bundle"); x.tx("todo-bundle");
} else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta)) { } else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta)) {

View File

@ -59,6 +59,9 @@ public class RendererFactory {
if ("Encounter".equals(resourceName)) { if ("Encounter".equals(resourceName)) {
return new EncounterRenderer(context); return new EncounterRenderer(context);
} }
if ("Library".equals(resourceName)) {
return new LibraryRenderer(context);
}
if ("List".equals(resourceName)) { if ("List".equals(resourceName)) {
return new ListRenderer(context); return new ListRenderer(context);
} }
@ -102,6 +105,9 @@ public class RendererFactory {
if ("List".equals(resource.getName())) { if ("List".equals(resource.getName())) {
return new ListRenderer(context); return new ListRenderer(context);
} }
if ("Library".equals(resource.getName())) {
return new LibraryRenderer(context);
}
if ("DiagnosticReport".equals(resource.getName())) { if ("DiagnosticReport".equals(resource.getName())) {
return new DiagnosticReportRenderer(context); return new DiagnosticReportRenderer(context);
} }

View File

@ -125,6 +125,44 @@ public abstract class ResourceRenderer extends DataRenderer {
} }
} }
public void renderCanonical(Resource res, XhtmlNode x, String url) throws UnsupportedEncodingException, IOException {
ResourceWrapper rw = new ResourceWrapperDirect(this.context, res);
renderCanonical(rw, x, url);
}
public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url) throws UnsupportedEncodingException, IOException {
renderCanonical(rw, x, url, true);
}
public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url, boolean allowLinks) throws UnsupportedEncodingException, IOException {
if (url == null) {
return;
}
Resource target = context.getWorker().fetchResource(Resource.class, url);
if (target == null || !(target instanceof CanonicalResource)) {
x.code().tx(url);
} else {
CanonicalResource cr = (CanonicalResource) target;
if (url.contains("|")) {
if (target.hasUserData("path")) {
x.ah(target.getUserString("path")).tx(cr.present()+" (version "+cr.getVersion()+")");
} else {
url = url.substring(0, url.indexOf("|"));
x.code().tx(url);
x.tx(": "+cr.present()+" (version "+cr.getVersion()+")");
}
} else {
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());
}
}
}
}
public void renderReference(Resource res, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException { public void renderReference(Resource res, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException {
ResourceWrapper rw = new ResourceWrapperDirect(this.context, res); ResourceWrapper rw = new ResourceWrapperDirect(this.context, res);
renderReference(rw, x, r); renderReference(rw, x, r);

View File

@ -52,6 +52,7 @@ public class BaseWrappers {
public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException; public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException;
public void injectNarrative(XhtmlNode x, NarrativeStatus status) throws IOException; public void injectNarrative(XhtmlNode x, NarrativeStatus status) throws IOException;
public BaseWrapper root(); public BaseWrapper root();
public PropertyWrapper getChildByName(String tail);
public StructureDefinition getDefinition(); public StructureDefinition getDefinition();
public boolean hasNarrative(); public boolean hasNarrative();
} }

View File

@ -362,6 +362,16 @@ public class DOMWrappers {
public String fhirType() { public String fhirType() {
return wrapped.getNodeName(); return wrapped.getNodeName();
} }
@Override
public PropertyWrapper getChildByName(String name) {
for (PropertyWrapper p : children())
if (p.getName().equals(name))
return p;
return null;
}
} }
} }

View File

@ -267,6 +267,16 @@ public class DirectWrappers {
public String fhirType() { public String fhirType() {
return wrapped.fhirType(); return wrapped.fhirType();
} }
@Override
public PropertyWrapper getChildByName(String name) {
Property p = wrapped.getChildByName(name);
if (p == null)
return null;
else
return new PropertyWrapperDirect(context, p);
}
} }
} }

View File

@ -246,7 +246,16 @@ public class ElementWrappers {
public String fhirType() { public String fhirType() {
return wrapped.fhirType(); return wrapped.fhirType();
} }
}
@Override
public PropertyWrapper getChildByName(String name) {
for (PropertyWrapper p : children())
if (p.getName().equals(name))
return p;
return null;
}
}
public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper { public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper {

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -90,4 +90,49 @@ public class MimeType {
return source; return source;
} }
public static String getExtension(String mimeType) {
MimeType mt = new MimeType(mimeType);
return mt.getExtension();
}
public String getExtension() {
switch (base) {
case "text/html" : return "html";
case "text/xml" : return "xml";
case "application/xml" : return "xml";
case "text/markdown" : return "md";
case "application/js" : return "js";
case "application/css" : return "css";
case "text/x-csrc" : return "c";
case "text/x-csharp" : return "cs";
case "text/x-c++src" : return "c";
case "application/graphql" : return "graphql";
case "application/x-java" : return "java";
case "application/json" : return "json";
case "text/json" : return "json";
case "application/liquid" : return "liquid";
case "text/x-pascal" : return "pas";
case "text/x-python" : return "py";
case "text/x-rsrc" : return "r";
case "text/x-ruby" : return "ruby";
case "text/x-sas" : return "sas";
case "text/x-sql" : return "sql";
case "application/typescript" : return "ts";
case "text/cql": return "cql";
case "image/png": return "png";
case "image/gif": return "gif";
case "image/jpeg": return "jpg";
}
if (base.contains("xml+") || base.contains("+xml")) {
return "xml";
}
if (base.contains("json+") || base.contains("+json")) {
return "json";
}
if (base.contains("turtle+") || base.contains("+turtle")) {
return "ttl";
}
return null;
}
} }

View File

@ -25,7 +25,7 @@ import com.google.gson.JsonObject;
public class PackageHacker { public class PackageHacker {
public static void main(String[] args) throws FileNotFoundException, IOException { public static void main(String[] args) throws FileNotFoundException, IOException {
new PackageHacker().edit("M:\\web\\hl7.org\\fhir\\uv\\cdisc-lab\\package.tgz"); new PackageHacker().edit("M:\\web\\hl7.org\\fhir\\us\\carin-rtpbc\\package.tgz");
} }
private void edit(String name) throws FileNotFoundException, IOException { private void edit(String name) throws FileNotFoundException, IOException {
@ -58,9 +58,9 @@ public class PackageHacker {
private void change(JsonObject npm, Map<String, byte[]> content) throws FileNotFoundException, IOException { private void change(JsonObject npm, Map<String, byte[]> content) throws FileNotFoundException, IOException {
fixVersions(npm); fixVersions(npm);
npm.remove("url"); npm.remove("url");
npm.addProperty("url", "http://hl7.org/fhir/uv/cdisc-lab/STU1"); npm.addProperty("url", "http://hl7.org/fhir/us/carin-rtpbc/STU1");
npm.remove("name"); // npm.remove("name");
npm.addProperty("name", "hl7.fhir.uv.cdisc-lab"); // npm.addProperty("name", "hl7.fhir.uv.smart-app-launch");
// npm.remove("canonical"); // npm.remove("canonical");
// npm.addProperty("canonical", "http://hl7.org/fhir/us/davinci-drug-formulary"); // npm.addProperty("canonical", "http://hl7.org/fhir/us/davinci-drug-formulary");
//// npm.remove("description"); //// npm.remove("description");
@ -70,7 +70,7 @@ public class PackageHacker {
// npm.remove("dependencies"); // npm.remove("dependencies");
// JsonObject dep = new JsonObject(); // JsonObject dep = new JsonObject();
// npm.add("dependencies", dep); // npm.add("dependencies", dep);
// dep.addProperty("hl7.fhir.r4.core", "4.0.1"); // dep.addProperty("hl7.fhir.r3.core", "3.0.1");
// dep.addProperty("hl7.fhir.r4.examples", "4.0.1"); // dep.addProperty("hl7.fhir.r4.examples", "4.0.1");
// dep.addProperty("hl7.fhir.r4.expansions", "4.0.1"); // dep.addProperty("hl7.fhir.r4.expansions", "4.0.1");
// dep.addProperty("hl7.fhir.r4.elements", "4.0.1"); // dep.addProperty("hl7.fhir.r4.elements", "4.0.1");
@ -80,7 +80,7 @@ public class PackageHacker {
npm.remove("fhirVersions"); npm.remove("fhirVersions");
JsonArray a = new JsonArray(); JsonArray a = new JsonArray();
npm.add("fhirVersions", a); npm.add("fhirVersions", a);
a.add("4.5.0"); a.add("3.0.1");
} }
private void setProperty(JsonObject npm, String name, String value) { private void setProperty(JsonObject npm, String name, String value) {

View File

@ -38,9 +38,13 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.instance.model.api.IBaseXhtml; import org.hl7.fhir.instance.model.api.IBaseXhtml;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
import org.hl7.fhir.utilities.i18n.I18nConstants; import org.hl7.fhir.utilities.i18n.I18nConstants;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
@ -796,6 +800,21 @@ public class XhtmlNode implements IBaseXhtml {
} }
public void markdown(String md, String source) throws IOException {
if (md != null) {
String s = new MarkDownProcessor(Dialect.COMMON_MARK).process(md, source);
XhtmlParser p = new XhtmlParser();
XhtmlNode m;
try {
m = p.parse("<div>"+s+"</div>", "div");
} catch (org.hl7.fhir.exceptions.FHIRFormatError e) {
throw new FHIRFormatError(e.getMessage(), e);
}
getChildNodes().addAll(m.getChildNodes());
}
}

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ca.uhn.hapi.fhir</groupId> <groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId> <artifactId>org.hl7.fhir.core</artifactId>
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

View File

@ -13,11 +13,11 @@
each other. It is fine to bump the point version of this POM without affecting each other. It is fine to bump the point version of this POM without affecting
HAPI FHIR. HAPI FHIR.
--> -->
<version>5.1.12-SNAPSHOT</version> <version>5.1.13-SNAPSHOT</version>
<properties> <properties>
<hapi_fhir_version>5.1.0</hapi_fhir_version> <hapi_fhir_version>5.1.0</hapi_fhir_version>
<validator_test_case_version>1.1.42-SNAPSHOT</validator_test_case_version> <validator_test_case_version>1.1.43-SNAPSHOT</validator_test_case_version>
<junit_jupiter_version>5.6.2</junit_jupiter_version> <junit_jupiter_version>5.6.2</junit_jupiter_version>
<maven_surefire_version>3.0.0-M4</maven_surefire_version> <maven_surefire_version>3.0.0-M4</maven_surefire_version>
<jacoco_version>0.8.5</jacoco_version> <jacoco_version>0.8.5</jacoco_version>