Merge pull request #351 from hapifhir/gg-library-rendering
GG library rendering
This commit is contained in:
commit
233cf71630
|
@ -0,0 +1,11 @@
|
|||
Validator:
|
||||
* Fix handling resources in bundles when type is profiled
|
||||
* Prevent NPE resolving resource in batch
|
||||
* fix value set validation for primitive types when an expansion is provided, and the code system is not known
|
||||
|
||||
Other Changes:
|
||||
* Package Subsystem - Support wildcars for patch version
|
||||
* Renderer: Don't make a column for definitions in a code system if there are none
|
||||
* Renderer: special case support for fr-CA language
|
||||
* Renderer: Prevent NPE when auto-generating narrative and an illegal resource type is encountered
|
||||
* FHIRPath Engine: correction for allowing boolean conversion of primitive types
|
|
@ -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;
|
||||
}
|
|
@ -35,6 +35,7 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
import java.util.List;
|
||||
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.instance.model.api.IBaseDatatypeElement;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -184,8 +184,18 @@ public class DataRenderer extends Renderer {
|
|||
lang = lang.substring(0, lang.indexOf("-"));
|
||||
}
|
||||
for (ConceptReferenceComponent cc : v.getCompose().getIncludeFirstRep().getConcept()) {
|
||||
if (cc.getCode().equals(lang) || cc.getCode().startsWith(lang+"-"))
|
||||
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) {
|
||||
|
@ -689,9 +699,63 @@ public class DataRenderer extends Renderer {
|
|||
}
|
||||
|
||||
protected void renderContactPoint(XhtmlNode x, ContactPoint contact) {
|
||||
if (contact != null) {
|
||||
if (!contact.hasSystem()) {
|
||||
x.addText(displayContactPoint(contact));
|
||||
} else {
|
||||
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().replace(" ", "")).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 displayContactPoint(XhtmlNode p, ContactPoint c) {
|
||||
if (c != null) {
|
||||
if (c.getSystem() == ContactPointSystem.PHONE) {
|
||||
p.tx("Phone: "+c.getValue());
|
||||
} else if (c.getSystem() == ContactPointSystem.FAX) {
|
||||
p.tx("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, ContactPoint c) {
|
||||
if (c.getSystem() == ContactPointSystem.PHONE) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -392,6 +392,8 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
} else if (e instanceof DataRequirement) {
|
||||
DataRequirement p = (DataRequirement) e;
|
||||
renderDataRequirement(x, p);
|
||||
} else if (e instanceof PrimitiveType) {
|
||||
x.tx(((PrimitiveType) e).primitiveValue());
|
||||
} else if (e instanceof ElementDefinition) {
|
||||
x.tx("todo-bundle");
|
||||
} else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta)) {
|
||||
|
@ -486,7 +488,11 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
renderAddress(x, (Address) e);
|
||||
return true;
|
||||
} else if (e instanceof ContactPoint) {
|
||||
if (allowLinks) {
|
||||
renderContactPoint(x, (ContactPoint) e);
|
||||
} else {
|
||||
displayContactPoint(x, (ContactPoint) e);
|
||||
}
|
||||
return true;
|
||||
} else if (e instanceof Timing) {
|
||||
renderTiming(x, (Timing) e);
|
||||
|
@ -528,7 +534,11 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
boolean first = true;
|
||||
for (ContactPoint c : cd.getTelecom()) {
|
||||
if (first) first = false; else x.tx(",");
|
||||
if (allowLinks) {
|
||||
renderContactPoint(x, c);
|
||||
} else {
|
||||
displayContactPoint(x, c);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (e instanceof Range) {
|
||||
|
|
|
@ -59,6 +59,9 @@ public class RendererFactory {
|
|||
if ("Encounter".equals(resourceName)) {
|
||||
return new EncounterRenderer(context);
|
||||
}
|
||||
if ("Library".equals(resourceName)) {
|
||||
return new LibraryRenderer(context);
|
||||
}
|
||||
if ("List".equals(resourceName)) {
|
||||
return new ListRenderer(context);
|
||||
}
|
||||
|
@ -102,6 +105,9 @@ public class RendererFactory {
|
|||
if ("List".equals(resource.getName())) {
|
||||
return new ListRenderer(context);
|
||||
}
|
||||
if ("Library".equals(resource.getName())) {
|
||||
return new LibraryRenderer(context);
|
||||
}
|
||||
if ("DiagnosticReport".equals(resource.getName())) {
|
||||
return new DiagnosticReportRenderer(context);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
ResourceWrapper rw = new ResourceWrapperDirect(this.context, res);
|
||||
renderReference(rw, x, r);
|
||||
|
|
|
@ -52,6 +52,7 @@ public class BaseWrappers {
|
|||
public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException;
|
||||
public void injectNarrative(XhtmlNode x, NarrativeStatus status) throws IOException;
|
||||
public BaseWrapper root();
|
||||
public PropertyWrapper getChildByName(String tail);
|
||||
public StructureDefinition getDefinition();
|
||||
public boolean hasNarrative();
|
||||
}
|
||||
|
|
|
@ -362,6 +362,16 @@ public class DOMWrappers {
|
|||
public String fhirType() {
|
||||
return wrapped.getNodeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyWrapper getChildByName(String name) {
|
||||
for (PropertyWrapper p : children())
|
||||
if (p.getName().equals(name))
|
||||
return p;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -267,6 +267,16 @@ public class DirectWrappers {
|
|||
public String 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -246,8 +246,17 @@ public class ElementWrappers {
|
|||
public String 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 {
|
||||
|
||||
private StructureDefinition structure;
|
||||
|
|
|
@ -90,4 +90,49 @@ public class MimeType {
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -47,6 +47,8 @@ import java.math.RoundingMode;
|
|||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
|
@ -320,13 +322,13 @@ public class Utilities {
|
|||
destFile.createNewFile();
|
||||
}
|
||||
|
||||
FileChannel source = null;
|
||||
FileChannel destination = null;
|
||||
FileInputStream source = null;
|
||||
FileOutputStream destination = null;
|
||||
|
||||
try {
|
||||
source = new FileInputStream(sourceFile).getChannel();
|
||||
destination = new FileOutputStream(destFile).getChannel();
|
||||
destination.transferFrom(source, 0, source.size());
|
||||
source = new FileInputStream(sourceFile);
|
||||
destination = new FileOutputStream(destFile);
|
||||
destination.getChannel().transferFrom(source.getChannel(), 0, source.getChannel().size());
|
||||
} finally {
|
||||
if (source != null) {
|
||||
source.close();
|
||||
|
|
|
@ -25,7 +25,7 @@ import com.google.gson.JsonObject;
|
|||
public class PackageHacker {
|
||||
|
||||
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 {
|
||||
|
@ -58,9 +58,9 @@ public class PackageHacker {
|
|||
private void change(JsonObject npm, Map<String, byte[]> content) throws FileNotFoundException, IOException {
|
||||
fixVersions(npm);
|
||||
npm.remove("url");
|
||||
npm.addProperty("url", "http://hl7.org/fhir/uv/cdisc-lab/STU1");
|
||||
npm.remove("name");
|
||||
npm.addProperty("name", "hl7.fhir.uv.cdisc-lab");
|
||||
npm.addProperty("url", "http://hl7.org/fhir/us/carin-rtpbc/STU1");
|
||||
// npm.remove("name");
|
||||
// npm.addProperty("name", "hl7.fhir.uv.smart-app-launch");
|
||||
// npm.remove("canonical");
|
||||
// npm.addProperty("canonical", "http://hl7.org/fhir/us/davinci-drug-formulary");
|
||||
//// npm.remove("description");
|
||||
|
@ -70,7 +70,7 @@ public class PackageHacker {
|
|||
// npm.remove("dependencies");
|
||||
// JsonObject dep = new JsonObject();
|
||||
// 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.expansions", "4.0.1");
|
||||
// dep.addProperty("hl7.fhir.r4.elements", "4.0.1");
|
||||
|
@ -80,7 +80,7 @@ public class PackageHacker {
|
|||
npm.remove("fhirVersions");
|
||||
JsonArray a = new JsonArray();
|
||||
npm.add("fhirVersions", a);
|
||||
a.add("4.5.0");
|
||||
a.add("3.0.1");
|
||||
}
|
||||
|
||||
private void setProperty(JsonObject npm, String name, String value) {
|
||||
|
|
|
@ -38,9 +38,13 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
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.MarkDownProcessor.Dialect;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
|
||||
|
@ -86,6 +90,9 @@ public class XhtmlNode implements IBaseXhtml {
|
|||
private List<XhtmlNode> childNodes = new ArrayList<XhtmlNode>();
|
||||
private String content;
|
||||
private boolean notPretty;
|
||||
private boolean inPara;
|
||||
private boolean inLink;
|
||||
|
||||
|
||||
public XhtmlNode() {
|
||||
super();
|
||||
|
@ -140,7 +147,7 @@ public class XhtmlNode implements IBaseXhtml {
|
|||
return this;
|
||||
}
|
||||
|
||||
public void validate(List<String> errors, String path, boolean inResource, boolean inPara) {
|
||||
public void validate(List<String> errors, String path, boolean inResource, boolean inPara, boolean inLink) {
|
||||
if (nodeType == NodeType.Element || nodeType == NodeType.Document) {
|
||||
path = Utilities.noString(path) ? name : path+"/"+name;
|
||||
if (inResource) {
|
||||
|
@ -168,13 +175,19 @@ public class XhtmlNode implements IBaseXhtml {
|
|||
if (inPara && Utilities.existsInList(name, "div", "blockquote", "table", "ol", "ul", "p")) {
|
||||
errors.add("Error at "+path+": Found "+name+" inside an html paragraph");
|
||||
}
|
||||
if (inLink && Utilities.existsInList(name, "a")) {
|
||||
errors.add("Error at "+path+": Found an <a> inside an <a> paragraph");
|
||||
}
|
||||
|
||||
if (childNodes != null) {
|
||||
if ("p".equals(name)) {
|
||||
inPara = true;
|
||||
}
|
||||
if ("a".equals(name)) {
|
||||
inLink = true;
|
||||
}
|
||||
for (XhtmlNode child : childNodes) {
|
||||
child.validate(errors, path, inResource, inPara);
|
||||
child.validate(errors, path, inResource, inPara, inLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,8 +200,20 @@ public class XhtmlNode implements IBaseXhtml {
|
|||
throw new Error("Wrong node type - node is "+nodeType.toString()+" ('"+getName()+"/"+getContent()+"')");
|
||||
}
|
||||
|
||||
// if (inPara && name.equals("p")) {
|
||||
// throw new FHIRException("nested Para");
|
||||
// }
|
||||
// if (inLink && name.equals("a")) {
|
||||
// throw new FHIRException("Nested Link");
|
||||
// }
|
||||
XhtmlNode node = new XhtmlNode(NodeType.Element);
|
||||
node.setName(name);
|
||||
if (inPara || name.equals("p")) {
|
||||
node.inPara = true;
|
||||
}
|
||||
if (inLink || name.equals("a")) {
|
||||
node.inLink = true;
|
||||
}
|
||||
childNodes.add(node);
|
||||
return node;
|
||||
}
|
||||
|
@ -199,6 +224,12 @@ public class XhtmlNode implements IBaseXhtml {
|
|||
if (!(nodeType == NodeType.Element || nodeType == NodeType.Document))
|
||||
throw new Error("Wrong node type. is "+nodeType.toString());
|
||||
XhtmlNode node = new XhtmlNode(NodeType.Element);
|
||||
if (inPara || name.equals("p")) {
|
||||
node.inPara = true;
|
||||
}
|
||||
if (inLink || name.equals("a")) {
|
||||
node.inLink = true;
|
||||
}
|
||||
node.setName(name);
|
||||
childNodes.add(index, node);
|
||||
return node;
|
||||
|
@ -796,6 +827,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -17,7 +17,7 @@
|
|||
|
||||
<properties>
|
||||
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
||||
<validator_test_case_version>1.1.42</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>
|
||||
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
||||
<jacoco_version>0.8.5</jacoco_version>
|
||||
|
|
Loading…
Reference in New Issue