Merge pull request #290 from hapifhir/gg-work-5018
various fixes for 5.0.18
This commit is contained in:
commit
389ad1c180
|
@ -0,0 +1,16 @@
|
|||
Validator Fixes:
|
||||
* better validation of external references. Note: this is a potentially significant change: things that were called ok before may not be now, and things that were not ok before may become so, depending on the interplay between this and auto-load, further work may be needed here
|
||||
* Support better validation of version specific profiles in meta.profile. This may also find new errors that were not previously being found
|
||||
* Support auto-determination of the version of FHIR to use when using the java validator
|
||||
* auto-load packages from the package server when references to profiles etc are encountered
|
||||
* look for references inside other parameters in Parameters resource
|
||||
* no validation for CanonicalResource.url (further work needed)
|
||||
|
||||
Other Code changes:
|
||||
* Rendering: add rendering for Parameters resources
|
||||
* Rendering: refactor of resource resolution code to support Parameters
|
||||
* General clean up of rendering consistency & implement additional details when rendering (including patient summary)
|
||||
* Rendering: major overhaul of DiagnosticReport rendering
|
||||
* Fix NPE bug in value set comparison
|
||||
|
||||
|
|
@ -154,7 +154,7 @@ public class CodeSystemComparer extends CanonicalResourceComparer {
|
|||
|
||||
|
||||
private void compareConcepts(List<ConceptDefinitionComponent> left, List<ConceptDefinitionComponent> right, StructuralMatch<ConceptDefinitionComponent> combined,
|
||||
List<ConceptDefinitionComponent> union, List<ConceptDefinitionComponent> intersection, CodeSystem csU, CodeSystem csI, CodeSystemComparison res, String path) {
|
||||
List<ConceptDefinitionComponent> union, List<ConceptDefinitionComponent> intersection, CodeSystem csU, CodeSystem csI, CodeSystemComparison res, String path) {
|
||||
List<ConceptDefinitionComponent> matchR = new ArrayList<>();
|
||||
for (ConceptDefinitionComponent l : left) {
|
||||
ConceptDefinitionComponent r = findInList(right, l);
|
||||
|
|
|
@ -84,7 +84,12 @@ public class ComparisonRenderer implements IEvaluationContext {
|
|||
first = false;
|
||||
b.append("<tr><td colspan=4><b>"+name+"</b></td></tr>\r\n");
|
||||
}
|
||||
renderComparison(id, comp);
|
||||
try {
|
||||
renderComparison(id, comp);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception rendering "+id+": "+e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
b.append(comp.toTable());
|
||||
//"<li><a href=\""+comp.getId()+".html\">"+Utilities.escapeXml(comp.summary())+"</a></li>\r\n"
|
||||
}
|
||||
|
|
|
@ -210,7 +210,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
private int countMatchesBySystem(List<ConceptSetComponent> list, ConceptSetComponent item) {
|
||||
int c = 0;
|
||||
for (ConceptSetComponent t : list) {
|
||||
if (t.getSystem().equals(item.getSystem())) {
|
||||
if (t.hasSystem() && t.getSystem().equals(item.getSystem())) {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
@ -545,8 +545,7 @@ public class ValueSetComparer extends CanonicalResourceComparer {
|
|||
if (t.hasLeft() && t.hasRight()) {
|
||||
ConceptSetComponent csL = (ConceptSetComponent) t.getLeft();
|
||||
ConceptSetComponent csR = (ConceptSetComponent) t.getRight();
|
||||
// we assume both have systems
|
||||
if (csL.getSystem().equals(csR.getSystem())) {
|
||||
if (csL.hasSystem() && csL.getSystem().equals(csR.getSystem())) {
|
||||
r.getCells().add(gen.new Cell(null, null, csL.getSystem(), null, null).span(2).center());
|
||||
} else {
|
||||
r.getCells().add(gen.new Cell(null, null, csL.getSystem(), null, null).setStyle("background-color: "+COLOR_DIFFERENT));
|
||||
|
|
|
@ -267,6 +267,11 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
|
|||
return res;
|
||||
}
|
||||
|
||||
public static SimpleWorkerContext fromNothing() throws FileNotFoundException, FHIRException, IOException {
|
||||
SimpleWorkerContext res = new SimpleWorkerContext();
|
||||
return res;
|
||||
}
|
||||
|
||||
private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader, ILoadFilter filter, PackageVersion pi) throws IOException, FHIRException {
|
||||
if (name.endsWith(".xml"))
|
||||
loadFromFile(stream, name, loader, filter);
|
||||
|
|
|
@ -37,8 +37,8 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, DomainResource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
return false;
|
||||
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
return render(x, (Bundle) r);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,6 +46,11 @@ public class BundleRenderer extends ResourceRenderer {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, ResourceWrapper b) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
List<BaseWrapper> entries = b.children("entry");
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
|
|||
import org.hl7.fhir.r5.model.CapabilityStatement.SystemRestfulInteraction;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.TypeRestfulInteraction;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
@ -29,7 +30,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (CapabilityStatement) dr);
|
||||
}
|
||||
|
||||
|
@ -149,4 +150,14 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
|
|||
tr.td().addText(value);
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hl7.fhir.r5.model.Coding;
|
|||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Enumeration;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
|
@ -38,7 +39,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
}
|
||||
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (CodeSystem) dr);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.StringType;
|
|||
import org.hl7.fhir.r5.model.CompartmentDefinition;
|
||||
import org.hl7.fhir.r5.model.CompartmentDefinition.CompartmentDefinitionResourceComponent;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
@ -26,7 +27,7 @@ public class CompartmentDefinitionRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (CompartmentDefinition) dr);
|
||||
}
|
||||
|
||||
|
@ -72,4 +73,14 @@ public class CompartmentDefinitionRenderer extends ResourceRenderer {
|
|||
return ((CompartmentDefinition) r).present();
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hl7.fhir.r5.model.ContactDetail;
|
|||
import org.hl7.fhir.r5.model.ContactPoint;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Enumerations.ConceptMapRelationship;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
@ -34,7 +35,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (ConceptMap) dr);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.hl7.fhir.r5.renderers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
|
@ -11,6 +12,7 @@ import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
|
|||
import org.hl7.fhir.r5.model.Address;
|
||||
import org.hl7.fhir.r5.model.Annotation;
|
||||
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;
|
||||
|
@ -23,6 +25,7 @@ import org.hl7.fhir.r5.model.Enumeration;
|
|||
import org.hl7.fhir.r5.model.HumanName;
|
||||
import org.hl7.fhir.r5.model.HumanName.NameUse;
|
||||
import org.hl7.fhir.r5.model.Identifier;
|
||||
import org.hl7.fhir.r5.model.InstantType;
|
||||
import org.hl7.fhir.r5.model.Period;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.Quantity;
|
||||
|
@ -50,7 +53,7 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
|
|||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
||||
|
||||
public class DataRenderer {
|
||||
public class DataRenderer extends Renderer {
|
||||
|
||||
// -- 1. context --------------------------------------------------------------
|
||||
|
||||
|
@ -193,7 +196,6 @@ public class DataRenderer {
|
|||
return lang;
|
||||
}
|
||||
|
||||
|
||||
private boolean isCanonical(String path) {
|
||||
if (!path.endsWith(".url"))
|
||||
return false;
|
||||
|
@ -269,8 +271,19 @@ public class DataRenderer {
|
|||
return "to do";
|
||||
}
|
||||
|
||||
public void render(XhtmlNode x, BaseWrapper type) {
|
||||
x.tx("to do");
|
||||
public void render(XhtmlNode x, BaseWrapper type) {
|
||||
Base base = null;
|
||||
try {
|
||||
base = type.getBase();
|
||||
} catch (FHIRException | IOException e) {
|
||||
x.tx("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("to do: "+base.fhirType());
|
||||
}
|
||||
}
|
||||
|
||||
public void renderBase(XhtmlNode x, Base b) {
|
||||
|
@ -312,6 +325,10 @@ public class DataRenderer {
|
|||
renderSampledData(x, (SampledData) type);
|
||||
} else if (type instanceof Reference) {
|
||||
renderReference(x, (Reference) type);
|
||||
} else if (type instanceof InstantType) {
|
||||
x.tx(((InstantType) type).toHumanDisplay());
|
||||
} else if (type instanceof BaseDateTimeType) {
|
||||
x.tx(((BaseDateTimeType) type).toHumanDisplay());
|
||||
} else if (type.isPrimitive()) {
|
||||
x.tx(type.primitiveValue());
|
||||
} else {
|
||||
|
@ -367,31 +384,37 @@ public class DataRenderer {
|
|||
}
|
||||
|
||||
protected void renderAnnotation(XhtmlNode x, Annotation a, boolean showCodeDetails) throws FHIRException {
|
||||
StringBuilder s = new StringBuilder();
|
||||
if (a.hasAuthor()) {
|
||||
s.append("Author: ");
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (a.hasText()) {
|
||||
b.append(a.getText());
|
||||
}
|
||||
|
||||
if (a.hasAuthorReference())
|
||||
s.append(a.getAuthorReference().getReference());
|
||||
else if (a.hasAuthorStringType())
|
||||
s.append(a.getAuthorStringType().getValue());
|
||||
if (a.hasText() && (a.hasAuthor() || a.hasTimeElement())) {
|
||||
b.append(" (");
|
||||
}
|
||||
|
||||
if (a.hasAuthor()) {
|
||||
b.append("By ");
|
||||
if (a.hasAuthorReference()) {
|
||||
b.append(a.getAuthorReference().getReference());
|
||||
} else if (a.hasAuthorStringType()) {
|
||||
b.append(a.getAuthorStringType().getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (a.hasTimeElement()) {
|
||||
if (s.length() > 0)
|
||||
s.append("; ");
|
||||
|
||||
s.append("Made: ").append(a.getTimeElement().toHumanDisplay());
|
||||
if (b.length() > 0) {
|
||||
b.append(" ");
|
||||
}
|
||||
b.append("@").append(a.getTimeElement().toHumanDisplay());
|
||||
}
|
||||
if (a.hasText() && (a.hasAuthor() || a.hasTimeElement())) {
|
||||
b.append(")");
|
||||
}
|
||||
|
||||
if (a.hasText()) {
|
||||
if (s.length() > 0)
|
||||
s.append("; ");
|
||||
|
||||
s.append("Annotation: ").append(a.getText());
|
||||
}
|
||||
x.addText(s.toString());
|
||||
x.addText(b.toString());
|
||||
}
|
||||
|
||||
public String displayCoding(Coding c) {
|
||||
|
@ -563,11 +586,13 @@ public class DataRenderer {
|
|||
|
||||
if (ii.hasType()) {
|
||||
if (ii.getType().hasText())
|
||||
s = ii.getType().getText()+" = "+s;
|
||||
s = ii.getType().getText()+": "+s;
|
||||
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasDisplay())
|
||||
s = ii.getType().getCoding().get(0).getDisplay()+" = "+s;
|
||||
s = ii.getType().getCoding().get(0).getDisplay()+": "+s;
|
||||
else if (ii.getType().hasCoding() && ii.getType().getCoding().get(0).hasCode())
|
||||
s = lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getCode())+" = "+s;
|
||||
s = lookupCode(ii.getType().getCoding().get(0).getSystem(), ii.getType().getCoding().get(0).getCode())+": "+s;
|
||||
} else {
|
||||
s = "id: "+s;
|
||||
}
|
||||
|
||||
if (ii.hasUse())
|
||||
|
|
|
@ -10,6 +10,8 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.DiagnosticReport;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
|
||||
|
@ -18,6 +20,7 @@ import org.hl7.fhir.r5.renderers.utils.DirectWrappers;
|
|||
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.r5.utils.EOperationOutcome;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
|
@ -38,11 +41,11 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
|
||||
return render(x, (DiagnosticReport) dr);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, ResourceWrapper dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome {
|
||||
XhtmlNode h2 = x.h2();
|
||||
render(h2, getProperty(dr, "code").value());
|
||||
h2.tx(" ");
|
||||
|
@ -56,40 +59,55 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
}
|
||||
h2.tx(") ");
|
||||
}
|
||||
if (dr.has("issued")) {
|
||||
render(h2, getProperty(dr, "issued").value());
|
||||
XhtmlNode tbl = x.table("grid");
|
||||
XhtmlNode tr;
|
||||
if (dr.has("subject")) {
|
||||
tr = tbl.tr();
|
||||
tr.td().tx("Subject");
|
||||
populateSubjectSummary(tr.td(), getProperty(dr, "subject").value());
|
||||
}
|
||||
|
||||
XhtmlNode tbl = x.table("grid");
|
||||
XhtmlNode tr = tbl.tr();
|
||||
XhtmlNode tdl = tr.td();
|
||||
XhtmlNode tdr = tr.td();
|
||||
if (dr.has("subject")) {
|
||||
populateSubjectSummary(tdl, getProperty(dr, "subject").value());
|
||||
DataType eff = null;
|
||||
DataType iss = null;
|
||||
|
||||
if (dr.has("effective[x]")) {
|
||||
tr = tbl.tr();
|
||||
tr.td().tx("When For");
|
||||
eff = (DataType) getProperty(dr, "effective[x]").value().getBase();
|
||||
render(tr.td(), eff);
|
||||
}
|
||||
tdr.b().tx("Report Details");
|
||||
tdr.br();
|
||||
if (dr.has("issued")) {
|
||||
tr = tbl.tr();
|
||||
tr.td().tx("Reported");
|
||||
eff = (DataType) getProperty(dr, "effective[x]").value().getBase();
|
||||
render(tr.td(), getProperty(dr, "issued").value());
|
||||
}
|
||||
|
||||
pw = getProperty(dr, "perfomer");
|
||||
if (valued(pw)) {
|
||||
tdr.addText(Utilities.pluralize("Performer", pw.getValues().size())+":");
|
||||
tr = tbl.tr();
|
||||
tr.td().tx(Utilities.pluralize("Performer", pw.getValues().size()));
|
||||
XhtmlNode tdr = tr.td();
|
||||
for (BaseWrapper v : pw.getValues()) {
|
||||
tdr.tx(" ");
|
||||
render(tdr, v);
|
||||
}
|
||||
tdr.br();
|
||||
}
|
||||
pw = getProperty(dr, "identifier");
|
||||
if (valued(pw)) {
|
||||
tdr.addText(Utilities.pluralize("Identifier", pw.getValues().size())+":");
|
||||
tr = tbl.tr();
|
||||
tr.td().tx(Utilities.pluralize("Identifier", pw.getValues().size())+":");
|
||||
XhtmlNode tdr = tr.td();
|
||||
for (BaseWrapper v : pw.getValues()) {
|
||||
tdr.tx(" ");
|
||||
render(tdr, v);
|
||||
}
|
||||
tdr.br();
|
||||
}
|
||||
pw = getProperty(dr, "request");
|
||||
if (valued(pw)) {
|
||||
tdr.addText(Utilities.pluralize("Request", pw.getValues().size())+":");
|
||||
tr = tbl.tr();
|
||||
tr.td().tx(Utilities.pluralize("Request", pw.getValues().size())+":");
|
||||
XhtmlNode tdr = tr.td();
|
||||
for (BaseWrapper v : pw.getValues()) {
|
||||
tdr.tx(" ");
|
||||
render(tdr, v);
|
||||
|
@ -97,29 +115,35 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
tdr.br();
|
||||
}
|
||||
|
||||
|
||||
x.para().b().tx("Report Details");
|
||||
|
||||
pw = getProperty(dr, "result");
|
||||
if (valued(pw)) {
|
||||
List<ObservationNode> observations = fetchObservations(pw.getValues(), dr);
|
||||
buildObservationsTable(x, observations);
|
||||
buildObservationsTable(x, observations, eff, iss);
|
||||
}
|
||||
|
||||
pw = getProperty(dr, "conclusion");
|
||||
if (valued(pw))
|
||||
render(x.para(), pw.value());
|
||||
|
||||
pw = getProperty(dr, "result");
|
||||
pw = getProperty(dr, "conclusionCode");
|
||||
if (!valued(pw)) {
|
||||
pw = getProperty(dr, "codedDiagnosis");
|
||||
}
|
||||
if (valued(pw)) {
|
||||
XhtmlNode p = x.para();
|
||||
p.b().tx("Coded Diagnoses :");
|
||||
p.b().tx("Coded Conclusions :");
|
||||
XhtmlNode ul = x.ul();
|
||||
for (BaseWrapper v : pw.getValues()) {
|
||||
tdr.tx(" ");
|
||||
render(tdr, v);
|
||||
render(ul.li(), v);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DiagnosticReport dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, DiagnosticReport dr) throws IOException, FHIRException, EOperationOutcome {
|
||||
render(x, new DirectWrappers.ResourceWrapperDirect(this.context, dr));
|
||||
|
||||
return true;
|
||||
|
@ -138,7 +162,12 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
return display((DiagnosticReport) r);
|
||||
}
|
||||
|
||||
private void populateSubjectSummary(XhtmlNode container, BaseWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return "Not done yet";
|
||||
}
|
||||
|
||||
private void populateSubjectSummary(XhtmlNode container, BaseWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome {
|
||||
ResourceWrapper r = fetchResource(subject);
|
||||
if (r == null)
|
||||
container.tx("Unable to get Patient Details");
|
||||
|
@ -148,8 +177,8 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
container.tx("Not done yet");
|
||||
}
|
||||
|
||||
private void generatePatientSummary(XhtmlNode c, ResourceWrapper r) {
|
||||
c.tx("to do");
|
||||
private void generatePatientSummary(XhtmlNode c, ResourceWrapper r) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||
new PatientRenderer(context).describe(c, r);
|
||||
}
|
||||
|
||||
private List<ObservationNode> fetchObservations(List<BaseWrapper> list, ResourceWrapper rw) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
|
@ -171,40 +200,165 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
return res;
|
||||
}
|
||||
|
||||
private void buildObservationsTable(XhtmlNode root, List<ObservationNode> observations) {
|
||||
XhtmlNode tbl = root.table( "none");
|
||||
private void buildObservationsTable(XhtmlNode root, List<ObservationNode> observations, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
XhtmlNode tbl = root.table("grid");
|
||||
boolean refRange = scanObsForRefRange(observations);
|
||||
boolean flags = scanObsForFlags(observations);
|
||||
boolean note = scanObsForNote(observations);
|
||||
boolean effectiveTime = scanObsForEffective(observations, eff);
|
||||
boolean issued = scanObsForIssued(observations, iss);
|
||||
int cs = 2;
|
||||
if (refRange) cs++;
|
||||
if (flags) cs++;
|
||||
if (note) cs++;
|
||||
if (issued) cs++;
|
||||
if (effectiveTime) cs++;
|
||||
XhtmlNode tr = tbl.tr();
|
||||
tr.td().b().tx("Code");
|
||||
tr.td().b().tx("Value");
|
||||
if (refRange) {
|
||||
tr.td().b().tx("Reference Range");
|
||||
}
|
||||
if (flags) {
|
||||
tr.td().b().tx("Flags");
|
||||
}
|
||||
if (note) {
|
||||
tr.td().b().tx("Note");
|
||||
}
|
||||
if (effectiveTime) {
|
||||
tr.td().b().tx("When For");
|
||||
}
|
||||
if (issued) {
|
||||
tr.td().b().tx("Reported");
|
||||
}
|
||||
for (ObservationNode o : observations) {
|
||||
addObservationToTable(tbl, o, 0);
|
||||
addObservationToTable(tbl, o, 0, Integer.toString(cs), refRange, flags, note, effectiveTime, issued, eff, iss);
|
||||
}
|
||||
}
|
||||
|
||||
private void addObservationToTable(XhtmlNode tbl, ObservationNode o, int i) {
|
||||
private boolean scanObsForRefRange(List<ObservationNode> observations) {
|
||||
for (ObservationNode o : observations) {
|
||||
if (o.obs.getResource() != null) {
|
||||
PropertyWrapper pw = getProperty(o.obs.getResource(), "referenceRange");
|
||||
if (valued(pw)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (o.contained != null) {
|
||||
if (scanObsForRefRange(o.contained)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean scanObsForNote(List<ObservationNode> observations) {
|
||||
for (ObservationNode o : observations) {
|
||||
if (o.obs.getResource() != null) {
|
||||
PropertyWrapper pw = getProperty(o.obs.getResource(), "note");
|
||||
if (valued(pw)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (o.contained != null) {
|
||||
if (scanObsForNote(o.contained)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean scanObsForIssued(List<ObservationNode> observations, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
for (ObservationNode o : observations) {
|
||||
if (o.obs.getResource() != null) {
|
||||
PropertyWrapper pw = getProperty(o.obs.getResource(), "issued");
|
||||
if (valued(pw)) {
|
||||
if (!Base.compareDeep(pw.value().getBase(), iss, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.contained != null) {
|
||||
if (scanObsForIssued(o.contained, iss)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean scanObsForEffective(List<ObservationNode> observations, DataType eff) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
for (ObservationNode o : observations) {
|
||||
if (o.obs.getResource() != null) {
|
||||
PropertyWrapper pw = getProperty(o.obs.getResource(), "effective[x]");
|
||||
if (valued(pw)) {
|
||||
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o.contained != null) {
|
||||
if (scanObsForEffective(o.contained, eff)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean scanObsForFlags(List<ObservationNode> observations) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
for (ObservationNode o : observations) {
|
||||
if (o.obs.getResource() != null) {
|
||||
PropertyWrapper pw = getProperty(o.obs.getResource(), "interpretation");
|
||||
if (valued(pw)) {
|
||||
return true;
|
||||
}
|
||||
pw = getProperty(o.obs.getResource(), "status");
|
||||
if (valued(pw)) {
|
||||
if (!pw.value().getBase().primitiveValue().equals("final")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (o.contained != null) {
|
||||
if (scanObsForFlags(o.contained)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addObservationToTable(XhtmlNode tbl, ObservationNode o, int i, String cs, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
XhtmlNode tr = tbl.tr();
|
||||
if (o.obs.getReference() == null) {
|
||||
XhtmlNode td = tr.td().colspan("6");
|
||||
XhtmlNode td = tr.td().colspan(cs);
|
||||
td.i().tx("This Observation could not be resolved");
|
||||
} else {
|
||||
if (o.obs.getResource() != null) {
|
||||
addObservationToTable(tr, o.obs.getResource(), i);
|
||||
addObservationToTable(tr, o.obs.getResource(), i, o.obs.getReference(), refRange, flags, note, effectiveTime, issued, eff, iss);
|
||||
} else {
|
||||
tr.td().tx("Unable to resolve Observation: "+o.obs.getReference());
|
||||
XhtmlNode td = tr.td().colspan(cs);
|
||||
td.i().ah(o.obs.getReference()).tx("Observation");
|
||||
}
|
||||
if (o.contained != null) {
|
||||
for (ObservationNode c : o.contained) {
|
||||
addObservationToTable(tbl, c, i+1);
|
||||
addObservationToTable(tbl, c, i+1, cs, refRange, flags, note, effectiveTime, issued, eff, iss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addObservationToTable(XhtmlNode tr, ResourceWrapper obs, int i) {
|
||||
// TODO Auto-generated method stub
|
||||
private void addObservationToTable(XhtmlNode tr, ResourceWrapper obs, int i, String ref, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
|
||||
// code (+bodysite)
|
||||
XhtmlNode td = tr.td();
|
||||
PropertyWrapper pw = getProperty(obs, "code");
|
||||
if (valued(pw)) {
|
||||
render(td, pw.value());
|
||||
render(td.ah(ref), pw.value());
|
||||
}
|
||||
pw = getProperty(obs, "bodySite");
|
||||
if (valued(pw)) {
|
||||
|
@ -218,23 +372,113 @@ public class DiagnosticReportRenderer extends ResourceRenderer {
|
|||
pw = getProperty(obs, "value[x]");
|
||||
if (valued(pw)) {
|
||||
render(td, pw.value());
|
||||
} else {
|
||||
pw = getProperty(obs, "dataAbsentReason");
|
||||
if (valued(pw)) {
|
||||
XhtmlNode span = td.span("color: maroon", "Error");
|
||||
span.tx("Error: ");
|
||||
render(span.b(), pw.value());
|
||||
}
|
||||
}
|
||||
if (refRange) {
|
||||
// reference range
|
||||
td = tr.td();
|
||||
pw = getProperty(obs, "referenceRange");
|
||||
if (valued(pw)) {
|
||||
boolean first = true;
|
||||
for (BaseWrapper v : pw.getValues()) {
|
||||
if (first) first = false; else td.br();
|
||||
PropertyWrapper pwr = getProperty(v, "type");
|
||||
if (valued(pwr)) {
|
||||
render(td, pwr.value());
|
||||
td.tx(": ");
|
||||
}
|
||||
PropertyWrapper pwt = getProperty(v, "text");
|
||||
if (valued(pwt)) {
|
||||
render(td, pwt.value());
|
||||
} else {
|
||||
PropertyWrapper pwl = getProperty(v, "low");
|
||||
PropertyWrapper pwh = getProperty(v, "high");
|
||||
if (valued(pwl) && valued(pwh)) {
|
||||
render(td, pwl.value());
|
||||
td.tx(" - ");
|
||||
render(td, pwh.value());
|
||||
} else if (valued(pwl)) {
|
||||
td.tx(">");
|
||||
render(td, pwl.value());
|
||||
} else if (valued(pwh)) {
|
||||
td.tx("<");
|
||||
render(td, pwh.value());
|
||||
} else {
|
||||
td.tx("??");
|
||||
}
|
||||
}
|
||||
pwr = getProperty(v, "appliesTo");
|
||||
PropertyWrapper pwrA = getProperty(v, "age");
|
||||
if (valued(pwr) || valued(pwrA)) {
|
||||
boolean firstA = true;
|
||||
td.tx(" for ");
|
||||
if (valued(pwr)) {
|
||||
for (BaseWrapper va : pwr.getValues()) {
|
||||
if (firstA) firstA = false; else td.tx(", ");
|
||||
render(td, va);
|
||||
}
|
||||
}
|
||||
if (valued(pwrA)) {
|
||||
if (firstA) firstA = false; else td.tx(", ");
|
||||
td.tx("Age ");
|
||||
render(td, pwrA.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags) {
|
||||
// flags (status other than F, interpretation, )
|
||||
td = tr.td();
|
||||
boolean first = true;
|
||||
pw = getProperty(obs, "status");
|
||||
if (valued(pw)) {
|
||||
if (!pw.value().getBase().primitiveValue().equals("final")) {
|
||||
if (first) first = false; else td.br();
|
||||
render(td, pw.value());
|
||||
}
|
||||
}
|
||||
pw = getProperty(obs, "interpretation");
|
||||
if (valued(pw)) {
|
||||
for (BaseWrapper v : pw.getValues()) {
|
||||
if (first) first = false; else td.br();
|
||||
render(td, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// units
|
||||
td = tr.td();
|
||||
td.tx("to do");
|
||||
|
||||
// reference range
|
||||
td = tr.td();
|
||||
td.tx("to do");
|
||||
|
||||
// flags (status other than F, interpretation, )
|
||||
td = tr.td();
|
||||
td.tx("to do");
|
||||
|
||||
// issued if different to DR
|
||||
td = tr.td();
|
||||
td.tx("to do");
|
||||
if (note) {
|
||||
td = tr.td();
|
||||
pw = getProperty(obs, "note");
|
||||
if (valued(pw)) {
|
||||
render(td, pw.value());
|
||||
}
|
||||
}
|
||||
if (effectiveTime) {
|
||||
// effective if different to DR
|
||||
td = tr.td();
|
||||
pw = getProperty(obs, "effective[x]");
|
||||
if (valued(pw)) {
|
||||
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
|
||||
render(td, pw.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (issued) {
|
||||
// issued if different to DR
|
||||
td = tr.td();
|
||||
pw = getProperty(obs, "issued");
|
||||
if (valued(pw)) {
|
||||
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
|
||||
render(td, pw.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class EncounterRenderer extends ResourceRenderer {
|
||||
|
@ -15,7 +16,7 @@ public class EncounterRenderer extends ResourceRenderer {
|
|||
super(context);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws UnsupportedEncodingException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws UnsupportedEncodingException, IOException {
|
||||
describe(x, dr);
|
||||
return false;
|
||||
}
|
||||
|
@ -24,4 +25,10 @@ public class EncounterRenderer extends ResourceRenderer {
|
|||
return "Not done yet";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return "Not done yet";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.hl7.fhir.r5.model.DomainResource;
|
|||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class ImplementationGuideRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (ImplementationGuide) dr);
|
||||
}
|
||||
|
||||
|
@ -47,4 +48,14 @@ public class ImplementationGuideRenderer extends ResourceRenderer {
|
|||
return ((ImplementationGuide) r).present();
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class LiquidRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, DomainResource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
LiquidEngine engine = new LiquidEngine(context.getWorker(), context.getServices());
|
||||
XhtmlNode xn;
|
||||
try {
|
||||
|
@ -56,6 +56,16 @@ public class LiquidRenderer extends ResourceRenderer {
|
|||
return "not done yet";
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
LiquidEngine engine = new LiquidEngine(context.getWorker(), context.getServices());
|
||||
|
|
|
@ -29,7 +29,7 @@ public class ListRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (ListResource) dr);
|
||||
}
|
||||
|
||||
|
@ -189,6 +189,14 @@ public class ListRenderer extends ResourceRenderer {
|
|||
return ((ListResource) r).getTitle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
private void shortForRef(XhtmlNode x, Reference ref) throws UnsupportedEncodingException, IOException {
|
||||
ResourceWithReference r = context.getResolver().resolve(context, ref.getReference());
|
||||
if (r == null) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hl7.fhir.r5.model.PrimitiveType;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
@ -28,7 +29,7 @@ public class NamingSystemRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (NamingSystem) dr);
|
||||
}
|
||||
|
||||
|
@ -125,4 +126,14 @@ public class NamingSystemRenderer extends ResourceRenderer {
|
|||
return ((NamingSystem) r).present();
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws IOException, FHIRException, EOperationOutcome {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
|
||||
return render(x, (OperationDefinition) dr);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
|
@ -29,7 +30,7 @@ public class OperationOutcomeRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (OperationOutcome) dr);
|
||||
}
|
||||
|
||||
|
@ -85,6 +86,11 @@ public class OperationOutcomeRenderer extends ResourceRenderer {
|
|||
return "todo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return "Not done yet";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(Resource r) throws UnsupportedEncodingException, IOException {
|
||||
return display((OperationOutcome) r);
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
package org.hl7.fhir.r5.renderers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
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.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryRequestComponent;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryResponseComponent;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntrySearchComponent;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.r5.model.Composition;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.Provenance;
|
||||
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.utils.EOperationOutcome;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class ParametersRenderer extends ResourceRenderer {
|
||||
|
||||
public ParametersRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||
super(context, rcontext);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(Resource r) throws UnsupportedEncodingException, IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, ResourceWrapper params) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
x.h2().tx("Parameters");
|
||||
XhtmlNode tbl = x.table("grid");
|
||||
PropertyWrapper pw = getProperty(params, "parameter");
|
||||
if (valued(pw)) {
|
||||
paramsW(tbl, pw.getValues(), 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void paramsW(XhtmlNode tbl, List<BaseWrapper> list, int indent) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||
for (BaseWrapper p : list) {
|
||||
XhtmlNode tr = tbl.tr();
|
||||
XhtmlNode td = tr.td();
|
||||
for (int i = 0; i < indent; i++) {
|
||||
td.tx(XhtmlNode.NBSP);
|
||||
}
|
||||
td.tx(p.get("name").primitiveValue());
|
||||
if (p.has("value")) {
|
||||
renderBase(tr.td(), p.get("value"));
|
||||
} else if (p.has("resource")) {
|
||||
ResourceWrapper rw = p.getChildByName("resource").getAsResource();
|
||||
td = tr.td();
|
||||
XhtmlNode para = td.para();
|
||||
para.tx(rw.fhirType()+"/"+rw.getId());
|
||||
para.an(rw.fhirType().toLowerCase()+"_"+rw.getId()).tx(" ");
|
||||
XhtmlNode x = rw.getNarrative();
|
||||
if (x != null) {
|
||||
td.addChildren(x);
|
||||
} else {
|
||||
ResourceRenderer rr = RendererFactory.factory(rw, context, rcontext);
|
||||
rr.render(td, rw);
|
||||
}
|
||||
} else if (p.has("part")) {
|
||||
tr.td();
|
||||
PropertyWrapper pw = getProperty(p, "parameter");
|
||||
paramsW(tbl, pw.getValues(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public XhtmlNode render(Parameters params) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
|
||||
div.h2().tx("Parameters");
|
||||
XhtmlNode tbl = div.table("grid");
|
||||
params(tbl, params.getParameter(), 0);
|
||||
return div;
|
||||
}
|
||||
|
||||
private void params(XhtmlNode tbl, List<ParametersParameterComponent> list, int indent) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
|
||||
for (ParametersParameterComponent p : list) {
|
||||
XhtmlNode tr = tbl.tr();
|
||||
XhtmlNode td = tr.td();
|
||||
for (int i = 0; i < indent; i++) {
|
||||
td.tx(XhtmlNode.NBSP);
|
||||
}
|
||||
td.tx(p.getName());
|
||||
if (p.hasValue()) {
|
||||
render(tr.td(), p.getValue());
|
||||
} else if (p.hasResource()) {
|
||||
ResourceRenderer rr = RendererFactory.factory(p.getResource(), context);
|
||||
rr.render(tr.td(), p.getResource());
|
||||
} else if (p.hasPart()) {
|
||||
tr.td();
|
||||
params(tbl, p.getPart(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,9 +3,20 @@ package org.hl7.fhir.r5.renderers;
|
|||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.apache.poi.hssf.record.chart.DatRecord;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.DateType;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.HumanName;
|
||||
import org.hl7.fhir.r5.model.HumanName.NameUse;
|
||||
import org.hl7.fhir.r5.model.Identifier;
|
||||
import org.hl7.fhir.r5.model.Identifier.IdentifierUse;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
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.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class PatientRenderer extends ResourceRenderer {
|
||||
|
@ -16,13 +27,179 @@ public class PatientRenderer extends ResourceRenderer {
|
|||
super(context);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws UnsupportedEncodingException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws UnsupportedEncodingException, IOException {
|
||||
describe(x, dr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// name gender DoB (MRN)
|
||||
public String display(Resource dr) {
|
||||
return "Not done yet";
|
||||
Patient pat = (Patient) dr;
|
||||
Identifier id = null;
|
||||
for (Identifier t : pat.getIdentifier()) {
|
||||
id = chooseId(id, t);
|
||||
}
|
||||
HumanName n = null;
|
||||
for (HumanName t : pat.getName()) {
|
||||
n = chooseName(n, t);
|
||||
}
|
||||
return display(n, pat.getGender().getDisplay(), pat.getBirthDateElement(), id);
|
||||
}
|
||||
|
||||
private Identifier chooseId(Identifier oldId, Identifier newId) {
|
||||
if (oldId == null) {
|
||||
return newId;
|
||||
}
|
||||
if (newId == null) {
|
||||
return oldId;
|
||||
}
|
||||
return isPreferred(newId.getUse(), oldId.getUse()) ? newId : oldId;
|
||||
}
|
||||
|
||||
private boolean isPreferred(IdentifierUse newUse, IdentifierUse oldUse) {
|
||||
if (newUse == null && oldUse == null || newUse == oldUse) {
|
||||
return false;
|
||||
}
|
||||
if (newUse == null) {
|
||||
return true;
|
||||
}
|
||||
switch (newUse) {
|
||||
case NULL: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.USUAL);
|
||||
case OFFICIAL: return !existsInList(oldUse, IdentifierUse.USUAL);
|
||||
case OLD: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.SECONDARY, IdentifierUse.USUAL);
|
||||
case SECONDARY: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.USUAL);
|
||||
case TEMP: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.SECONDARY, IdentifierUse.USUAL);
|
||||
case USUAL: return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean existsInList(IdentifierUse oldUse, IdentifierUse... values) {
|
||||
for (IdentifierUse value : values) {
|
||||
if (value == oldUse) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private HumanName chooseName(HumanName oldName, HumanName newName) {
|
||||
if (oldName == null) {
|
||||
return newName;
|
||||
}
|
||||
if (newName == null) {
|
||||
return oldName;
|
||||
}
|
||||
return isPreferred(newName.getUse(), oldName.getUse()) ? newName : oldName;
|
||||
}
|
||||
|
||||
|
||||
private boolean isPreferred(NameUse newUse, NameUse oldUse) {
|
||||
if (newUse == null && oldUse == null || newUse == oldUse) {
|
||||
return false;
|
||||
}
|
||||
if (newUse == null) {
|
||||
return true;
|
||||
}
|
||||
switch (oldUse) {
|
||||
case ANONYMOUS: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
|
||||
case MAIDEN: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
|
||||
case NICKNAME: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
|
||||
case NULL: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
|
||||
case OFFICIAL: return existsInList(newUse, NameUse.USUAL);
|
||||
case OLD: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
|
||||
case TEMP: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
|
||||
case USUAL: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean existsInList(NameUse oldUse, NameUse... values) {
|
||||
for (NameUse value : values) {
|
||||
if (value == oldUse) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper pat) throws UnsupportedEncodingException, IOException {
|
||||
Identifier id = null;
|
||||
PropertyWrapper pw = getProperty(pat, "identifier");
|
||||
for (BaseWrapper t : pw.getValues()) {
|
||||
id = chooseId(id, (Identifier) t.getBase());
|
||||
}
|
||||
pw = getProperty(pat, "name");
|
||||
HumanName n = null;
|
||||
for (BaseWrapper t : pw.getValues()) {
|
||||
n = chooseName(n, (HumanName) t);
|
||||
}
|
||||
String gender = null;
|
||||
pw = getProperty(pat, "gender");
|
||||
if (valued(pw)) {
|
||||
pw.value().getBase().primitiveValue();
|
||||
}
|
||||
DateType dt = null;
|
||||
pw = getProperty(pat, "birthDate");
|
||||
if (valued(pw)) {
|
||||
dt = (DateType) pw.value().getBase();
|
||||
}
|
||||
return display(n, gender, dt, id);
|
||||
}
|
||||
|
||||
public void describe(XhtmlNode x, ResourceWrapper pat) throws UnsupportedEncodingException, IOException {
|
||||
Identifier id = null;
|
||||
PropertyWrapper pw = getProperty(pat, "identifier");
|
||||
for (BaseWrapper t : pw.getValues()) {
|
||||
id = chooseId(id, (Identifier) t.getBase());
|
||||
}
|
||||
pw = getProperty(pat, "name");
|
||||
HumanName n = null;
|
||||
for (BaseWrapper t : pw.getValues()) {
|
||||
n = chooseName(n, (HumanName) t.getBase());
|
||||
}
|
||||
String gender = null;
|
||||
pw = getProperty(pat, "gender");
|
||||
if (valued(pw)) {
|
||||
pw.value().getBase().primitiveValue();
|
||||
}
|
||||
DateType dt = null;
|
||||
pw = getProperty(pat, "birthDate");
|
||||
if (valued(pw)) {
|
||||
dt = (DateType) pw.value().getBase();
|
||||
}
|
||||
describe(x, n, gender, dt, id);
|
||||
}
|
||||
|
||||
|
||||
private String display(HumanName name, String gender, DateType dob, Identifier id) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(display(name));
|
||||
b.append(" ");
|
||||
b.append(gender);
|
||||
b.append(" ");
|
||||
b.append(display(dob));
|
||||
if (id != null) {
|
||||
b.append(" ( ");
|
||||
b.append(display(id));
|
||||
b.append(")");
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public void describe(XhtmlNode x, HumanName name, String gender, DateType dob, Identifier id) throws UnsupportedEncodingException, IOException {
|
||||
render(x.b(), name);
|
||||
x.tx(" ");
|
||||
x.tx(gender);
|
||||
x.tx(" ");
|
||||
render(x, dob);
|
||||
if (id != null) {
|
||||
x.tx(" ( ");
|
||||
render(x, id);
|
||||
x.tx(")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -92,7 +92,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, DomainResource r) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, new DirectWrappers.ResourceWrapperDirect(context, r));
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,6 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
containedIds.clear();
|
||||
generateByProfile(r, sd, r.root(), sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), false, 0);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
||||
|
@ -121,6 +120,12 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
public String display(Resource r) throws UnsupportedEncodingException, IOException {
|
||||
return "todo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return "Not done yet";
|
||||
}
|
||||
|
||||
//
|
||||
// public void inject(Element er, XhtmlNode x, NarrativeStatus status, boolean pretty) {
|
||||
// if (!x.hasAttribute("xmlns"))
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.Reference;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.UriType;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class ProvenanceRenderer extends ResourceRenderer {
|
||||
|
@ -19,7 +20,7 @@ public class ProvenanceRenderer extends ResourceRenderer {
|
|||
super(context);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource prv) throws UnsupportedEncodingException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource prv) throws UnsupportedEncodingException, IOException {
|
||||
return render(x, (Provenance) prv);
|
||||
}
|
||||
|
||||
|
@ -150,4 +151,9 @@ public class ProvenanceRenderer extends ResourceRenderer {
|
|||
return "Provenance for "+displayReference(prv, prv.getTargetFirstRep());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return "Not done yet";
|
||||
}
|
||||
|
||||
}
|
|
@ -42,7 +42,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
|
|||
super(context);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource q) throws UnsupportedEncodingException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource q) throws UnsupportedEncodingException, IOException {
|
||||
return render(x, (Questionnaire) q);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
|
|||
super(context);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource q) throws UnsupportedEncodingException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource q) throws UnsupportedEncodingException, IOException {
|
||||
return render(x, (QuestionnaireResponse) q);
|
||||
}
|
||||
|
||||
|
@ -850,4 +850,9 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
|
|||
return "todo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
return "Not done yet";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.hl7.fhir.r5.renderers;
|
||||
|
||||
|
||||
/**
|
||||
* Rendering framework:
|
||||
*
|
||||
* * boolean render(DomainResource) : produce an HTML representation suitable for runtime / documentation, and insert it into the resource. Return true of any extensions encountered
|
||||
* * boolean render(XhtmlNode, Resource: produce an HTML representation, and fill out the provided node with it. Return true of any extensions encountered
|
||||
* * XhtmlNode build(DomainResource): same as render(DomainResource) but also return the XHtmlNode
|
||||
*
|
||||
* * String display(Base) : produce a plan text concise representation that serves to describe the resource
|
||||
* * void display(XhtmlNode, Base) : produce a plan text concise representation that serves to describe the resource
|
||||
*
|
||||
* * void describe(XhtmlNode, Resource) : produce a short summary of the resource with key details presented (potentially more verbose than display, but still suitable for a single line)
|
||||
*
|
||||
* if not specific code for rendering a resource has been provided, and there's no liquid script to guide it, a generic rendering based onthe profile will be performed
|
||||
*
|
||||
* @author graha
|
||||
*
|
||||
*/
|
||||
public class Renderer {
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@ import org.hl7.fhir.r5.model.DomainResource;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
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;
|
||||
|
||||
public class RendererFactory {
|
||||
|
||||
|
@ -87,7 +88,7 @@ public class RendererFactory {
|
|||
}
|
||||
|
||||
|
||||
public static ResourceRenderer factory(ResourceWrapper resource, RenderingContext context) {
|
||||
public static ResourceRenderer factory(ResourceWrapper resource, RenderingContext context, ResourceContext resourceContext) {
|
||||
if (context.getTemplateProvider() != null) {
|
||||
String liquidTemplate = context.getTemplateProvider().findTemplate(context, resource.getName());
|
||||
if (liquidTemplate != null) {
|
||||
|
@ -102,7 +103,11 @@ public class RendererFactory {
|
|||
return new DiagnosticReportRenderer(context);
|
||||
}
|
||||
|
||||
return new ProfileDrivenRenderer(context);
|
||||
return new ProfileDrivenRenderer(context, resourceContext);
|
||||
}
|
||||
|
||||
public static ResourceRenderer factory(ResourceWrapper rw, RenderingContext lrc) {
|
||||
return factory(rw, lrc, null);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.apache.commons.lang3.NotImplementedException;
|
|||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
|
||||
|
@ -80,18 +81,23 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
return x;
|
||||
}
|
||||
|
||||
public abstract boolean render(XhtmlNode x, DomainResource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome;
|
||||
public abstract boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome;
|
||||
|
||||
public boolean render(XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
ProfileDrivenRenderer pr = new ProfileDrivenRenderer(context);
|
||||
return pr.render(x, r);
|
||||
}
|
||||
|
||||
public void describe(XhtmlNode x, DomainResource r) throws UnsupportedEncodingException, IOException {
|
||||
public void describe(XhtmlNode x, Resource r) throws UnsupportedEncodingException, IOException {
|
||||
x.tx(display(r));
|
||||
}
|
||||
|
||||
public void describe(XhtmlNode x, ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
x.tx(display(r));
|
||||
}
|
||||
|
||||
public abstract String display(Resource r) throws UnsupportedEncodingException, IOException;
|
||||
public abstract String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException;
|
||||
|
||||
public static void inject(DomainResource r, XhtmlNode x, NarrativeStatus status) {
|
||||
if (!x.hasAttribute("xmlns"))
|
||||
|
@ -151,7 +157,12 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, r.getReference().startsWith("#"));
|
||||
}
|
||||
} else if (tr != null && tr.getResource() != null) {
|
||||
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), r.getReference().startsWith("#"), r.getReference().startsWith("#"));
|
||||
if (tr.getReference().startsWith("#")) {
|
||||
// we already rendered this in this page
|
||||
c.tx("See above ("+tr.getResource().fhirType()+"/"+tr.getResource().getId()+")");
|
||||
} else {
|
||||
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), r.getReference().startsWith("#"), r.getReference().startsWith("#"));
|
||||
}
|
||||
} else {
|
||||
c.addText(r.getReference());
|
||||
}
|
||||
|
@ -208,12 +219,13 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url);
|
||||
if (bundleElement != null) {
|
||||
String bundleUrl = null;
|
||||
if (bundleElement.getNamedChild("resource").getChildValue("id") != null) {
|
||||
bundleUrl = "#" + bundleElement.fhirType().toLowerCase() + "_" + bundleElement.getNamedChild("resource").getChildValue("id");
|
||||
Element br = bundleElement.getNamedChild("resource");
|
||||
if (br.getChildValue("id") != null) {
|
||||
bundleUrl = "#" + br.fhirType().toLowerCase() + "_" + br.getChildValue("id");
|
||||
} else {
|
||||
bundleUrl = "#" +fullUrlToAnchor(bundleElement.getChildValue("fullUrl"));
|
||||
}
|
||||
return new ResourceWithReference(bundleUrl, new ResourceWrapperMetaElement(this.context, bundleElement));
|
||||
return new ResourceWithReference(bundleUrl, new ResourceWrapperMetaElement(this.context, br));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,6 +266,14 @@ public abstract class ResourceRenderer extends DataRenderer {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected PropertyWrapper getProperty(BaseWrapper res, String name) {
|
||||
for (PropertyWrapper t : res.children()) {
|
||||
if (t.getName().equals(name))
|
||||
return t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean valued(PropertyWrapper pw) {
|
||||
return pw != null && pw.hasValues();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.hl7.fhir.r5.model.DomainResource;
|
|||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
super(context, rcontext);
|
||||
}
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (StructureDefinition) dr);
|
||||
}
|
||||
|
||||
|
@ -44,4 +45,14 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
return ((StructureDefinition) r).present();
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ 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.ConceptSetComponent;
|
||||
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.terminologies.CodeSystemUtilities;
|
||||
|
@ -44,6 +45,16 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
|
|||
return ((CanonicalResource) r).present();
|
||||
}
|
||||
|
||||
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
|
||||
if (r.has("title")) {
|
||||
return r.children("title").get(0).getBase().primitiveValue();
|
||||
}
|
||||
if (r.has("name")) {
|
||||
return r.children("name").get(0).getBase().primitiveValue();
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
protected class TargetElementComponentWrapper {
|
||||
protected ConceptMapGroupComponent group;
|
||||
protected TargetElementComponent comp;
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
|
|||
|
||||
private List<ConceptMapRenderInstructions> renderingMaps = new ArrayList<ConceptMapRenderInstructions>();
|
||||
|
||||
public boolean render(XhtmlNode x, DomainResource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
|
||||
return render(x, (ValueSet) dr, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,46 +3,58 @@ package org.hl7.fhir.r5.renderers.utils;
|
|||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Parameters;
|
||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContextType;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
public class Resolver {
|
||||
|
||||
public enum ResourceContextType {
|
||||
PARAMETERS, BUNDLE
|
||||
}
|
||||
|
||||
public interface IReferenceResolver {
|
||||
ResourceWithReference resolve(RenderingContext context, String url);
|
||||
}
|
||||
|
||||
public static class ResourceContext {
|
||||
Bundle bundleResource;
|
||||
org.hl7.fhir.r5.elementmodel.Element bundleElement;
|
||||
private ResourceContextType type;
|
||||
private Resource containerResource;
|
||||
private org.hl7.fhir.r5.elementmodel.Element containerElement;
|
||||
|
||||
DomainResource resourceResource;
|
||||
org.hl7.fhir.r5.elementmodel.Element resourceElement;
|
||||
|
||||
public ResourceContext(Bundle bundle, DomainResource dr) {
|
||||
public ResourceContext(ResourceContextType type, Resource bundle, DomainResource dr) {
|
||||
super();
|
||||
this.bundleResource = bundle;
|
||||
this.type = type;
|
||||
this.containerResource = bundle;
|
||||
this.resourceResource = dr;
|
||||
}
|
||||
|
||||
public ResourceContext(org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||
this.bundleElement = bundle;
|
||||
public ResourceContext(ResourceContextType type, org.hl7.fhir.r5.elementmodel.Element bundle, org.hl7.fhir.r5.elementmodel.Element dr) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.containerElement = bundle;
|
||||
this.resourceElement = dr;
|
||||
}
|
||||
|
||||
public ResourceContext(Object bundle, Element doc) {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
// public ResourceContext(Object bundle, Element doc) {
|
||||
// // TODO Auto-generated constructor stub
|
||||
// }
|
||||
|
||||
public Bundle getBundleResource() {
|
||||
return bundleResource;
|
||||
}
|
||||
// public Bundle getBundleResource() {
|
||||
// return containerResource;
|
||||
// }
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element getBundleElement() {
|
||||
return bundleElement;
|
||||
}
|
||||
|
||||
// public org.hl7.fhir.r5.elementmodel.Element getBundleElement() {
|
||||
// return containerElement;
|
||||
// }
|
||||
//
|
||||
public DomainResource getResourceResource() {
|
||||
return resourceResource;
|
||||
}
|
||||
|
@ -64,12 +76,26 @@ public class Resolver {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
if (bundleResource != null) {
|
||||
for (BundleEntryComponent be : bundleResource.getEntry()) {
|
||||
if (be.getFullUrl().equals(value))
|
||||
return be;
|
||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||
return be;
|
||||
if (type == ResourceContextType.BUNDLE) {
|
||||
if (containerResource != null) {
|
||||
for (BundleEntryComponent be : ((Bundle) containerResource).getEntry()) {
|
||||
if (be.getFullUrl().equals(value))
|
||||
return be;
|
||||
if (value.equals(be.getResource().fhirType()+"/"+be.getResource().getId()))
|
||||
return be;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ResourceContextType.PARAMETERS) {
|
||||
if (containerResource != null) {
|
||||
for (ParametersParameterComponent p : ((Parameters) containerResource).getParameter()) {
|
||||
if (p.getResource() != null && value.equals(p.getResource().fhirType()+"/"+p.getResource().getId())) {
|
||||
BundleEntryComponent be = new BundleEntryComponent();
|
||||
be.setResource(p.getResource());
|
||||
return be;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -85,13 +111,24 @@ public class Resolver {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
if (bundleElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element be : bundleElement.getChildren("entry")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||
if (value.equals(be.getChildValue("fullUrl")))
|
||||
return be;
|
||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||
return be;
|
||||
if (type == ResourceContextType.BUNDLE) {
|
||||
if (containerElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element be : containerElement.getChildren("entry")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = be.getNamedChild("resource");
|
||||
if (value.equals(be.getChildValue("fullUrl")))
|
||||
return be;
|
||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||
return be;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type == ResourceContextType.PARAMETERS) {
|
||||
if (containerElement != null) {
|
||||
for (org.hl7.fhir.r5.elementmodel.Element p : containerElement.getChildren("parameter")) {
|
||||
org.hl7.fhir.r5.elementmodel.Element res = p.getNamedChild("resource");
|
||||
if (value.equals(res.fhirType()+"/"+res.getChildValue("id")))
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -71,7 +71,7 @@ public class FHIRLexer {
|
|||
private String name;
|
||||
|
||||
public FHIRLexer(String source, String name) throws FHIRLexerException {
|
||||
this.source = source;
|
||||
this.source = source == null ? "" : source;
|
||||
this.name = name == null ? "??" : name;
|
||||
currentLocation = new SourceLocation(1, 1);
|
||||
next();
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package org.hl7.fhir.utilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -9,12 +13,12 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
* Neither the name of HL7 nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
|
@ -35,6 +39,22 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
public class VersionUtilities {
|
||||
|
||||
|
||||
public static class VersionURLInfo {
|
||||
private String version;
|
||||
private String url;
|
||||
public VersionURLInfo(String version, String url) {
|
||||
super();
|
||||
this.version = version;
|
||||
this.url = url;
|
||||
}
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String CURRENT_VERSION = "4.4";
|
||||
public static final String CURRENT_FULL_VERSION = "4.4.0";
|
||||
|
||||
|
@ -225,4 +245,124 @@ public class VersionUtilities {
|
|||
throw new FHIRException("Unknown version "+version);
|
||||
}
|
||||
|
||||
public static VersionURLInfo parseVersionUrl(String url) {
|
||||
if (url.length() < 24) {
|
||||
return null;
|
||||
}
|
||||
String v = url.substring(20, 24);
|
||||
if (v.endsWith("/")) {
|
||||
v = v.substring(0, v.length()-1);
|
||||
if (Utilities.existsInList(v, "1.0", "1.4", "3.0", "4.0", "5.0", CURRENT_VERSION)) {
|
||||
return new VersionURLInfo(v, "http://hl7.org/fhir/"+url.substring(24));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<String> getCanonicalResourceNames(String version) {
|
||||
ArrayList<String> res = new ArrayList<String>();
|
||||
if (isR2Ver(version) || isR2BVer(version)) {
|
||||
res.add("ValueSet");
|
||||
res.add("ConceptMap");
|
||||
res.add("NamingSystem");
|
||||
res.add("StructureDefinition");
|
||||
res.add("DataElement");
|
||||
res.add("Conformance");
|
||||
res.add("OperationDefinition");
|
||||
res.add("SearchParameter");
|
||||
res.add("ImplementationGuide");
|
||||
res.add("TestScript");
|
||||
}
|
||||
if (isR3Ver(version)) {
|
||||
res.add("CapabilityStatement");
|
||||
res.add("StructureDefinition");
|
||||
res.add("ImplementationGuide");
|
||||
res.add("SearchParameter");
|
||||
res.add("MessageDefinition");
|
||||
res.add("OperationDefinition");
|
||||
res.add("CompartmentDefinition");
|
||||
res.add("StructureMap");
|
||||
res.add("GraphDefinition");
|
||||
res.add("DataElement");
|
||||
res.add("CodeSystem");
|
||||
res.add("ValueSet");
|
||||
res.add("ConceptMap");
|
||||
res.add("ExpansionProfile");
|
||||
res.add("Questionnaire");
|
||||
res.add("ActivityDefinition");
|
||||
res.add("ServiceDefinition");
|
||||
res.add("PlanDefinition");
|
||||
res.add("Measure");
|
||||
res.add("TestScript");
|
||||
|
||||
}
|
||||
if (isR4Ver(version)) {
|
||||
|
||||
res.add("ActivityDefinition");
|
||||
res.add("CapabilityStatement");
|
||||
res.add("ChargeItemDefinition");
|
||||
res.add("CodeSystem");
|
||||
res.add("CompartmentDefinition");
|
||||
res.add("ConceptMap");
|
||||
res.add("EffectEvidenceSynthesis");
|
||||
res.add("EventDefinition");
|
||||
res.add("Evidence");
|
||||
res.add("EvidenceVariable");
|
||||
res.add("ExampleScenario");
|
||||
res.add("GraphDefinition");
|
||||
res.add("ImplementationGuide");
|
||||
res.add("Library");
|
||||
res.add("Measure");
|
||||
res.add("MessageDefinition");
|
||||
res.add("NamingSystem");
|
||||
res.add("OperationDefinition");
|
||||
res.add("PlanDefinition");
|
||||
res.add("Questionnaire");
|
||||
res.add("ResearchDefinition");
|
||||
res.add("ResearchElementDefinition");
|
||||
res.add("RiskEvidenceSynthesis");
|
||||
res.add("SearchParameter");
|
||||
res.add("StructureDefinition");
|
||||
res.add("StructureMap");
|
||||
res.add("TerminologyCapabilities");
|
||||
res.add("TestScript");
|
||||
res.add("ValueSet");
|
||||
}
|
||||
|
||||
if (isR5Ver(version)) {
|
||||
|
||||
res.add("ActivityDefinition");
|
||||
res.add("CapabilityStatement");
|
||||
res.add("CapabilityStatement2");
|
||||
res.add("ChargeItemDefinition");
|
||||
res.add("Citation");
|
||||
res.add("CodeSystem");
|
||||
res.add("CompartmentDefinition");
|
||||
res.add("ConceptMap");
|
||||
res.add("ConditionDefinition");
|
||||
res.add("EventDefinition");
|
||||
res.add("Evidence");
|
||||
res.add("EvidenceReport");
|
||||
res.add("EvidenceVariable");
|
||||
res.add("ExampleScenario");
|
||||
res.add("GraphDefinition");
|
||||
res.add("ImplementationGuide");
|
||||
res.add("Library");
|
||||
res.add("Measure");
|
||||
res.add("MessageDefinition");
|
||||
res.add("NamingSystem");
|
||||
res.add("OperationDefinition");
|
||||
res.add("PlanDefinition");
|
||||
res.add("Questionnaire");
|
||||
res.add("SearchParameter");
|
||||
res.add("StructureDefinition");
|
||||
res.add("StructureMap");
|
||||
res.add("TerminologyCapabilities");
|
||||
res.add("TestScript");
|
||||
res.add("ValueSet");
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
|
@ -1058,5 +1058,25 @@ public class NpmPackage {
|
|||
return "fhir.core".equals(JSONUtil.str(npm, "type"));
|
||||
}
|
||||
|
||||
public boolean hasCanonical(String url) {
|
||||
if (url == null) {
|
||||
return false;
|
||||
}
|
||||
String u = url.contains("|") ? url.substring(0, url.indexOf("|")) : url;
|
||||
String v = url.contains("|") ? url.substring(url.indexOf("|")+1) : null;
|
||||
NpmPackageFolder folder = folders.get("package");
|
||||
if (folder != null) {
|
||||
for (JsonElement e : folder.index.getAsJsonArray("files")) {
|
||||
JsonObject o = (JsonObject) e;
|
||||
if (u.equals(JSONUtil.str(o, "url"))) {
|
||||
if (v == null || v.equals(JSONUtil.str(o, "version"))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ public class I18nConstants {
|
|||
public static final String BUNDLE_BUNDLE_ENTRY_NOFIRSTRESOURCE = "Bundle_BUNDLE_Entry_NoFirstResource";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_NOFULLURL = "Bundle_BUNDLE_Entry_NoFullUrl";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_NOPROFILE = "Bundle_BUNDLE_Entry_NoProfile";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = "BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_NOTFOUND = "Bundle_BUNDLE_Entry_NotFound";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_ORPHAN = "Bundle_BUNDLE_Entry_Orphan";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_TYPE = "Bundle_BUNDLE_Entry_Type";
|
||||
|
@ -543,10 +544,14 @@ public class I18nConstants {
|
|||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL = "VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL";
|
||||
public static final String VALIDATION_VAL_PROFILE_SIGNPOST_META = "VALIDATION_VAL_PROFILE_SIGNPOST_META";
|
||||
public static final String VALIDATION_VAL_PROFILE_SLICEORDER = "Validation_VAL_Profile_SliceOrder";
|
||||
public static final String VALIDATION_VAL_PROFILE_OTHER_VERSION = "VALIDATION_VAL_PROFILE_OTHER_VERSION";
|
||||
public static final String VALIDATION_VAL_PROFILE_THIS_VERSION_OK = "VALIDATION_VAL_PROFILE_THIS_VERSION_OK";
|
||||
public static final String VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER = "VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER";
|
||||
public static final String VALIDATION_VAL_PROFILE_UNKNOWN = "Validation_VAL_Profile_Unknown";
|
||||
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE = "Validation_VAL_Profile_WrongType";
|
||||
public static final String VALIDATION_VAL_PROFILE_WRONGTYPE2 = "Validation_VAL_Profile_WrongType2";
|
||||
public static final String VALIDATION_VAL_UNKNOWN_PROFILE = "Validation_VAL_Unknown_Profile";
|
||||
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE";
|
||||
public static final String VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER = "VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER";
|
||||
public static final String VALUESET_NO_SYSTEM_WARNING = "VALUESET_NO_SYSTEM_WARNING";
|
||||
|
|
|
@ -571,3 +571,7 @@ PACKAGE_VERSION_MISMATCH = FHIR Version mismatch in package {0}: version is {2}
|
|||
VALUESET_REFERENCE_UNKNOWN = The value set import {0} could not be found so cannot be checked
|
||||
VALUESET_REFERENCE_INVALID_TYPE = The value set import {0} points to a resource of type {1} which is not valid
|
||||
SD_MUST_HAVE_DERIVATION = StructureDefinition {0} must have a derivation, since it has a baseDefinition
|
||||
VALIDATION_VAL_PROFILE_OTHER_VERSION = Profile is for a different version of FHIR ({0}) so has been ignored
|
||||
VALIDATION_VAL_PROFILE_THIS_VERSION_OK = Profile for this version of FHIR - all OK
|
||||
VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER = Profile is for this version of FHIR, but is an invalid type {0}
|
||||
BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = Multiple profiles found for contained resource. This is not supported at this time. (Type {0}: {1})
|
||||
|
|
|
@ -58,7 +58,7 @@ public class CachingPackageClientTests {
|
|||
Assertions.assertTrue(client.exists("hl7.fhir.r4.core", "4.0.1"));
|
||||
Assertions.assertTrue(!client.exists("hl7.fhir.r4.core", "1.0.2"));
|
||||
Assertions.assertTrue(!client.exists("hl7.fhir.nothing", "1.0.1"));
|
||||
Assertions.assertTrue(client.exists("hl7.fhir.pubpack", "0.0.6"));
|
||||
Assertions.assertTrue(client.exists("hl7.fhir.pubpack", "0.0.7"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -22,7 +22,7 @@ public class PackageCacheTests {
|
|||
System.out.println("remaining packages: "+list.toString());
|
||||
}
|
||||
Assertions.assertTrue(list.isEmpty(), "List should be true but is "+list.toString());
|
||||
NpmPackage npm = cache.loadPackage("hl7.fhir.pubpack", "0.0.3");
|
||||
NpmPackage npm = cache.loadPackage("hl7.fhir.pubpack", "0.0.7");
|
||||
npm.loadAllFiles();
|
||||
Assertions.assertNotNull(npm);
|
||||
File dir = new File(Utilities.path("[tmp]", "cache"));
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hl7.fhir.r5.utils.*;
|
|||
import org.hl7.fhir.r5.utils.IResourceValidator.*;
|
||||
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
|
||||
import org.hl7.fhir.validation.instance.InstanceValidator;
|
||||
import org.hl7.fhir.utilities.IniFile;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
|
@ -163,7 +164,42 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
* @author Grahame Grieve
|
||||
*
|
||||
*/
|
||||
public class ValidationEngine implements IValidatorResourceFetcher {
|
||||
public class ValidationEngine implements IValidatorResourceFetcher, IPackageInstaller {
|
||||
|
||||
public static class VersionSourceInformation {
|
||||
|
||||
private List<String> report = new ArrayList<>();
|
||||
private List<String> versions = new ArrayList<>();
|
||||
|
||||
public void see(String version, String src) {
|
||||
version = VersionUtilities.getMajMin(version);
|
||||
report.add(src+": "+version);
|
||||
if (!versions.contains(version)) {
|
||||
versions.add(version);
|
||||
Collections.sort(versions);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return versions.isEmpty();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return versions.size();
|
||||
}
|
||||
|
||||
public String version() {
|
||||
return versions.get(0);
|
||||
}
|
||||
|
||||
public List<String> getReport() {
|
||||
if (report.isEmpty()) {
|
||||
report.add("(nothing found)");
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ScanOutputItem {
|
||||
private String ref;
|
||||
|
@ -311,9 +347,10 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
|
||||
public ValidationEngine() throws IOException {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
context = SimpleWorkerContext.fromNothing();
|
||||
}
|
||||
|
||||
public void setTerminologyServer(String src, String log, FhirPublication version) throws Exception {
|
||||
public void setTerminologyServer(String src, String log, FhirPublication version) throws FHIRException, URISyntaxException {
|
||||
connectToTSServer(src, log, version);
|
||||
}
|
||||
|
||||
|
@ -342,7 +379,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.showTimes = showTimes;
|
||||
}
|
||||
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws Exception {
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, boolean canRunWithoutTerminologyServer, String vString) throws FHIRException, IOException, URISyntaxException {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
loadCoreDefinitions(src, false);
|
||||
context.setCanRunWithoutTerminology(canRunWithoutTerminologyServer);
|
||||
|
@ -350,14 +387,14 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.version = vString;
|
||||
}
|
||||
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws Exception {
|
||||
public ValidationEngine(String src, String txsrvr, String txLog, FhirPublication version, String vString) throws FHIRException, IOException, URISyntaxException {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
loadCoreDefinitions(src, false);
|
||||
setTerminologyServer(txsrvr, txLog, version);
|
||||
this.version = vString;
|
||||
}
|
||||
|
||||
public ValidationEngine(String src) throws Exception {
|
||||
public ValidationEngine(String src) throws FHIRException, IOException {
|
||||
loadCoreDefinitions(src, false);
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
|
@ -370,7 +407,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.language = language;
|
||||
}
|
||||
|
||||
private void loadCoreDefinitions(String src, boolean recursive) throws Exception {
|
||||
private void loadCoreDefinitions(String src, boolean recursive) throws FHIRException, IOException {
|
||||
if (pcm == null) {
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
|
@ -435,7 +472,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return ep;
|
||||
}
|
||||
|
||||
private byte[] loadProfileSource(String src) throws Exception {
|
||||
private byte[] loadProfileSource(String src) throws FHIRException, FileNotFoundException, IOException {
|
||||
if (Utilities.noString(src)) {
|
||||
throw new FHIRException("Profile Source '" + src + "' could not be processed");
|
||||
} else if (src.startsWith("https:") || src.startsWith("http:")) {
|
||||
|
@ -447,13 +484,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
private byte[] loadProfileFromUrl(String src) throws Exception {
|
||||
private byte[] loadProfileFromUrl(String src) throws FHIRException {
|
||||
try {
|
||||
URL url = new URL(src+"?nocache=" + System.currentTimeMillis());
|
||||
URLConnection c = url.openConnection();
|
||||
return IOUtils.toByteArray(c.getInputStream());
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Unable to find definitions at URL '"+src+"': "+e.getMessage(), e);
|
||||
throw new FHIRException("Unable to find definitions at URL '"+src+"': "+e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,9 +501,10 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return TextFile.fileToBytes(src);
|
||||
}
|
||||
|
||||
/** explore should be true if we're trying to load an -ig parameter, and false if we're loading source **/
|
||||
/** explore should be true if we're trying to load an -ig parameter, and false if we're loading source
|
||||
* @throws IOException **/
|
||||
|
||||
private Map<String, byte[]> loadIgSource(String src, boolean recursive, boolean explore) throws Exception {
|
||||
private Map<String, byte[]> loadIgSource(String src, boolean recursive, boolean explore) throws FHIRException, IOException {
|
||||
// src can be one of the following:
|
||||
// - a canonical url for an ig - this will be converted to a package id and loaded into the cache
|
||||
// - a package id for an ig - this will be loaded into the cache
|
||||
|
@ -510,11 +548,60 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
} else if ((src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) || src.matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
|
||||
return fetchByPackage(src);
|
||||
}
|
||||
throw new Exception("Unable to find/resolve/read -ig "+src);
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> loadIgSourceForVersion(String src, boolean recursive, boolean explore, VersionSourceInformation versions) throws FHIRException, IOException {
|
||||
if (src.startsWith("https:") || src.startsWith("http:")) {
|
||||
String v = null;
|
||||
if (src.contains("|")) {
|
||||
v = src.substring(src.indexOf("|")+1);
|
||||
src = src.substring(0, src.indexOf("|"));
|
||||
}
|
||||
String pid = pcm.getPackageId(src);
|
||||
if (!Utilities.noString(pid)) {
|
||||
versions.see(fetchVersionByPackage(pid+(v == null ? "" : "#"+v)), "Package "+src);
|
||||
return null;
|
||||
} else {
|
||||
return fetchVersionFromUrl(src+(v == null ? "" : "|"+v), explore, versions);
|
||||
}
|
||||
}
|
||||
|
||||
File f = new File(Utilities.path(src));
|
||||
if (f.exists()) {
|
||||
if (f.isDirectory() && new File(Utilities.path(src, "package.tgz")).exists()) {
|
||||
versions.see(loadPackageForVersion(new FileInputStream(Utilities.path(src, "package.tgz")), Utilities.path(src, "package.tgz")), "Package "+src);
|
||||
return null;
|
||||
}
|
||||
if (f.isDirectory() && new File(Utilities.path(src, "igpack.zip")).exists())
|
||||
return readZip(new FileInputStream(Utilities.path(src, "igpack.zip")));
|
||||
if (f.isDirectory() && new File(Utilities.path(src, "validator.pack")).exists())
|
||||
return readZip(new FileInputStream(Utilities.path(src, "validator.pack")));
|
||||
if (f.isDirectory())
|
||||
return scanDirectory(f, recursive);
|
||||
if (src.endsWith(".tgz")) {
|
||||
versions.see(loadPackageForVersion(new FileInputStream(src), src), "Package "+src);
|
||||
return null;
|
||||
}
|
||||
if (src.endsWith(".pack"))
|
||||
return readZip(new FileInputStream(src));
|
||||
if (src.endsWith("igpack.zip"))
|
||||
return readZip(new FileInputStream(src));
|
||||
FhirFormat fmt = checkIsResource(src);
|
||||
if (fmt != null) {
|
||||
Map<String, byte[]> res = new HashMap<String, byte[]>();
|
||||
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), TextFile.fileToBytesNCS(src));
|
||||
return res;
|
||||
}
|
||||
} else if ((src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) || src.matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX)) && !src.endsWith(".zip") && !src.endsWith(".tgz")) {
|
||||
versions.see(fetchVersionByPackage(src), "Package "+src);
|
||||
return null;
|
||||
}
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, byte[]> fetchFromUrl(String src, boolean explore) throws Exception {
|
||||
private Map<String, byte[]> fetchFromUrl(String src, boolean explore) throws FHIRException, IOException {
|
||||
if (src.endsWith(".tgz"))
|
||||
return loadPackage(fetchFromUrlSpecific(src, false), src);
|
||||
if (src.endsWith(".pack"))
|
||||
|
@ -551,15 +638,59 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
|
||||
return res;
|
||||
}
|
||||
throw new Exception("Unable to find/resolve/read -ig "+src);
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws Exception {
|
||||
private Map<String, byte[]> fetchVersionFromUrl(String src, boolean explore, VersionSourceInformation versions) throws FHIRException, IOException {
|
||||
if (src.endsWith(".tgz")) {
|
||||
versions.see(loadPackageForVersion(fetchFromUrlSpecific(src, false), src), "From Package "+src);
|
||||
return null;
|
||||
}
|
||||
if (src.endsWith(".pack"))
|
||||
return readZip(fetchFromUrlSpecific(src, false));
|
||||
if (src.endsWith("igpack.zip"))
|
||||
return readZip(fetchFromUrlSpecific(src, false));
|
||||
|
||||
InputStream stream = null;
|
||||
if (explore) {
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "package.tgz"), true);
|
||||
if (stream != null) {
|
||||
versions.see(loadPackageForVersion(stream, Utilities.pathURL(src, "package.tgz")), "From Package at "+src);
|
||||
return null;
|
||||
}
|
||||
// todo: these options are deprecated - remove once all IGs have been rebuilt post R4 technical correction
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "igpack.zip"), true);
|
||||
if (stream != null)
|
||||
return readZip(stream);
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "validator.pack"), true);
|
||||
if (stream != null)
|
||||
return readZip(stream);
|
||||
stream = fetchFromUrlSpecific(Utilities.pathURL(src, "validator.pack"), true);
|
||||
//// -----
|
||||
}
|
||||
|
||||
// ok, having tried all that... now we'll just try to access it directly
|
||||
byte[] cnt;
|
||||
if (stream == null)
|
||||
cnt = fetchFromUrlSpecific(src, "application/json", true);
|
||||
else
|
||||
cnt = TextFile.streamToBytes(stream);
|
||||
|
||||
FhirFormat fmt = checkIsResource(cnt, src);
|
||||
if (fmt != null) {
|
||||
Map<String, byte[]> res = new HashMap<String, byte[]>();
|
||||
res.put(Utilities.changeFileExt(src, "."+fmt.getExtension()), cnt);
|
||||
return res;
|
||||
}
|
||||
throw new FHIRException("Unable to find/resolve/read -ig "+src);
|
||||
}
|
||||
|
||||
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException, IOException {
|
||||
try {
|
||||
URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
|
||||
URLConnection c = url.openConnection();
|
||||
return c.getInputStream();
|
||||
} catch (Exception e) {
|
||||
} catch (IOException e) {
|
||||
if (optional)
|
||||
return null;
|
||||
else
|
||||
|
@ -567,13 +698,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional) throws Exception {
|
||||
private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional) throws FHIRException, IOException {
|
||||
try {
|
||||
URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestProperty("Accept", contentType);
|
||||
return TextFile.streamToBytes(conn.getInputStream());
|
||||
} catch (Exception e) {
|
||||
} catch (IOException e) {
|
||||
if (optional)
|
||||
return null;
|
||||
else
|
||||
|
@ -604,11 +735,15 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return Utilities.existsInList(Utilities.getFileExtension(ff.getName()).toLowerCase(), "md", "css", "js", "png", "gif", "jpg", "html", "tgz", "pack", "zip");
|
||||
}
|
||||
|
||||
private Map<String, byte[]> loadPackage(InputStream stream, String name) throws Exception {
|
||||
private Map<String, byte[]> loadPackage(InputStream stream, String name) throws FHIRException, IOException {
|
||||
return loadPackage(NpmPackage.fromPackage(stream));
|
||||
}
|
||||
|
||||
public Map<String, byte[]> loadPackage(NpmPackage pi) throws Exception {
|
||||
private String loadPackageForVersion(InputStream stream, String name) throws FHIRException, IOException {
|
||||
return NpmPackage.fromPackage(stream).fhirVersion();
|
||||
}
|
||||
|
||||
public Map<String, byte[]> loadPackage(NpmPackage pi) throws FHIRException, IOException {
|
||||
context.getLoadedPackages().add(pi.name()+"#"+pi.version());
|
||||
Map<String, byte[]> res = new HashMap<String, byte[]>();
|
||||
for (String s : pi.dependencies()) {
|
||||
|
@ -652,7 +787,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
System.out.println(message);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> fetchByPackage(String src) throws Exception {
|
||||
private Map<String, byte[]> fetchByPackage(String src) throws FHIRException, IOException {
|
||||
String id = src;
|
||||
String version = null;
|
||||
if (src.contains("#")) {
|
||||
|
@ -679,13 +814,46 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return loadPackage(pi);
|
||||
}
|
||||
|
||||
private Map<String, byte[]> resolvePackage(String id, String v) throws Exception {
|
||||
private String fetchVersionByPackage(String src) throws FHIRException, IOException {
|
||||
String id = src;
|
||||
String version = null;
|
||||
if (src.contains("#")) {
|
||||
id = src.substring(0, src.indexOf("#"));
|
||||
version = src.substring(src.indexOf("#")+1);
|
||||
}
|
||||
if (pcm == null) {
|
||||
log("Creating Package manager?");
|
||||
pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
}
|
||||
if (version == null) {
|
||||
version = pcm.getLatestVersion(id);
|
||||
}
|
||||
NpmPackage pi = null;
|
||||
if (version == null) {
|
||||
pi = pcm.loadPackageFromCacheOnly(id);
|
||||
if (pi != null)
|
||||
log(" ... Using version "+pi.version());
|
||||
} else
|
||||
pi = pcm.loadPackageFromCacheOnly(id, version);
|
||||
if (pi == null) {
|
||||
return resolvePackageForVersion(id, version);
|
||||
} else {
|
||||
return pi.fhirVersion();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, byte[]> resolvePackage(String id, String v) throws FHIRException, IOException {
|
||||
NpmPackage pi = pcm.loadPackage(id, v);
|
||||
if (pi != null && v == null)
|
||||
log(" ... Using version "+pi.version());
|
||||
return loadPackage(pi);
|
||||
}
|
||||
|
||||
private String resolvePackageForVersion(String id, String v) throws FHIRException, IOException {
|
||||
NpmPackage pi = pcm.loadPackage(id, v);
|
||||
return pi.fhirVersion();
|
||||
}
|
||||
|
||||
public SimpleWorkerContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
@ -758,7 +926,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadProfile(String src) throws Exception {
|
||||
public void loadProfile(String src) throws FHIRException, IOException {
|
||||
if (context.hasResource(StructureDefinition.class, src))
|
||||
return;
|
||||
if (context.hasResource(ImplementationGuide.class, src))
|
||||
|
@ -770,7 +938,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
context.cacheResource(r);
|
||||
}
|
||||
|
||||
public void loadIg(String src, boolean recursive) throws IOException, FHIRException, Exception {
|
||||
public void scanForIgVersion(String src, boolean recursive, VersionSourceInformation versions) throws IOException, FHIRException, Exception {
|
||||
Map<String, byte[]> source = loadIgSourceForVersion(src, recursive, true, versions);
|
||||
if (source != null && source.containsKey("version.info"))
|
||||
versions.see(readInfoVersion(source.get("version.info")), "version.info in "+src);
|
||||
}
|
||||
|
||||
public void loadIg(String src, boolean recursive) throws IOException, FHIRException {
|
||||
NpmPackage npm = src.matches(FilesystemPackageCacheManager.PACKAGE_REGEX) ? pcm.loadPackage(src, null) : null;
|
||||
if (npm != null) {
|
||||
for (String s : npm.dependencies()) {
|
||||
|
@ -834,7 +1008,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return r;
|
||||
}
|
||||
|
||||
public Resource loadResourceByVersion(String version, byte[] content, String fn) throws IOException, Exception {
|
||||
public Resource loadResourceByVersion(String version, byte[] content, String fn) throws IOException, FHIRException {
|
||||
Resource r;
|
||||
if (version.startsWith("3.0")) {
|
||||
org.hl7.fhir.dstu3.model.Resource res;
|
||||
|
@ -845,7 +1019,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
res = new org.hl7.fhir.dstu3.utils.StructureMapUtilities(null).parse(new String(content));
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
r = VersionConvertor_30_50.convertResource(res, false);
|
||||
} else if (version.startsWith("4.0")) {
|
||||
org.hl7.fhir.r4.model.Resource res;
|
||||
|
@ -856,7 +1030,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
res = new org.hl7.fhir.r4.utils.StructureMapUtilities(null).parse(new String(content), fn);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
r = VersionConvertor_40_50.convertResource(res);
|
||||
} else if (version.startsWith("1.4")) {
|
||||
org.hl7.fhir.dstu2016may.model.Resource res;
|
||||
|
@ -865,7 +1039,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
res = new org.hl7.fhir.dstu2016may.formats.JsonParser().parse(new ByteArrayInputStream(content));
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
r = VersionConvertor_14_50.convertResource(res);
|
||||
} else if (version.startsWith("1.0")) {
|
||||
org.hl7.fhir.dstu2.model.Resource res;
|
||||
|
@ -874,7 +1048,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
res = new org.hl7.fhir.dstu2.formats.JsonParser().parse(new ByteArrayInputStream(content));
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
VersionConvertorAdvisor50 advisor = new org.hl7.fhir.convertors.misc.IGR2ConvertorAdvisor5();
|
||||
r = VersionConvertor_10_50.convertResource(res, advisor);
|
||||
} else if (version.equals(Constants.VERSION) || "current".equals(version)) {
|
||||
|
@ -887,9 +1061,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
r = new org.hl7.fhir.r5.utils.StructureMapUtilities(null).parse(new String(content), fn);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else
|
||||
throw new Exception("Unsupported version "+version);
|
||||
throw new FHIRException("Unsupported version "+version);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -923,11 +1097,11 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
FhirFormat cntType = null;
|
||||
}
|
||||
|
||||
public Content loadContent(String source, String opName) throws Exception {
|
||||
public Content loadContent(String source, String opName) throws FHIRException, IOException {
|
||||
Map<String, byte[]> s = loadIgSource(source, false, false);
|
||||
Content res = new Content();
|
||||
if (s.size() != 1)
|
||||
throw new Exception("Unable to find resource " + source + " to "+opName);
|
||||
throw new FHIRException("Unable to find resource " + source + " to "+opName);
|
||||
for (Entry<String, byte[]> t: s.entrySet()) {
|
||||
res.focus = t.getValue();
|
||||
if (t.getKey().endsWith(".json"))
|
||||
|
@ -939,13 +1113,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (t.getKey().endsWith(".txt") || t.getKey().endsWith(".map"))
|
||||
res.cntType = FhirFormat.TEXT;
|
||||
else
|
||||
throw new Exception("Todo: Determining resource type is not yet done");
|
||||
throw new FHIRException("Todo: Determining resource type is not yet done");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// testing entry point
|
||||
public OperationOutcome validate(FhirFormat format, InputStream stream, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(FhirFormat format, InputStream stream, List<String> profiles) throws FHIRException, IOException, EOperationOutcome {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
InstanceValidator validator = getValidator();
|
||||
validator.validate(null, messages, stream, format, asSdList(profiles));
|
||||
|
@ -966,13 +1140,13 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return list;
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String source, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(String source, List<String> profiles) throws FHIRException, IOException {
|
||||
List<String> l = new ArrayList<String>();
|
||||
l.add(source);
|
||||
return (OperationOutcome)validate(l, profiles);
|
||||
}
|
||||
|
||||
public List<ScanOutputItem> validateScan(List<String> sources, Set<String> guides) throws Exception {
|
||||
public List<ScanOutputItem> validateScan(List<String> sources, Set<String> guides) throws FHIRException, IOException, EOperationOutcome {
|
||||
List<String> refs = new ArrayList<String>();
|
||||
handleSources(sources, refs);
|
||||
|
||||
|
@ -1048,7 +1222,28 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Resource validate(List<String> sources, List<String> profiles) throws Exception {
|
||||
public void scanForVersions(List<String> sources, VersionSourceInformation versions) throws FHIRException, IOException {
|
||||
List<String> refs = new ArrayList<String>();
|
||||
handleSources(sources, refs);
|
||||
for (String ref : refs) {
|
||||
Content cnt = loadContent(ref, "validate");
|
||||
String s = TextFile.bytesToString(cnt.focus);
|
||||
if (s.contains("http://hl7.org/fhir/3.0")) {
|
||||
versions.see("3.0", "Profile in "+ref);
|
||||
}
|
||||
if (s.contains("http://hl7.org/fhir/1.0")) {
|
||||
versions.see("1.0", "Profile in "+ref);
|
||||
}
|
||||
if (s.contains("http://hl7.org/fhir/4.0")) {
|
||||
versions.see("4.0", "Profile in "+ref);
|
||||
}
|
||||
if (s.contains("http://hl7.org/fhir/1.4")) {
|
||||
versions.see("1.4", "Profile in "+ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Resource validate(List<String> sources, List<String> profiles) throws FHIRException, IOException {
|
||||
List<String> refs = new ArrayList<String>();
|
||||
boolean asBundle = handleSources(sources, refs);
|
||||
Bundle results = new Bundle();
|
||||
|
@ -1065,7 +1260,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
results.addEntry().setResource(outcome);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Validation Infrastructure fail validating "+ref+": "+e.getMessage());
|
||||
throw e;
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
}
|
||||
if (asBundle)
|
||||
|
@ -1082,7 +1277,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
public OperationOutcome validateString(String location, String source, FhirFormat format, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validateString(String location, String source, FhirFormat format, List<String> profiles) throws FHIRException, IOException, EOperationOutcome, SAXException {
|
||||
return validate(location, source.getBytes(), format, profiles);
|
||||
}
|
||||
|
||||
|
@ -1136,14 +1331,14 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return isBundle;
|
||||
}
|
||||
|
||||
public OperationOutcome validate(byte[] source, FhirFormat cntType, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(byte[] source, FhirFormat cntType, List<String> profiles) throws FHIRException, IOException, EOperationOutcome {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
InstanceValidator validator = getValidator();
|
||||
validator.validate(null, messages, new ByteArrayInputStream(source), cntType, asSdList(profiles));
|
||||
return messagesToOutcome(messages);
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles) throws Exception {
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles) throws FHIRException, IOException, EOperationOutcome, SAXException {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
if (doNative) {
|
||||
if (cntType == FhirFormat.JSON)
|
||||
|
@ -1161,7 +1356,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return messagesToOutcome(messages);
|
||||
}
|
||||
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles, IdStatus resourceIdRule, boolean anyExtensionsAllowed, BestPracticeWarningLevel bpWarnings, CheckDisplayOption displayOption) throws Exception {
|
||||
public OperationOutcome validate(String location, byte[] source, FhirFormat cntType, List<String> profiles, IdStatus resourceIdRule, boolean anyExtensionsAllowed, BestPracticeWarningLevel bpWarnings, CheckDisplayOption displayOption) throws FHIRException, IOException, EOperationOutcome, SAXException {
|
||||
List<ValidationMessage> messages = new ArrayList<ValidationMessage>();
|
||||
if (doNative) {
|
||||
if (cntType == FhirFormat.JSON)
|
||||
|
@ -1254,12 +1449,12 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return issue.getSeverity().toString()+" @ "+issue.getLocation() + " " +issue.getDetails().getText() +(source != null ? " (src = "+source+")" : "");
|
||||
}
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(String source, String map) throws Exception {
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(String source, String map) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
return transform(cnt.focus, cnt.cntType, map);
|
||||
}
|
||||
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(byte[] source, FhirFormat cntType, String mapUri) throws Exception {
|
||||
public org.hl7.fhir.r5.elementmodel.Element transform(byte[] source, FhirFormat cntType, String mapUri) throws FHIRException, IOException {
|
||||
List<Base> outputs = new ArrayList<Base>();
|
||||
|
||||
StructureMapUtilities scu = new StructureMapUtilities(context, new TransformSupportServices(outputs));
|
||||
|
@ -1299,7 +1494,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return Manager.build(getContext(), structureDefinition);
|
||||
}
|
||||
|
||||
public DomainResource generate(String source, String version) throws Exception {
|
||||
public DomainResource generate(String source, String version) throws FHIRException, IOException, EOperationOutcome {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
Resource res = loadResourceByVersion(version, cnt.focus, source);
|
||||
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
|
||||
|
@ -1307,25 +1502,25 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
return (DomainResource) res;
|
||||
}
|
||||
|
||||
public void convert(String source, String output) throws Exception {
|
||||
public void convert(String source, String output) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
Element e = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
|
||||
Manager.compose(context, e, new FileOutputStream(output), (output.endsWith(".json") ? FhirFormat.JSON : FhirFormat.XML), OutputStyle.PRETTY, null);
|
||||
}
|
||||
|
||||
public String evaluateFhirPath(String source, String expression) throws Exception {
|
||||
public String evaluateFhirPath(String source, String expression) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
FHIRPathEngine fpe = new FHIRPathEngine(context);
|
||||
Element e = Manager.parse(context, new ByteArrayInputStream(cnt.focus), cnt.cntType);
|
||||
return fpe.evaluateToString(e, expression);
|
||||
}
|
||||
|
||||
public StructureDefinition snapshot(String source, String version) throws Exception {
|
||||
public StructureDefinition snapshot(String source, String version) throws FHIRException, IOException {
|
||||
Content cnt = loadContent(source, "validate");
|
||||
Resource res = loadResourceByVersion(version, cnt.focus, Utilities.getFileNameForName(source));
|
||||
|
||||
if (!(res instanceof StructureDefinition))
|
||||
throw new Exception("Require a StructureDefinition for generating a snapshot");
|
||||
throw new FHIRException("Require a StructureDefinition for generating a snapshot");
|
||||
StructureDefinition sd = (StructureDefinition) res;
|
||||
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
|
||||
|
||||
|
@ -1670,8 +1865,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
|
||||
@Override
|
||||
public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException {
|
||||
if (!url.startsWith("http://hl7.org/fhir"))
|
||||
return true; // we don't bother with those.
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) { // ignore these
|
||||
return true;
|
||||
}
|
||||
if (context.fetchResource(Resource.class, url) != null)
|
||||
return true;
|
||||
if (Utilities.existsInList(url, "http://hl7.org/fhir/sid/us-ssn", "http://hl7.org/fhir/sid/cvx", "http://hl7.org/fhir/sid/ndc", "http://hl7.org/fhir/sid/us-npi", "http://hl7.org/fhir/sid/icd-10",
|
||||
|
@ -1679,6 +1875,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
"http://hl7.org/fhir/workflow", "http://hl7.org/fhir/ConsentPolicy/opt-out", "http://hl7.org/fhir/ConsentPolicy/opt-in")) {
|
||||
return true;
|
||||
}
|
||||
if (Utilities.existsInList(url, "http://loinc.org", "http://unitsofmeasure.org", "http://snomed.info/sct")) {
|
||||
return true;
|
||||
}
|
||||
if (fetcher != null) {
|
||||
return fetcher.resolveURL(appContext, path, url);
|
||||
};
|
||||
|
@ -1690,7 +1889,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
this.locale = locale;
|
||||
}
|
||||
|
||||
public void handleOutput(Resource r, String output, String version) throws Exception {
|
||||
public void handleOutput(Resource r, String output, String version) throws FHIRException, IOException {
|
||||
if (output.startsWith("http://") || output.startsWith("http://")) {
|
||||
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
||||
handleOutputToStream(r, output, bs, version);
|
||||
|
@ -1719,7 +1918,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleOutputToStream(Resource r, String fn, OutputStream s, String version) throws Exception {
|
||||
private void handleOutputToStream(Resource r, String fn, OutputStream s, String version) throws FHIRException, IOException {
|
||||
if (fn.endsWith(".html") || fn.endsWith(".htm") && r instanceof DomainResource)
|
||||
new XhtmlComposer(XhtmlComposer.HTML, true).compose(s, ((DomainResource) r).getText().getDiv());
|
||||
else if (version.startsWith("3.0")) {
|
||||
|
@ -1731,7 +1930,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
TextFile.stringToStream(org.hl7.fhir.dstu3.utils.StructureMapUtilities.render((org.hl7.fhir.dstu3.model.StructureMap) res), s, false);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.startsWith("4.0")) {
|
||||
org.hl7.fhir.r4.model.Resource res = VersionConvertor_40_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
|
@ -1741,7 +1940,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
TextFile.stringToStream(org.hl7.fhir.r4.utils.StructureMapUtilities.render((org.hl7.fhir.r4.model.StructureMap) res), s, false);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.startsWith("1.4")) {
|
||||
org.hl7.fhir.dstu2016may.model.Resource res = VersionConvertor_14_50.convertResource(r);
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
|
@ -1749,7 +1948,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
new org.hl7.fhir.dstu2016may.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2016may.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.startsWith("1.0")) {
|
||||
VersionConvertorAdvisor50 advisor = new org.hl7.fhir.convertors.misc.IGR2ConvertorAdvisor5();
|
||||
org.hl7.fhir.dstu2.model.Resource res = VersionConvertor_10_50.convertResource(r, advisor);
|
||||
|
@ -1758,7 +1957,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".json") && !fn.endsWith("template.json"))
|
||||
new org.hl7.fhir.dstu2.formats.JsonParser().setOutputStyle(org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY).compose(s, res);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else if (version.equals(Constants.VERSION)) {
|
||||
if (fn.endsWith(".xml") && !fn.endsWith("template.xml"))
|
||||
new XmlParser().setOutputStyle(org.hl7.fhir.r5.formats.IParser.OutputStyle.PRETTY).compose(s, r);
|
||||
|
@ -1767,9 +1966,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
else if (fn.endsWith(".txt") || fn.endsWith(".map") )
|
||||
TextFile.stringToStream(org.hl7.fhir.r5.utils.StructureMapUtilities.render((org.hl7.fhir.r5.model.StructureMap) r), s, false);
|
||||
else
|
||||
throw new Exception("Unsupported format for "+fn);
|
||||
throw new FHIRException("Unsupported format for "+fn);
|
||||
} else
|
||||
throw new Exception("Encounted unsupported configured version "+version+" loading "+fn);
|
||||
throw new FHIRException("Encounted unsupported configured version "+version+" loading "+fn);
|
||||
|
||||
s.close();
|
||||
}
|
||||
|
@ -1833,7 +2032,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
return convertVersionNativeR4(targetVer, cnt, format);
|
||||
} else {
|
||||
throw new Exception("Source version not supported yet: "+version);
|
||||
throw new FHIRException("Source version not supported yet: "+version);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Conversion failed using Java convertor: "+e.getMessage());
|
||||
|
@ -1940,7 +2139,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2009,7 +2208,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2078,7 +2277,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2147,7 +2346,7 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
throw new FHIRException("Unsupported output format: "+cnt.cntType.toString());
|
||||
}
|
||||
} else {
|
||||
throw new Exception("Target Version not supported yet: "+targetVer);
|
||||
throw new FHIRException("Target Version not supported yet: "+targetVer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2166,4 +2365,9 @@ public class ValidationEngine implements IValidatorResourceFetcher {
|
|||
|
||||
}
|
||||
|
||||
public FilesystemPackageCacheManager getPcm() {
|
||||
return pcm;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -65,6 +65,7 @@ import org.hl7.fhir.r5.model.ImplementationGuide;
|
|||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.cli.ValidatorGui;
|
||||
import org.hl7.fhir.validation.cli.services.ComparisonService;
|
||||
import org.hl7.fhir.validation.cli.services.ValidationService;
|
||||
|
@ -171,6 +172,10 @@ public class Validator {
|
|||
Display.printCliArgumentsAndInfo(args);
|
||||
cliContext = Params.loadCliContext(args);
|
||||
|
||||
if (cliContext.getSv() == null) {
|
||||
cliContext.setSv(determineVersion(cliContext));
|
||||
}
|
||||
|
||||
// Comment this out because definitions filename doesn't necessarily contain version (and many not even be 14 characters long). Version gets spit out a couple of lines later after we've loaded the context
|
||||
String definitions = VersionUtilities.packageForVersion(cliContext.getSv()) + "#" + VersionUtilities.getCurrentVersion(cliContext.getSv());
|
||||
ValidationEngine validator = ValidationService.getValidator(cliContext, definitions);
|
||||
|
@ -204,5 +209,27 @@ public class Validator {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String determineVersion(CliContext cliContext) throws Exception {
|
||||
if (cliContext.getMode() != EngineMode.VALIDATION) {
|
||||
return "current";
|
||||
}
|
||||
System.out.println("Scanning for versions (no -version parameter):");
|
||||
VersionSourceInformation versions = ValidationService.scanForVersions(cliContext);
|
||||
for (String s : versions.getReport()) {
|
||||
System.out.println(" "+s);
|
||||
}
|
||||
if (versions.isEmpty()) {
|
||||
System.out.println("-> Using Default version '"+VersionUtilities.CURRENT_VERSION+"'");
|
||||
return "current";
|
||||
}
|
||||
if (versions.size() == 1) {
|
||||
System.out.println("-> use version "+versions.version());
|
||||
return versions.version();
|
||||
}
|
||||
throw new Exception("-> Multiple versions found. Specify a particular version using the -version parameter");
|
||||
}
|
||||
|
||||
}
|
|
@ -36,7 +36,7 @@ public class CliContext {
|
|||
@JsonProperty("txServer")
|
||||
private String txServer = "http://tx.fhir.org";
|
||||
@JsonProperty("sv")
|
||||
private String sv = "current";
|
||||
private String sv = null;
|
||||
@JsonProperty("txLog")
|
||||
private String txLog = null;
|
||||
@JsonProperty("mapLog")
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package org.hl7.fhir.validation.cli.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Locale;
|
||||
|
||||
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.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
|
||||
import org.hl7.fhir.utilities.cache.BasePackageCacheManager;
|
||||
import org.hl7.fhir.utilities.cache.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.cache.NpmPackage;
|
||||
import org.hl7.fhir.validation.cli.services.StandAloneValidatorFetcher.IPackageInstaller;
|
||||
|
||||
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
|
||||
|
||||
public interface IPackageInstaller {
|
||||
public void loadIg(String src, boolean recursive) throws IOException, FHIRException;
|
||||
}
|
||||
|
||||
private BasePackageCacheManager pcm;
|
||||
private IWorkerContext context;
|
||||
private IPackageInstaller installer;
|
||||
|
||||
public StandAloneValidatorFetcher(FilesystemPackageCacheManager pcm, IWorkerContext context, IPackageInstaller installer) {
|
||||
super();
|
||||
this.pcm = pcm;
|
||||
this.context = context;
|
||||
this.installer = installer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url) {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException {
|
||||
if (!Utilities.isAbsoluteUrl(url)) {
|
||||
return false;
|
||||
}
|
||||
// if we've got to here, it's a reference to a FHIR URL. We're going to try to resolve it on the fly
|
||||
|
||||
// first possibility: it's a reference to a version specific URL http://hl7.org/fhir/X.X/...
|
||||
VersionURLInfo vu = VersionUtilities.parseVersionUrl(url);
|
||||
if (vu != null) {
|
||||
NpmPackage pi = pcm.loadPackage(VersionUtilities.packageForVersion(vu.getVersion()), VersionUtilities.getCurrentVersion(vu.getVersion()));
|
||||
return pi.hasCanonical(vu.getUrl());
|
||||
}
|
||||
|
||||
// ok maybe it's a reference to a package we know
|
||||
String base = findBaseUrl(url);
|
||||
String pid = pcm.getPackageId(base);
|
||||
if (url.contains("|")) {
|
||||
pid = pid+"#"+url.substring(url.indexOf("|")+1);
|
||||
}
|
||||
if (pid != null) {
|
||||
installer.loadIg(pid, false);
|
||||
NpmPackage pi = pcm.loadPackage(pid);
|
||||
return pi.hasCanonical(url);
|
||||
}
|
||||
|
||||
if (!url.startsWith("http://hl7.org/fhir")) {
|
||||
return true; // we don't bother with those in the standalone validator - we assume they are valid
|
||||
}
|
||||
|
||||
// we assume it's invalid at this point
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private String findBaseUrl(String url) {
|
||||
String[] p = url.split("\\/");
|
||||
for (int i = 1; i< p.length; i++) {
|
||||
if (Utilities.existsInList(p[i], context.getResourceNames())) {
|
||||
StringBuilder b = new StringBuilder(p[0]);
|
||||
for (int j = 1; j < i; j++) {
|
||||
b.append("/");
|
||||
b.append(p[j]);
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] fetchRaw(String url) throws MalformedURLException, IOException {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale locale) {
|
||||
throw new Error("Not done yet");
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
|
|||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.validation.ValidationEngine;
|
||||
import org.hl7.fhir.validation.ValidationEngine.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.cli.model.*;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -52,6 +53,15 @@ public class ValidationService {
|
|||
return response;
|
||||
}
|
||||
|
||||
public static VersionSourceInformation scanForVersions(CliContext cliContext) throws Exception {
|
||||
VersionSourceInformation versions = new VersionSourceInformation();
|
||||
ValidationEngine ve = new ValidationEngine();
|
||||
for (String src : cliContext.getIgs()) {
|
||||
ve.scanForIgVersion(src, cliContext.isRecursive(), versions);
|
||||
}
|
||||
ve.scanForVersions(cliContext.getSources(), versions);
|
||||
return versions;
|
||||
}
|
||||
public static void validateSources(CliContext cliContext, ValidationEngine validator, long loadStart) throws Exception {
|
||||
validator.doneLoading(loadStart);
|
||||
if (cliContext.getProfiles().size() > 0) {
|
||||
|
@ -205,6 +215,7 @@ public class ValidationService {
|
|||
validator.setSecurityChecks(cliContext.isSecurityChecks());
|
||||
validator.setCrumbTrails(cliContext.isCrumbTrails());
|
||||
validator.setShowTimes(cliContext.isShowTimes());
|
||||
validator.setFetcher(new StandAloneValidatorFetcher(validator.getPcm(), validator.getContext(), validator));
|
||||
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
|
||||
return validator;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
|||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.Utilities.DecimalStatus;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities.VersionURLInfo;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
|
@ -592,8 +593,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
throw new FHIRException(e1);
|
||||
}
|
||||
timeTracker.load(t);
|
||||
if (e != null)
|
||||
if (e != null) {
|
||||
validate(appContext, errors, e, profiles);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -1852,15 +1854,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, url.startsWith("#") || Utilities.isAbsoluteUrl(url), I18nConstants.TYPE_SPECIFIC_CHECKS_CANONICAL_ABSOLUTE, url);
|
||||
}
|
||||
|
||||
// now, do we check the URI target?
|
||||
if (fetcher != null) {
|
||||
boolean found;
|
||||
try {
|
||||
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com"))) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url);
|
||||
} catch (IOException e1) {
|
||||
found = false;
|
||||
if (isCanonicalURLElement(e)) {
|
||||
// for now, no validation. Need to think about authority.
|
||||
} else {
|
||||
// now, do we check the URI target?
|
||||
if (fetcher != null) {
|
||||
boolean found;
|
||||
try {
|
||||
found = isDefinitionURL(url) || (allowExamples && (url.contains("example.org") || url.contains("acme.com")) || url.contains("acme.org")) || (url.startsWith("http://hl7.org/fhir/tools")) || fetcher.resolveURL(appContext, path, url);
|
||||
} catch (IOException e1) {
|
||||
found = false;
|
||||
}
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
|
||||
}
|
||||
rule(errors, IssueType.INVALID, e.line(), e.col(), path, found, I18nConstants.TYPE_SPECIFIC_CHECKS_DT_URL_RESOLVE, url);
|
||||
}
|
||||
}
|
||||
if (type.equals(ID)) {
|
||||
|
@ -2007,6 +2013,24 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// for nothing to check
|
||||
}
|
||||
|
||||
private boolean isCanonicalURLElement(Element e) {
|
||||
if (e.getProperty() == null || e.getProperty().getDefinition() == null) {
|
||||
return false;
|
||||
}
|
||||
String path = e.getProperty().getDefinition().getBase().getPath();
|
||||
if (path == null) {
|
||||
return false;
|
||||
}
|
||||
String[] p = path.split("\\.");
|
||||
if (p.length != 2) {
|
||||
return false;
|
||||
}
|
||||
if (!"url".equals(p[1])) {
|
||||
return false;
|
||||
}
|
||||
return Utilities.existsInList(p[0], VersionUtilities.getCanonicalResourceNames(context.getVersion()));
|
||||
}
|
||||
|
||||
private boolean containsHtmlTags(String cnt) {
|
||||
int i = cnt.indexOf("<");
|
||||
while (i > -1) {
|
||||
|
@ -2928,7 +2952,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return rr;
|
||||
}
|
||||
}
|
||||
if (stack.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY) {
|
||||
if (stack.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || stack.getElement().getSpecial() == SpecialElement.PARAMETER) {
|
||||
return null; // we don't try to resolve contained references across this boundary
|
||||
}
|
||||
stack = stack.getParent();
|
||||
|
@ -2963,6 +2987,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return rr;
|
||||
}
|
||||
}
|
||||
if (stack.getElement().getSpecial() == SpecialElement.PARAMETER && stack.getParent() != null) {
|
||||
NodeStack tgt = findInParams(stack.getParent().getParent(), ref);
|
||||
if (tgt != null) {
|
||||
ResolvedReference rr = new ResolvedReference();
|
||||
rr.setResource(tgt.getElement());
|
||||
rr.setFocus(tgt.getElement());
|
||||
rr.setExternal(false);
|
||||
rr.setStack(tgt);
|
||||
rr.getStack().qualifyPath(".ofType("+tgt.getElement().fhirType()+")");
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
stack = stack.getParent();
|
||||
}
|
||||
// we can get here if we got called via FHIRPath conformsTo which breaks the stack continuity.
|
||||
|
@ -2989,6 +3025,42 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return null;
|
||||
}
|
||||
|
||||
private NodeStack findInParams(NodeStack params, String ref) {
|
||||
int i = 0;
|
||||
for (Element child : params.getElement().getChildren("parameter")) {
|
||||
NodeStack p = params.push(child, i, child.getProperty().getDefinition(), child.getProperty().getDefinition());
|
||||
if (child.hasChild("resource")) {
|
||||
Element res = child.getNamedChild("resource");
|
||||
if ((res.fhirType()+"/"+res.getIdBase()).equals(ref)) {
|
||||
return p.push(res, -1, res.getProperty().getDefinition(), res.getProperty().getDefinition());
|
||||
}
|
||||
}
|
||||
NodeStack pc = findInParamParts(p, child, ref);
|
||||
if (pc != null) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private NodeStack findInParamParts(NodeStack pp, Element param, String ref) {
|
||||
int i = 0;
|
||||
for (Element child : param.getChildren("part")) {
|
||||
NodeStack p = pp.push(child, i, child.getProperty().getDefinition(), child.getProperty().getDefinition());
|
||||
if (child.hasChild("resource")) {
|
||||
Element res = child.getNamedChild("resource");
|
||||
if ((res.fhirType()+"/"+res.getIdBase()).equals(ref)) {
|
||||
return p.push(res, -1, res.getProperty().getDefinition(), res.getProperty().getDefinition());
|
||||
}
|
||||
}
|
||||
NodeStack pc = findInParamParts(p, child, ref);
|
||||
if (pc != null) {
|
||||
return pc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Element getEntryForSource(Element bundle, Element element) {
|
||||
List<Element> entries = new ArrayList<Element>();
|
||||
bundle.getNamedChildren(ENTRY, entries);
|
||||
|
@ -3432,7 +3504,18 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
for (Element profile : profiles) {
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, profile.primitiveValue());
|
||||
if (!defn.getUrl().equals(profile.primitiveValue())) {
|
||||
if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", sd != null, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN, profile.primitiveValue())) {
|
||||
// is this a version specific reference?
|
||||
VersionURLInfo vu = VersionUtilities.parseVersionUrl(profile.primitiveValue());
|
||||
if (vu != null) {
|
||||
if (!VersionUtilities.versionsCompatible(vu.getVersion(), context.getVersion())) {
|
||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_OTHER_VERSION, vu.getVersion());
|
||||
} else if (vu.getUrl().equals(defn.getUrl())) {
|
||||
hint(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_THIS_VERSION_OK);
|
||||
} else {
|
||||
StructureDefinition sdt = context.fetchResource(StructureDefinition.class, vu.getUrl());
|
||||
rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", false, I18nConstants.VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER, sdt == null ? "null" : sdt.getType());
|
||||
}
|
||||
} else if (warning(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath() + ".meta.profile[" + i + "]", sd != null, I18nConstants.VALIDATION_VAL_PROFILE_UNKNOWN, profile.primitiveValue())) {
|
||||
signpost(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), !crumbTrails, I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_META, sd.getUrl());
|
||||
stack.resetIds();
|
||||
startInner(hostContext, errors, resource, element, sd, stack, false);
|
||||
|
@ -3658,9 +3741,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if (trr == null) {
|
||||
rule(errors, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_TYPE, resourceName);
|
||||
} else if (isValidResourceType(resourceName, trr)) {
|
||||
long t = System.nanoTime();
|
||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + resourceName);
|
||||
timeTracker.sd(t);
|
||||
// special case: resource wrapper is reset if we're crossing a bundle boundary, but not otherwise
|
||||
ValidatorHostContext hc = null;
|
||||
if (element.getSpecial() == SpecialElement.BUNDLE_ENTRY || element.getSpecial() == SpecialElement.BUNDLE_OUTCOME || element.getSpecial() == SpecialElement.PARAMETER) {
|
||||
|
@ -3669,10 +3749,29 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else {
|
||||
hc = hostContext.forContained(element);
|
||||
}
|
||||
trackUsage(profile, hostContext, element);
|
||||
stack.resetIds();
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
if (trr.getProfile().size() == 1) {
|
||||
long t = System.nanoTime();
|
||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, trr.getProfile().get(0).asStringValue());
|
||||
timeTracker.sd(t);
|
||||
trackUsage(profile, hostContext, element);
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
}
|
||||
} else if (trr.getProfile().size() == 0) {
|
||||
long t = System.nanoTime();
|
||||
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + resourceName);
|
||||
timeTracker.sd(t);
|
||||
trackUsage(profile, hostContext, element);
|
||||
if (rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), profile != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOPROFILE, resourceName)) {
|
||||
validateResource(hc, errors, resource, element, profile, idstatus, stack);
|
||||
}
|
||||
} else {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
for (CanonicalType u : trr.getProfile()) {
|
||||
b.append(u.asStringValue());
|
||||
}
|
||||
rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES, trr.getCode(), b.toString());
|
||||
}
|
||||
} else {
|
||||
List<String> types = new ArrayList<>();
|
||||
|
|
|
@ -107,7 +107,7 @@ public class ComparisonTests {
|
|||
System.out.println("---- Set up Output ----------------------------------------------------------");
|
||||
Utilities.createDirectory(Utilities.path("[tmp]", "comparison"));
|
||||
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
|
||||
NpmPackage npm = pcm.loadPackage("hl7.fhir.pubpack", "0.0.6");
|
||||
NpmPackage npm = pcm.loadPackage("hl7.fhir.pubpack", "0.0.7");
|
||||
for (String f : npm.list("other")) {
|
||||
TextFile.streamToFile(npm.load("other", f), Utilities.path("[tmp]", "comparison", f));
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class ProfileComparisonTests {
|
|||
// ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2");
|
||||
// ve.loadIg("hl7.fhir.us.core#1.0.1", false);
|
||||
// ve.loadIg("hl7.fhir.au.base#current", false);
|
||||
// ve.getContext().loadFromPackage(new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.pubpack", "0.0.4"), new R5ToR5Loader(new String[] {"Binary"}), "Binary");
|
||||
// ve.getContext().loadFromPackage(new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.pubpack", "0.0.7"), new R5ToR5Loader(new String[] {"Binary"}), "Binary");
|
||||
//
|
||||
//
|
||||
// String left = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient";
|
||||
|
|
|
@ -457,7 +457,7 @@ public class ValidationTestSuite implements IEvaluationContext, IValidatorResour
|
|||
|
||||
@Override
|
||||
public boolean resolveURL(Object appContext, String path, String url) throws IOException, FHIRException {
|
||||
return !url.contains("example.org");
|
||||
return !url.contains("example.org") && !url.startsWith("http://hl7.org/fhir/invalid");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue