Merge pull request #650 from hapifhir/gg-202111-renderer-n-http

Gg 202111 renderer n http
This commit is contained in:
Grahame Grieve 2021-11-10 06:18:56 +11:00 committed by GitHub
commit 9b868d3af3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 3405 additions and 377 deletions

View File

@ -1,2 +1,9 @@
Validator Changes
* none
Other Code Changes
* Updating client logger to log both req and resp
* Refactoring of converter loader and misc packages.
* rework all HTTP access through a single access point (todo: refactor this to use okhttp)
* Improvements to rendering for IG publication

View File

@ -1,5 +1,8 @@
package org.hl7.fhir.convertors.misc;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
@ -39,10 +42,10 @@ import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@ -122,13 +125,10 @@ public class CKMImporter {
}
private Document loadXml(String address) throws Exception {
URL url = new URL(address);
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
InputStream xml = connection.getInputStream();
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(address, "application/xml");
res.checkThrowException();
InputStream xml = new ByteArrayInputStream(res.getContent());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

View File

@ -122,7 +122,10 @@ public class DicomPackageBuilder {
npm.addProperty("version", version);
JsonArray fv = new JsonArray();
npm.add("fhirVersions", fv);
fv.add("4.0");
fv.add("4.0.1");
JsonObject dep = new JsonObject();
npm.add("dependencies", dep);
dep.addProperty("hl7.fhir.r4.core", "4.0.1");
return npm;
}

View File

@ -17,11 +17,13 @@ import org.hl7.fhir.r4.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r4.utils.ToolingExtensions;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@ -388,12 +390,12 @@ public class ICD11Generator {
private JsonObject fetchJson(String source) throws IOException {
URL url = new URL(source);
URLConnection c = url.openConnection();
c.addRequestProperty("Accept", "application/json");
c.addRequestProperty("API-Version", "v2");
c.addRequestProperty("Accept-Language", "en");
return (JsonObject) new com.google.gson.JsonParser().parse(TextFile.streamToString(c.getInputStream()));
SimpleHTTPClient http = new SimpleHTTPClient();
http.addHeader("API-Version", "v2");
http.addHeader("Accept-Language", "en");
HTTPResult res = http.get(source, "application/json");
res.checkThrowException();
return JsonTrackingParser.parseJson(res.getContent());
}

View File

@ -159,4 +159,9 @@ public class TerminologyClientR2 implements TerminologyClient {
client.setUserAgent(userAgent);
return this;
}
@Override
public String getServerVersion() {
return client.getServerVersion();
}
}

View File

@ -168,4 +168,9 @@ public class TerminologyClientR3 implements TerminologyClient {
client.setUserAgent(userAgent);
return this;
}
@Override
public String getServerVersion() {
return client.getServerVersion();
}
}

View File

@ -168,4 +168,9 @@ public class TerminologyClientR4 implements TerminologyClient {
client.setUserAgent(userAgent);
return this;
}
@Override
public String getServerVersion() {
return client.getServerVersion();
}
}

View File

@ -154,4 +154,9 @@ public class TerminologyClientR5 implements TerminologyClient {
client.setUserAgent(userAgent);
return this;
}
@Override
public String getServerVersion() {
return client.getServerVersion();
}
}

View File

@ -866,4 +866,8 @@ public class FHIRToolingClient {
public void setUserAgent(String userAgent) {
utils.setUserAgent(userAgent);
}
public String getServerVersion() {
return conf == null ? null : conf.getSoftware().getVersion();
}
}

View File

@ -580,5 +580,9 @@ public class FHIRToolingClient {
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public String getServerVersion() {
return capabilities == null ? null : capabilities.getSoftware().getVersion();
}
}

View File

@ -34,7 +34,6 @@ package org.hl7.fhir.r4.conformance;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -70,6 +69,8 @@ import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r4.utils.DefinitionNavigator;
import org.hl7.fhir.r4.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
@ -1283,9 +1284,10 @@ public class ProfileComparer {
File f = new File(local);
if (f.exists())
return TextFile.fileToString(f);
URL url = new URL(source);
URLConnection c = url.openConnection();
String result = TextFile.streamToString(c.getInputStream());
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source);
res.checkThrowException();
String result = TextFile.bytesToString(res.getContent());
TextFile.stringToFile(result, f);
return result;
}

View File

@ -547,5 +547,9 @@ public class FHIRToolingClient {
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public String getServerVersion() {
return capabilities == null ? null : capabilities.getSoftware().getVersion();
}
}

View File

@ -335,7 +335,7 @@ public class ProfileUtilities extends TranslatingUtilities {
private boolean autoFixSliceNames;
private XVerExtensionManager xver;
private boolean wantFixDifferentialFirstElementType;
private List<String> masterSourceFileNames;
private Set<String> masterSourceFileNames;
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
super();
@ -2465,7 +2465,7 @@ public class ProfileUtilities extends TranslatingUtilities {
return element;
}
public static String processRelativeUrls(String markdown, String webUrl, String basePath, List<String> resourceNames, List<String> filenames) {
public static String processRelativeUrls(String markdown, String webUrl, String basePath, List<String> resourceNames, Set<String> filenames) {
StringBuilder b = new StringBuilder();
int i = 0;
while (i < markdown.length()) {
@ -2508,7 +2508,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
public static boolean isLikelySourceURLReference(String url, List<String> resourceNames, List<String> filenames) {
public static boolean isLikelySourceURLReference(String url, List<String> resourceNames, Set<String> filenames) {
if (resourceNames != null) {
for (String n : resourceNames) {
if (url.startsWith(n.toLowerCase()+".html")) {
@ -6669,11 +6669,11 @@ public class ProfileUtilities extends TranslatingUtilities {
return getElementById(structure, structure.getSnapshot().getElement(), element.getContentReference());
}
public List<String> getMasterSourceFileNames() {
public Set<String> getMasterSourceFileNames() {
return masterSourceFileNames;
}
public void setMasterSourceFileNames(List<String> masterSourceFileNames) {
public void setMasterSourceFileNames(Set<String> masterSourceFileNames) {
this.masterSourceFileNames = masterSourceFileNames;
}

View File

@ -44,6 +44,7 @@ public class HTMLClientLogger extends BaseLogger implements ToolingClientLogger
private static final boolean DEBUG = true;
private boolean req = false;
private PrintStream file;
public HTMLClientLogger(String log) {
@ -80,6 +81,7 @@ public class HTMLClientLogger extends BaseLogger implements ToolingClientLogger
}
}
file.println("</pre>");
req = true;
}
@Override
@ -87,8 +89,12 @@ public class HTMLClientLogger extends BaseLogger implements ToolingClientLogger
if (DEBUG) {
System.out.println(" txlog resp: " +outcome+" "+present(body));
}
req = false;
if (file == null)
return;
if (!req) {
System.out.println("Record Response without request");
}
file.println("<pre>");
file.println(outcome);
for (String s : headers)

View File

@ -63,6 +63,8 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
public class DataRenderer extends Renderer {
@ -129,6 +131,56 @@ public class DataRenderer extends Renderer {
// -- 3. General Purpose Terminology Support -----------------------------------------
private static String month(String m) {
switch (m) {
case "1" : return "Jan";
case "2" : return "Feb";
case "3" : return "Mar";
case "4" : return "Apr";
case "5" : return "May";
case "6" : return "Jun";
case "7" : return "Jul";
case "8" : return "Aug";
case "9" : return "Sep";
case "10" : return "Oct";
case "11" : return "Nov";
case "12" : return "Dec";
default: return null;
}
}
public static String describeVersion(String version) {
if (version.startsWith("http://snomed.info/sct")) {
String[] p = version.split("\\/");
String ed = null;
String dt = "";
if (p[p.length-2].equals("version")) {
ed = p[p.length-3];
String y = p[p.length-3].substring(4, 8);
String m = p[p.length-3].substring(2, 4);
dt = " rel. "+month(m)+" "+y;
} else {
ed = p[p.length-1];
}
switch (ed) {
case "900000000000207008": return "Intl"+dt;
case "731000124108": return "US"+dt;
case "32506021000036107": return "AU"+dt;
case "449081005": return "ES"+dt;
case "554471000005108": return "DK"+dt;
case "11000146104": return "NL"+dt;
case "45991000052106": return "SE"+dt;
case "999000041000000102": return "UK"+dt;
case "20611000087101": return "CA"+dt;
case "11000172109": return "BE"+dt;
default: return "??"+dt;
}
} else {
return version;
}
}
public static String describeSystem(String system) {
if (system == null)
return "[not stated]";
@ -282,7 +334,7 @@ public class DataRenderer extends Renderer {
// -- 5. Data type Rendering ----------------------------------------------
public static String display(IWorkerContext context, DataType type) {
return new DataRenderer(new RenderingContext(context, null, null, "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.RESOURCE)).display(type);
return new DataRenderer(new RenderingContext(context, null, null, "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.END_USER)).display(type);
}
public String displayBase(Base b) {
@ -412,6 +464,13 @@ public class DataRenderer extends Renderer {
}
}
public void renderDateTime(XhtmlNode x, String s) {
if (s != null) {
DateTimeType dt = new DateTimeType(s);
x.addText(dt.toHumanDisplay());
}
}
protected void renderUri(XhtmlNode x, UriType uri) {
if (uri.getValue().startsWith("mailto:")) {
x.ah(uri.getValue()).addText(uri.getValue().substring(7));
@ -481,15 +540,53 @@ public class DataRenderer extends Renderer {
public String displayCoding(Coding c) {
String s = "";
if (context.isTechnicalMode()) {
s = c.getDisplay();
if (Utilities.noString(s)) {
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
}
if (Utilities.noString(s)) {
s = displayCodeTriple(c.getSystem(), c.getVersion(), c.getCode());
} else if (c.hasSystem()) {
s = s + " ("+displayCodeTriple(c.getSystem(), c.getVersion(), c.getCode())+")";
} else if (c.hasCode()) {
s = s + " ("+c.getCode()+")";
}
} else {
if (c.hasDisplayElement())
return c.getDisplay();
if (Utilities.noString(s))
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
if (Utilities.noString(s))
s = c.getCode();
}
return s;
}
private String displayCodeSource(String system, String version) {
String s = displaySystem(system);
if (version != null) {
s = s + "["+describeVersion(version)+"]";
}
return s;
}
private String displayCodeTriple(String system, String version, String code) {
if (system == null) {
if (code == null) {
return "";
} else {
return "#"+code;
}
} else {
String s = displayCodeSource(system, version);
if (code != null) {
s = s + "#"+code;
}
return s;
}
}
public String displayCoding(List<Coding> list) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (Coding c : list) {
@ -502,6 +599,48 @@ public class DataRenderer extends Renderer {
renderCoding(x, c, false);
}
protected void renderCoding(HierarchicalTableGenerator gen, List<Piece> pieces, Coding c) {
if (c.isEmpty()) {
return;
}
String url = getLinkForSystem(c.getSystem(), c.getVersion());
String name = displayCodeSource(c.getSystem(), c.getVersion());
if (!Utilities.noString(url)) {
pieces.add(gen.new Piece(url, name, c.getSystem()+(c.hasVersion() ? "#"+c.getVersion() : "")));
} else {
pieces.add(gen.new Piece(null, name, c.getSystem()+(c.hasVersion() ? "#"+c.getVersion() : "")));
}
pieces.add(gen.new Piece(null, "#"+c.getCode(), null));
String s = c.getDisplay();
if (Utilities.noString(s)) {
s = lookupCode(c.getSystem(), c.getVersion(), c.getCode());
}
if (!Utilities.noString(s)) {
pieces.add(gen.new Piece(null, " \""+s+"\"", null));
}
}
private String getLinkForSystem(String system, String version) {
if ("http://snomed.info/sct".equals(system)) {
return "https://browser.ihtsdotools.org/";
} else if ("http://loinc.org".equals(system)) {
return "https://loinc.org/";
} else if ("http://unitsofmeasure.org".equals(system)) {
return "http://ucum.org";
} else {
String url = system;
if (version != null) {
url = url + "|"+version;
}
CodeSystem cs = context.getWorker().fetchCodeSystem(url);
if (cs != null && cs.hasUserData("path")) {
return cs.getUserString("path");
}
return null;
}
}
protected void renderCodingWithDetails(XhtmlNode x, Coding c) {
String s = "";
if (c.hasDisplayElement())
@ -512,7 +651,11 @@ public class DataRenderer extends Renderer {
String sn = describeSystem(c.getSystem());
if ("http://snomed.info/sct".equals(c.getSystem())) {
x.ah("https://browser.ihtsdotools.org/").tx(sn);
if (c.hasCode()) {
x.ah("http://snomed.info/id/"+c.getCode()).tx(sn);
} else {
x.ah("https://browser.ihtsdotools.org/").tx(sn);
}
} else if ("http://loinc.org".equals(c.getSystem())) {
x.ah("https://loinc.org/").tx(sn);
} else {
@ -627,16 +770,27 @@ public class DataRenderer extends Renderer {
if (showCodeDetails) {
x.addText(s+" ");
XhtmlNode sp = x.span("background: LightGoldenRodYellow", null);
sp.tx("(Details ");
XhtmlNode sp = x.span("background: LightGoldenRodYellow; margin: 4px; border: 1px solid khaki", null);
sp.tx(" (");
boolean first = true;
for (Coding c : cc.getCoding()) {
if (first) {
sp.tx(": ");
first = false;
} else
} else {
sp.tx("; ");
sp.tx("{"+TerminologyRenderer.describeSystem(c.getSystem())+" code '"+c.getCode()+"' = '"+lookupCode(c.getSystem(), c.getVersion(), c.getCode())+(c.hasDisplay() ? "', given as '"+c.getDisplay()+"'}" : ""));
}
String url = getLinkForSystem(c.getSystem(), c.getVersion());
if (url != null) {
sp.ah(url).tx(displayCodeSource(c.getSystem(), c.getVersion()));
} else {
sp.tx(displayCodeSource(c.getSystem(), c.getVersion()));
}
if (c.hasCode()) {
sp.tx("#"+c.getCode());
}
if (c.hasDisplay() && !s.equals(c.getDisplay())) {
sp.tx(" \""+c.getDisplay()+"\"");
}
}
sp.tx(")");
} else {

View File

@ -104,6 +104,9 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
if (context.isAddGeneratedNarrativeHeader()) {
x.para().b().tx("Generated Narrative");
}
if (context.isTechnicalMode()) {
renderResourceHeader(r, x);
}
try {
StructureDefinition sd = r.getDefinition();
if (sd == null) {
@ -112,7 +115,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
ElementDefinition ed = sd.getSnapshot().getElement().get(0);
containedIds.clear();
hasExtensions = false;
generateByProfile(r, sd, r.root(), sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), false, 0);
generateByProfile(r, sd, r.root(), sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), context.isTechnicalMode(), 0);
}
} catch (Exception e) {
e.printStackTrace();
@ -121,6 +124,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
return hasExtensions;
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return "todo";
@ -212,7 +216,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
//
public void generateResourceSummary(XhtmlNode x, ResourceWrapper res, boolean textAlready, boolean showCodeDetails) throws FHIRException, UnsupportedEncodingException, IOException {
public void generateResourceSummary(XhtmlNode x, ResourceWrapper res, boolean textAlready, boolean showCodeDetails, boolean canLink) throws FHIRException, UnsupportedEncodingException, IOException {
if (!textAlready) {
XhtmlNode div = res.getNarrative();
if (div != null) {
@ -231,9 +235,9 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
boolean firstElement = true;
boolean last = false;
for (PropertyWrapper p : res.children()) {
if (!ignoreProperty(p)) {
if (!ignoreProperty(p) && !p.getElementDefinition().getBase().getPath().startsWith("Resource.")) {
ElementDefinition child = getElementDefinition(profile.getSnapshot().getElement(), path+"."+p.getName(), p);
if (p.getValues().size() > 0 && p.getValues().get(0) != null && child != null && isPrimitive(child) && includeInSummary(child)) {
if (p.getValues().size() > 0 && p.getValues().get(0) != null && child != null && isPrimitive(child) && includeInSummary(child, p.getValues())) {
if (firstElement)
firstElement = false;
else if (last)
@ -245,7 +249,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
first = false;
else if (last)
x.tx(", ");
last = displayLeaf(res, v, child, x, p.getName(), showCodeDetails, false) || last;
last = displayLeaf(res, v, child, x, p.getName(), showCodeDetails, canLink) || last;
}
}
}
@ -258,7 +262,10 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
return Utilities.existsInList(p.getName(), "contained");
}
private boolean includeInSummary(ElementDefinition child) {
private boolean includeInSummary(ElementDefinition child, List<BaseWrapper> list) throws UnsupportedEncodingException, FHIRException, IOException {
if (child.getName().endsWith("active") && list != null && list.size() > 0 && "true".equals(list.get(0).getBase().primitiveValue())) {
return false;
}
if (child.getIsModifier())
return true;
if (child.getMustSupport())
@ -432,7 +439,12 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
x.addText(name+": "+((IdType) e).getValue());
return true;
} else if (e instanceof UriType) {
x.addText(name+": "+((UriType) e).getValue());
if (Utilities.isAbsoluteUrlLinkable(((UriType) e).getValue()) && allowLinks) {
x.tx(name+": ");
x.ah(((UriType) e).getValue()).addText(((UriType) e).getValue());
} else {
x.addText(name+": "+((UriType) e).getValue());
}
return true;
} else if (e instanceof DateTimeType) {
x.addText(name+": "+((DateTimeType) e).toHumanDisplay());

View File

@ -325,7 +325,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (v.getValue().isPrimitive()) {
defn.getPieces().add(gen.new Piece(null, v.getValue().primitiveValue(), null));
} else {
defn.getPieces().add(gen.new Piece(null, "{todo}", null));
renderCoding(gen, defn.getPieces(), v.getValueCoding());
}
}
}
@ -499,7 +499,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (v.getValue().isPrimitive()) {
defn.getPieces().add(gen.new Piece(null, v.getValue().primitiveValue(), null));
} else {
defn.getPieces().add(gen.new Piece(null, "{todo}", null));
renderCoding(gen, defn.getPieces(), v.getValueCoding());
}
}
}
@ -730,7 +730,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (v.getValue().isPrimitive()) {
vi.tx(v.getValue().primitiveValue());
} else {
vi.tx("{todo}");
renderCoding(vi, v.getValueCoding(), true);
}
}
}

View File

@ -33,7 +33,7 @@ public class Renderer {
}
public Renderer(IWorkerContext worker) {
this.context = new RenderingContext(worker, new MarkDownProcessor(Dialect.COMMON_MARK), ValidationOptions.defaults(), "http://hl7.org/fhir/R5", "", null, ResourceRendererMode.RESOURCE);
this.context = new RenderingContext(worker, new MarkDownProcessor(Dialect.COMMON_MARK), ValidationOptions.defaults(), "http://hl7.org/fhir/R5", "", null, ResourceRendererMode.END_USER);
}

View File

@ -11,6 +11,7 @@ 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;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem;
@ -31,6 +32,7 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@ -195,22 +197,37 @@ public abstract class ResourceRenderer extends DataRenderer {
} else {
c = x.span(null, null);
}
// what to display: if text is provided, then that. if the reference was resolved, then show the generated narrative
if (r.hasDisplayElement()) {
c.addText(r.getDisplay());
if (tr != null && tr.getResource() != null) {
c.tx(". Generated Summary: ");
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, r.getReference().startsWith("#"));
if (tr != null && tr.getReference() != null && tr.getReference().startsWith("#")) {
c.tx("See above (");
}
// what to display: if text is provided, then that. if the reference was resolved, then show the name, or the generated narrative
String display = r.hasDisplayElement() ? r.getDisplay() : null;
String name = tr != null && tr.getResource() != null ? tr.getResource().getNameFromResource() : null;
if (display == null && (tr == null || tr.getResource() == null)) {
c.addText(r.getReference());
} else if (context.isTechnicalMode()) {
c.addText(r.getReference());
if (display != null) {
c.addText(": "+display);
}
} else if (tr != null && tr.getResource() != null) {
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("#"));
if ((tr == null || !tr.getReference().startsWith("#")) && name != null) {
x.addText(" \""+name+"\"");
}
} else {
c.addText(r.getReference());
if (display != null) {
c.addText(display);
} else if (name != null) {
c.addText(name);
} else {
c.tx(". Generated Summary: ");
if (tr != null) {
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, r.getReference().startsWith("#"), true);
}
}
}
if (tr != null && tr.getReference() != null && tr.getReference().startsWith("#")) {
c.tx(")");
}
}
@ -236,10 +253,10 @@ public abstract class ResourceRenderer extends DataRenderer {
c.addText(r.get("display").primitiveValue());
if (tr != null && tr.getResource() != null) {
c.tx(". Generated Summary: ");
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, v.startsWith("#"));
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), true, v.startsWith("#"), false);
}
} else if (tr != null && tr.getResource() != null) {
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), v.startsWith("#"), v.startsWith("#"));
new ProfileDrivenRenderer(context).generateResourceSummary(c, tr.getResource(), v.startsWith("#"), v.startsWith("#"), false);
} else {
c.addText(v);
}
@ -371,4 +388,95 @@ public abstract class ResourceRenderer extends DataRenderer {
return true;
}
protected void renderResourceHeader(ResourceWrapper r, XhtmlNode x) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode div = x.div().style("display: inline-block").style("background-color: #d9e0e7").style("padding: 6px")
.style("margin: 4px").style("border: 1px solid #8da1b4")
.style("border-radius: 5px").style("line-height: 60%");
String id = getPrimitiveValue(r, "id");
String lang = getPrimitiveValue(r, "language");
String ir = getPrimitiveValue(r, "implicitRules");
BaseWrapper meta = r.getChildByName("meta").hasValues() ? r.getChildByName("meta").getValues().get(0) : null;
String versionId = getPrimitiveValue(meta, "versionId");
String lastUpdated = getPrimitiveValue(meta, "lastUpdated");
String source = getPrimitiveValue(meta, "source");
if (id != null || lang != null || versionId != null || lastUpdated != null) {
XhtmlNode p = plateStyle(div.para());
p.tx("Resource ");
if (id != null) {
p.tx("\""+id+"\" ");
}
if (versionId != null) {
p.tx("Version \""+versionId+"\" ");
}
if (lastUpdated != null) {
p.tx("Updated \"");
renderDateTime(p, lastUpdated);
p.tx("\" ");
}
if (lang != null) {
p.tx(" (Language \""+lang+"\") ");
}
}
if (ir != null) {
plateStyle(div.para()).b().tx("Special rules apply: "+ir+"!");
}
if (source != null) {
plateStyle(div.para()).tx("Information Source: "+source+"!");
}
if (meta != null) {
PropertyWrapper pl = meta.getChildByName("profile");
if (pl.hasValues()) {
XhtmlNode p = plateStyle(div.para());
p.tx(Utilities.pluralize("Profile", pl.getValues().size())+": ");
boolean first = true;
for (BaseWrapper bw : pl.getValues()) {
if (first) first = false; else p.tx(", ");
renderCanonical(r, p, bw.getBase().primitiveValue());
}
}
PropertyWrapper tl = meta.getChildByName("tag");
if (tl.hasValues()) {
XhtmlNode p = plateStyle(div.para());
p.tx(Utilities.pluralize("Tag", tl.getValues().size())+": ");
boolean first = true;
for (BaseWrapper bw : tl.getValues()) {
if (first) first = false; else p.tx(", ");
String system = getPrimitiveValue(bw, "system");
String version = getPrimitiveValue(bw, "version");
String code = getPrimitiveValue(bw, "system");
String display = getPrimitiveValue(bw, "system");
renderCoding(p, new Coding(system, version, code, display));
}
}
PropertyWrapper sl = meta.getChildByName("security");
if (sl.hasValues()) {
XhtmlNode p = plateStyle(div.para());
p.tx(Utilities.pluralize("Security Label", tl.getValues().size())+": ");
boolean first = true;
for (BaseWrapper bw : sl.getValues()) {
if (first) first = false; else p.tx(", ");
String system = getPrimitiveValue(bw, "system");
String version = getPrimitiveValue(bw, "version");
String code = getPrimitiveValue(bw, "system");
String display = getPrimitiveValue(bw, "system");
renderCoding(p, new Coding(system, version, code, display));
}
}
}
}
private XhtmlNode plateStyle(XhtmlNode para) {
return para.style("margin-bottom: 0px");
}
private String getPrimitiveValue(BaseWrapper b, String name) throws UnsupportedEncodingException, FHIRException, IOException {
return b != null && b.getChildByName(name).hasValues() ? b.getChildByName(name).getValues().get(0).getBase().primitiveValue() : null;
}
private String getPrimitiveValue(ResourceWrapper r, String name) throws UnsupportedEncodingException, FHIRException, IOException {
return r.getChildByName(name).hasValues() ? r.getChildByName(name).getValues().get(0).getBase().primitiveValue() : null;
}
}

View File

@ -712,7 +712,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
public String sctLink(String code) {
// if (snomedEdition != null)
// http://browser.ihtsdotools.org/?perspective=full&conceptId1=428041000124106&edition=us-edition&release=v20180301&server=https://prod-browser-exten.ihtsdotools.org/api/snomed&langRefset=900000000000509007
return "http://browser.ihtsdotools.org/?perspective=full&conceptId1="+code;
return "http://snomed.info/id/"+code;
}
private void addRefToCode(XhtmlNode td, String target, String vslink, String code) {

View File

@ -55,6 +55,7 @@ public class BaseWrappers {
public PropertyWrapper getChildByName(String tail);
public StructureDefinition getDefinition();
public boolean hasNarrative();
public String getNameFromResource();
}
public interface BaseWrapper extends WrapperBase {

View File

@ -10,6 +10,7 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.formats.FormatUtilities;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
@ -267,6 +268,29 @@ public class DOMWrappers {
return wrapped.getNodeName();
}
@Override
public String getNameFromResource() {
Element e = XMLUtil.getNamedChild(wrapped, "name");
if (e != null) {
if (e.hasAttribute("value")) {
return e.getAttribute("value");
}
if (XMLUtil.hasNamedChild(e, "text")) {
return XMLUtil.getNamedChildValue(e, "text");
}
if (XMLUtil.hasNamedChild(e, "family") || XMLUtil.hasNamedChild(e, "given")) {
Element family = XMLUtil.getNamedChild(e, "family");
Element given = XMLUtil.getNamedChild(e, "given");
String s = given != null && given.hasAttribute("value") ? given.getAttribute("value") : "";
if (family != null && family.hasAttribute("value"))
s = s + " " + family.getAttribute("value").toUpperCase();
return s;
}
return null;
}
return null;
}
@Override
public List<PropertyWrapper> children() {
if (list2 == null) {

View File

@ -208,6 +208,28 @@ public class DirectWrappers {
return wrapped.getResourceType().toString();
}
@Override
public String getNameFromResource() {
Property name = wrapped.getChildByName("name");
if (name != null && name.hasValues()) {
Base b = name.getValues().get(0);
if (b.isPrimitive()) {
return b.primitiveValue();
} else if (b.fhirType().equals("HumanName")) {
Property family = b.getChildByName("family");
Property given = wrapped.getChildByName("given");
String s = given != null && given.hasValues() ? given.getValues().get(0).primitiveValue() : "";
if (family != null && family.hasValues())
s = s + " " + family.getValues().get(0).primitiveValue().toUpperCase();
return s;
} else {
// it might be a human name?
throw new Error("What to do?");
}
}
return null;
}
@Override
public List<PropertyWrapper> children() {
List<PropertyWrapper> list = new ArrayList<PropertyWrapper>();

View File

@ -16,6 +16,7 @@ import org.hl7.fhir.r5.elementmodel.XmlParser;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.StructureDefinition;
@ -157,6 +158,27 @@ public class ElementWrappers {
return wrapped.getName();
}
@Override
public String getNameFromResource() {
Property name = wrapped.getChildByName("name");
if (name != null && name.hasValues()) {
Base b = name.getValues().get(0);
if (b.isPrimitive()) {
return b.primitiveValue();
} else if (b.fhirType().equals("HumanName")) {
Property family = b.getChildByName("family");
Property given = wrapped.getChildByName("given");
String s = given != null && given.hasValues() ? given.getValues().get(0).primitiveValue() : "";
if (family != null && family.hasValues())
s = s + " " + family.getValues().get(0).primitiveValue().toUpperCase();
return s;
} else {
throw new Error("Now what? ("+b.fhirType()+")");
}
}
return null;
}
@Override
public List<PropertyWrapper> children() {
if (list2 == null) {

View File

@ -23,20 +23,38 @@ import org.hl7.fhir.utilities.validation.ValidationOptions;
public class RenderingContext {
// provides liquid templates, if they are available for the content
public interface ILiquidTemplateProvider {
String findTemplate(RenderingContext rcontext, DomainResource r);
String findTemplate(RenderingContext rcontext, String resourceName);
}
// parses xml to an XML instance. Whatever codes provides this needs to provide something that parses the right version
public interface ITypeParser {
Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException ;
}
public enum ResourceRendererMode{
RESOURCE, IG
/**
* What kind of user the renderer is targeting - end users, or technical users
*
* This affects the way codes and references are rendered
*
* @author graha
*
*/
public enum ResourceRendererMode {
/**
* The user has no interest in the contents of the FHIR resource, and just wants to see the data
*
*/
END_USER,
/**
* The user wants to see the resource, but a technical view so they can see what's going on with the content
*/
TECHNICAL
}
public enum QuestionnaireRendererMode {
/**
* A visual presentation of the questionnaire, with a set of property panes that can be toggled on and off.
@ -405,4 +423,8 @@ public class RenderingContext {
this.targetVersion = targetVersion;
}
public boolean isTechnicalMode() {
return mode == ResourceRendererMode.TECHNICAL;
}
}

View File

@ -0,0 +1,165 @@
package org.hl7.fhir.r5.terminologies;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
public class TerminologyCacheManager {
// if either the CACHE_VERSION of the stated maj/min server versions change, the
// cache will be blown. Note that the stated terminology server version is
// the CapabilityStatement.software.version
private static final String CACHE_VERSION = "1";
private String cacheFolder;
private String version;
private String ghOrg;
private String ghRepo;
private String ghBranch;
public TerminologyCacheManager(String serverVersion, String rootDir, String ghOrg, String ghRepo, String ghBranch) throws IOException {
super();
// this.rootDir = rootDir;
this.ghOrg = ghOrg;
this.ghRepo = ghRepo;
this.ghBranch = ghBranch;
version = CACHE_VERSION+"/"+VersionUtilities.getMajMin(serverVersion);
if (Utilities.noString(ghOrg) || Utilities.noString(ghRepo) || Utilities.noString(ghBranch)) {
cacheFolder = Utilities.path(rootDir, "temp", "tx-cache");
} else {
cacheFolder = Utilities.path(System.getProperty("user.home"), ".fhir", "tx-cache", ghOrg, ghRepo, ghBranch);
}
}
public void initialize() throws IOException {
File f = new File(cacheFolder);
if (!f.exists()) {
Utilities.createDirectory(cacheFolder);
}
if (!version.equals(getCacheVersion())) {
clearCache();
fillCache("http://tx.fhir.org/tx-cache/"+ghOrg+"/"+ghRepo+"/"+ghBranch+".zip");
}
if (!version.equals(getCacheVersion())) {
clearCache();
fillCache("http://tx.fhir.org/tx-cache/"+ghOrg+"/"+ghRepo+"/default.zip");
}
if (!version.equals(getCacheVersion())) {
clearCache();
}
IniFile ini = new IniFile(Utilities.path(cacheFolder, "cache.ini"));
ini.setStringProperty("version", "version", version, null);
ini.save();
}
private void fillCache(String source) throws IOException {
try {
System.out.println("Initialise terminology cache from "+source);
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source+"?nocache=" + System.currentTimeMillis());
res.checkThrowException();
unzip(new ByteArrayInputStream(res.getContent()), cacheFolder);
} catch (Exception e) {
System.out.println("No - can't initialise cache from "+source+": "+e.getMessage());
}
}
public static void unzip(InputStream is, String targetDir) throws IOException {
try (ZipInputStream zipIn = new ZipInputStream(is)) {
for (ZipEntry ze; (ze = zipIn.getNextEntry()) != null; ) {
String path = Utilities.path(targetDir, ze.getName());
if (!path.startsWith(targetDir)) {
// see: https://snyk.io/research/zip-slip-vulnerability
throw new RuntimeException("Entry with an illegal path: " + ze.getName());
}
if (ze.isDirectory()) {
Utilities.createDirectory(path);
} else {
Utilities.createDirectory(Utilities.getDirectoryForFile(path));
TextFile.streamToFile(zipIn, path);
}
}
}
}
private void clearCache() throws IOException {
Utilities.clearDirectory(cacheFolder);
}
private String getCacheVersion() throws IOException {
IniFile ini = new IniFile(Utilities.path(cacheFolder, "cache.ini"));
return ini.getStringProperty("version", "version");
}
public String getFolder() {
return cacheFolder;
}
private void zipDirectory(OutputStream outputStream) throws IOException {
try (ZipOutputStream zs = new ZipOutputStream(outputStream)) {
Path pp = Paths.get(cacheFolder);
Files.walk(pp)
.forEach(path -> {
try {
if (Files.isDirectory(path)) {
zs.putNextEntry(new ZipEntry(pp.relativize(path).toString() + "/"));
} else {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
zs.putNextEntry(zipEntry);
Files.copy(path, zs);
zs.closeEntry();
}
} catch (IOException e) {
System.err.println(e);
}
});
}
}
public void commit(String token) throws IOException {
// create a zip of all the files
ByteArrayOutputStream bs = new ByteArrayOutputStream();
zipDirectory(bs);
// post it to
String url = "https://tx.fhir.org/post/tx-cache/"+ghOrg+"/"+ghRepo+"/"+ghBranch+".zip";
System.out.println("Sending tx-cache to "+url+" ("+Utilities.describeSize(bs.toByteArray().length)+")");
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.put(url, "application/zip", bs.toByteArray(), null); // accept doesn't matter
if (res.getCode() >= 300) {
System.out.println("sending cache failed: "+res.getCode());
} else {
System.out.println("Sent cache");
}
}
}

View File

@ -40,6 +40,7 @@ import java.util.Map;
public interface TerminologyClient {
String getAddress();
String getServerVersion();
TerminologyCapabilities getTerminologyCapabilities() throws FHIRException;
ValueSet expandValueset(ValueSet vs, Parameters p, Map<String, String> params) throws FHIRException;
Parameters validateCS(Parameters pin) throws FHIRException;

View File

@ -43,7 +43,7 @@ public class XVerExtensionManager {
public XVerExtensionStatus status(String url) throws FHIRException {
String v = url.substring(20, 23);
if ("5.0".equals(v)) {
v = "4.5"; // for now
v = "4.6"; // for now
}
String e = url.substring(54);
if (!lists.containsKey(v)) {
@ -76,7 +76,7 @@ public class XVerExtensionManager {
public StructureDefinition makeDefinition(String url) {
String verSource = url.substring(20, 23);
if ("5.0".equals(verSource)) {
verSource = "4.5"; // for now
verSource = "4.6"; // for now
}
String verTarget = VersionUtilities.getMajMin(context.getVersion());
String e = url.substring(54);

View File

@ -581,6 +581,10 @@ public class FHIRToolingClient {
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public String getServerVersion() {
return capabilities == null ? null : capabilities.getSoftware().getVersion();
}
}

View File

@ -23,6 +23,7 @@ public class Client {
private FhirLoggingInterceptor fhirLoggingInterceptor;
private int retryCount;
private long timeout = DEFAULT_TIMEOUT;
private byte[] payload;
public ToolingClientLogger getLogger() {
return logger;
@ -53,6 +54,7 @@ public class Client {
String resourceFormat,
String message,
long timeout) throws IOException {
this.payload = null;
Request.Builder request = new Request.Builder()
.method("OPTIONS", null)
.url(optionsUri.toURL());
@ -65,6 +67,7 @@ public class Client {
Headers headers,
String message,
long timeout) throws IOException {
this.payload = null;
Request.Builder request = new Request.Builder()
.url(resourceUri.toURL());
@ -89,6 +92,7 @@ public class Client {
String message,
long timeout) throws IOException {
if (payload == null) throw new EFhirClientException("PUT requests require a non-null payload");
this.payload = payload;
RequestBody body = RequestBody.create(payload);
Request.Builder request = new Request.Builder()
.url(resourceUri.toURL())
@ -112,6 +116,7 @@ public class Client {
String message,
long timeout) throws IOException {
if (payload == null) throw new EFhirClientException("POST requests require a non-null payload");
this.payload = payload;
RequestBody body = RequestBody.create(MediaType.parse(resourceFormat + ";charset=" + DEFAULT_CHARSET), payload);
Request.Builder request = new Request.Builder()
.url(resourceUri.toURL())

View File

@ -127,7 +127,7 @@ public class NarrativeGenerationTests {
@ParameterizedTest(name = "{index}: file {0}")
@MethodSource("data")
public void test(String id, TestDetails test) throws Exception {
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER);
rc.setDestDir("");
rc.setHeader(test.isHeader());
rc.setDefinitionsTarget("test.html");

View File

@ -24,7 +24,7 @@ public class NarrativeGeneratorTests {
@BeforeAll
public static void setUp() throws FHIRException {
rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER);
}
@Test

View File

@ -35,7 +35,7 @@ public class ResourceRoundTripTests {
@Test
public void test() throws IOException, FHIRException, EOperationOutcome {
DomainResource res = (DomainResource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "unicode.xml"));
RenderingContext rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER);
RendererFactory.factory(res, rc).render(res);
IOUtils.copy(TestingUtilities.loadTestResourceStream("r5", "unicode.xml"), new FileOutputStream(TestingUtilities.tempFile("gen", "unicode.xml")));
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(TestingUtilities.tempFile("gen", "unicode.out.xml")), res);

View File

@ -42,6 +42,7 @@ import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
import org.hl7.fhir.r5.utils.IResourceValidator;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.ToolsVersion;
@ -546,8 +547,8 @@ public class SnapShotGenerationTests {
pu.setThrowException(false);
pu.setDebug(test.isDebug());
pu.setIds(test.getSource(), false);
if (!TestingUtilities.context().hasPackage("hl7.fhir.xver-extensions", "0.0.4")) {
NpmPackage npm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage("hl7.fhir.xver-extensions", "0.0.4");
if (!TestingUtilities.context().hasPackage(CommonPackages.ID_XVER, CommonPackages.VER_XVER)) {
NpmPackage npm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage(CommonPackages.ID_XVER, CommonPackages.VER_XVER);
TestingUtilities.context().loadFromPackage(npm, new TestLoader(new String[]{"StructureDefinition"}), new String[]{"StructureDefinition"});
}
pu.setXver(new XVerExtensionManager(TestingUtilities.context()));
@ -575,7 +576,7 @@ public class SnapShotGenerationTests {
throw e;
}
if (output.getDifferential().hasElement()) {
RenderingContext rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER);
rc.setDestDir(Utilities.path("[tmp]", "snapshot"));
rc.setProfileUtilities(new ProfileUtilities(TestingUtilities.context(), null, new TestPKP()));
RendererFactory.factory(output, rc).render(output);

View File

@ -86,12 +86,14 @@
<version>${validator_test_case_version}</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>4.9.0</version>
<scope>compile</scope>
</dependency>
-->
</dependencies>
<build>

View File

@ -0,0 +1,201 @@
package org.hl7.fhir.utilities;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.SimpleHTTPClient.Header;
import org.hl7.fhir.utilities.npm.SSLCertTruster;
public class SimpleHTTPClient {
public class Header {
private String name;
private String value;
public Header(String name, String value) {
super();
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
}
private static final int MAX_REDIRECTS = 5;
public class HTTPResult {
private int code;
private String contentType;
private byte[] content;
private String source;
public HTTPResult(String source, int code, String contentType, byte[] content) {
super();
this.source = source;
this.code = code;
this.contentType = contentType;
this.content = content;
}
public int getCode() {
return code;
}
public String getContentType() {
return contentType;
}
public byte[] getContent() {
return content;
}
public String getSource() {
return source;
}
public void checkThrowException() throws IOException {
if (code >= 300) {
throw new IOException("Invalid HTTP response "+code+" from "+source);
}
}
}
private List<Header> headers = new ArrayList<>();
private String username;
private String password;
public void addHeader(String name, String value) {
headers.add(new Header(name, value));
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private boolean trustAll = false;
public void trustAllhosts() {
trustAll = true;
SSLCertTruster.trustAllHosts();
}
public HTTPResult get(String url) throws IOException {
return get(url, null);
}
public HTTPResult get(String url, String accept) throws IOException {
URL u = new URL(url);
boolean isSSL = url.startsWith("https://");
// handling redirects - setInstanceFollowRedirects(true) doesn't handle crossing http to https
Map<String, Integer> visited = new HashMap<>();
HttpURLConnection c = null;
boolean done = false;
while (!done) {
int times = visited.compute(url, (key, count) -> count == null ? 1 : count + 1);
if (times > MAX_REDIRECTS)
throw new IOException("Stuck in redirect loop");
u = new URL(url);
c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setRequestProperty("Accept", accept);
setHeaders(c);
c.setInstanceFollowRedirects(false);
if (trustAll && url.startsWith("https://")) {
((javax.net.ssl.HttpsURLConnection) c).setHostnameVerifier(SSLCertTruster.DO_NOT_VERIFY);
}
switch (c.getResponseCode()) {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
String location = c.getHeaderField("Location");
location = URLDecoder.decode(location, "UTF-8");
URL base = new URL(url);
URL next = new URL(base, location); // Deal with relative URLs
url = next.toExternalForm();
continue;
default:
done = true;
}
}
return new HTTPResult(url, c.getResponseCode(), c.getRequestProperty("Content-Type"), TextFile.streamToBytes(c.getInputStream()));
}
private void setHeaders(HttpURLConnection c) {
for (Header h : headers) {
c.setRequestProperty(h.getName(), h.getValue());
}
c.setConnectTimeout(15000);
c.setReadTimeout(15000);
if (username != null) {
String auth = username+":"+password;
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8));
String authHeaderValue = "Basic " + new String(encodedAuth);
c.setRequestProperty("Authorization", authHeaderValue);
}
}
public HTTPResult post(String url, String contentType, byte[] content, String accept) throws IOException {
URL u = new URL(url);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setDoOutput(true);
c.setDoInput(true);
c.setRequestMethod("POST");
c.setRequestProperty("Content-type", contentType);
if (accept != null) {
c.setRequestProperty("Accept", accept);
}
setHeaders(c);
c.getOutputStream().write(content);
c.getOutputStream().close();
return new HTTPResult(url, c.getResponseCode(), c.getRequestProperty("Content-Type"), TextFile.streamToBytes(c.getInputStream()));
}
public HTTPResult put(String url, String contentType, byte[] content, String accept) throws IOException {
URL u = new URL(url);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setDoOutput(true);
c.setDoInput(true);
c.setRequestMethod("PUT");
c.setRequestProperty("Content-type", contentType);
if (accept != null) {
c.setRequestProperty("Accept", accept);
}
setHeaders(c);
c.getOutputStream().write(content);
c.getOutputStream().close();
return new HTTPResult(url, c.getResponseCode(), c.getRequestProperty("Content-Type"), TextFile.streamToBytes(c.getInputStream()));
}
}

View File

@ -1501,5 +1501,14 @@ public class Utilities {
return oid.matches(OID_REGEX);
}
public static int findinList(String[] list, String val) {
for (int i = 0; i < list.length; i++) {
if (val.equals(list[i])) {
return i;
}
}
return -1;
}
}

View File

@ -1,9 +1,7 @@
package org.hl7.fhir.utilities.json;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
@ -134,12 +132,6 @@ public class JSONUtil {
}
}
public static JsonObject fetchJson(String source) throws IOException {
URL url = new URL(source);
URLConnection c = url.openConnection();
return (JsonObject) new com.google.gson.JsonParser().parse(TextFile.streamToString(c.getInputStream()));
}
public static String type(JsonElement e) {
if (e == null) {
return "(null)";

View File

@ -36,12 +36,12 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Stack;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
@ -663,7 +663,7 @@ public class JsonTrackingParser {
String jcnt = gson.toJson(json);
TextFile.stringToFile(jcnt, file);
}
public static void write(JsonObject json, String fileName) throws IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jcnt = gson.toJson(json);
@ -675,6 +675,11 @@ public class JsonTrackingParser {
return gson.toJson(json);
}
public static String writeDense(JsonObject json) {
Gson gson = new GsonBuilder().create();
return gson.toJson(json);
}
public static byte[] writeBytes(JsonObject json, boolean pretty) {
if (pretty) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
@ -686,10 +691,10 @@ public class JsonTrackingParser {
}
public static JsonObject fetchJson(String source) throws IOException {
URL url = new URL(source+"?nocache=" + System.currentTimeMillis());
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setInstanceFollowRedirects(true);
return parseJson(c.getInputStream());
SimpleHTTPClient fetcher = new SimpleHTTPClient();
HTTPResult res = fetcher.get(source+"?nocache=" + System.currentTimeMillis());
res.checkThrowException();
return parseJson(res.getContent());
}

View File

@ -0,0 +1,11 @@
package org.hl7.fhir.utilities.npm;
public class CommonPackages {
public static final String ID_XVER = "hl7.fhir.xver-extensions";
public static final String VER_XVER = "0.0.7";
public static final String ID_PUBPACK = "hl7.fhir.pubpack";
public static final String VER_PUBPACK = "0.0.9";
}

View File

@ -36,6 +36,8 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.commons.io.FileUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
@ -47,6 +49,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -54,7 +58,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.sql.Timestamp;
@ -146,12 +149,6 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
return pi;
}
private JsonObject fetchJson(String source) throws IOException {
URL url = new URL(source);
URLConnection c = url.openConnection();
return (JsonObject) new com.google.gson.JsonParser().parse(TextFile.streamToString(c.getInputStream()));
}
private void clearCache() throws IOException {
for (File f : new File(cacheFolder).listFiles()) {
if (f.isDirectory()) {
@ -229,7 +226,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
public String getLatestVersion(String id) throws IOException {
for (String nextPackageServer : getPackageServers()) {
// special case:
if (!("hl7.fhir.pubpack".equals(id) && PRIMARY_SERVER.equals(nextPackageServer))) {
if (!(CommonPackages.ID_PUBPACK.equals(id) && PRIMARY_SERVER.equals(nextPackageServer))) {
CachingPackageClient pc = new CachingPackageClient(nextPackageServer);
try {
return pc.getLatestVersion(id);
@ -517,9 +514,10 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
private InputStream fetchFromUrlSpecific(String source, boolean optional) throws FHIRException {
try {
URL url = new URL(source);
URLConnection c = url.openConnection();
return c.getInputStream();
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source);
res.checkThrowException();
return new ByteArrayInputStream(res.getContent());
} catch (Exception e) {
if (optional)
return null;
@ -627,7 +625,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
// special case: current versions roll over, and we have to check their currency
try {
String url = ciList.get(id);
JsonObject json = fetchJson(Utilities.pathURL(url, "package.manifest.json"));
JsonObject json = JsonTrackingParser.fetchJson(Utilities.pathURL(url, "package.manifest.json"));
String currDate = JSONUtil.str(json, "date");
String packDate = p.date();
if (!currDate.equals(packDate))
@ -651,13 +649,12 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
}
private void loadFromBuildServer() throws IOException {
URL url = new URL("https://build.fhir.org/ig/qas.json?nocache=" + System.currentTimeMillis());
SSLCertTruster.trustAllHosts();
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setHostnameVerifier(SSLCertTruster.DO_NOT_VERIFY);
connection.setRequestMethod("GET");
InputStream json = connection.getInputStream();
buildInfo = (JsonArray) new com.google.gson.JsonParser().parse(TextFile.streamToString(json));
SimpleHTTPClient http = new SimpleHTTPClient();
http.trustAllhosts();
HTTPResult res = http.get("https://build.fhir.org/ig/qas.json?nocache=" + System.currentTimeMillis());
res.checkThrowException();
TextFile.bytesToFile(res.getContent(), "c:\\temp\\qa.json");
buildInfo = (JsonArray) new com.google.gson.JsonParser().parse(TextFile.bytesToString(res.getContent()));
List<BuildRecord> builds = new ArrayList<>();
@ -714,7 +711,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
String aurl = pu;
JsonObject json;
try {
json = fetchJson(pu);
json = JsonTrackingParser.fetchJson(pu);
} catch (Exception e) {
String pv = Utilities.pathURL(url, v, "package.tgz");
try {
@ -755,7 +752,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
throw new FHIRException("Unable to resolve package id " + id);
}
String pu = Utilities.pathURL(url, "package-list.json");
JsonObject json = fetchJson(pu);
JsonObject json = JsonTrackingParser.fetchJson(pu);
if (!id.equals(JSONUtil.str(json, "package-id")))
throw new FHIRException("Package ids do not match in " + pu + ": " + id + " vs " + JSONUtil.str(json, "package-id"));
for (JsonElement e : json.getAsJsonArray("list")) {
@ -769,7 +766,7 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
}
private String getUrlForPackage(String id) {
if ("hl7.fhir.xver-extensions".equals(id)) {
if (CommonPackages.ID_XVER.equals(id)) {
return "http://fhir.org/packages/hl7.fhir.xver-extensions";
}
return null;

View File

@ -727,16 +727,19 @@ public class NpmPackage {
if ("hl7.fhir.core".equals(JSONUtil.str(npm, "name")))
return JSONUtil.str(npm, "version");
else if (JSONUtil.str(npm, "name").startsWith("hl7.fhir.r2.") || JSONUtil.str(npm, "name").startsWith("hl7.fhir.r2b.") || JSONUtil.str(npm, "name").startsWith("hl7.fhir.r3.") ||
JSONUtil.str(npm, "name").startsWith("hl7.fhir.r4.") || JSONUtil.str(npm, "name").startsWith("hl7.fhir.r4b.") || JSONUtil.str(npm, "name").startsWith("hl7.fhir.r5."))
JSONUtil.str(npm, "name").startsWith("hl7.fhir.r4.") || JSONUtil.str(npm, "name").startsWith("hl7.fhir.r4b.") || JSONUtil.str(npm, "name").startsWith("hl7.fhir.r5."))
return JSONUtil.str(npm, "version");
else {
JsonObject dep = npm.getAsJsonObject("dependencies");
if (dep != null) {
for (Entry<String, JsonElement> e : dep.entrySet()) {
if (Utilities.existsInList(e.getKey(), "hl7.fhir.r2.core", "hl7.fhir.r2b.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core"))
return e.getValue().getAsString();
if (Utilities.existsInList(e.getKey(), "hl7.fhir.core")) // while all packages are updated
return e.getValue().getAsString();
else {
JsonObject dep = null;
if (npm.has("dependencies") && npm.get("dependencies").isJsonObject()) {
dep = npm.getAsJsonObject("dependencies");
if (dep != null) {
for (Entry<String, JsonElement> e : dep.entrySet()) {
if (Utilities.existsInList(e.getKey(), "hl7.fhir.r2.core", "hl7.fhir.r2b.core", "hl7.fhir.r3.core", "hl7.fhir.r4.core"))
return e.getValue().getAsString();
if (Utilities.existsInList(e.getKey(), "hl7.fhir.core")) // while all packages are updated
return e.getValue().getAsString();
}
}
}
if (npm.has("fhirVersions")) {
@ -955,8 +958,13 @@ public class NpmPackage {
public String fhirVersionList() {
if (npm.has("fhirVersions")) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (JsonElement n : npm.getAsJsonArray("fhirVersions")) {
b.append(n.getAsString());
if (npm.get("fhirVersions").isJsonArray()) {
for (JsonElement n : npm.getAsJsonArray("fhirVersions")) {
b.append(n.getAsString());
}
}
if (npm.get("fhirVersions").isJsonPrimitive()) {
b.append(npm.get("fhirVersions").getAsString());
}
return b.toString();
} else

View File

@ -4,17 +4,19 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.json.JSONUtil;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
@ -135,12 +137,10 @@ public class PackageClient {
}
private InputStream fetchUrl(String source, String accept) throws IOException {
URL url = new URL(source);
URLConnection c = url.openConnection();
if (accept != null) {
c.setRequestProperty("accept", accept);
}
return c.getInputStream();
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source, accept);
res.checkThrowException();
return new ByteArrayInputStream(res.getContent());
}
private JsonObject fetchJson(String source) throws IOException {

View File

@ -0,0 +1,75 @@
package org.hl7.fhir.utilities.npm;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.json.JSONUtil;
import org.hl7.fhir.utilities.json.JsonTrackingParser;
import com.google.gson.JsonObject;
public class PackageScanner {
public static void main(String[] args) throws IOException {
List<String> output = new ArrayList<>();
Set<String> packages = new HashSet<>();
processServer("http://packages.fhir.org", output, packages);
processServer("http://packages2.fhir.org/packages", output, packages);
StringBuilder b = new StringBuilder();
for (String s : output) {
b.append(s);
b.append("\r\n");
System.out.println(s);
}
TextFile.stringToFile(b.toString(), "c:\\temp\\packages.csv");
}
public static void processServer(String server, List<String> output, Set<String> packages) throws IOException {
System.out.println("Server: "+server);
PackageClient client = new PackageClient(server);
List<PackageInfo> list = client.search(null, null, null, false);
output.add("id\tversion\tcanonica\tfhir version\tfhir-versions\tkind\ttype\tsource");
for (PackageInfo pi : list) {
System.out.print(" fetch: "+pi.getId());
List<PackageInfo> versions = null;
while (versions == null) {
System.out.print("-");
try {
versions = client.getVersions(pi.getId());
} catch (Exception e) {
// nothing
}
}
for (PackageInfo piv : versions) {
if (!packages.contains(pi.getId()+"#"+piv.getVersion())) {
packages.add(pi.getId()+"#"+piv.getVersion());
try {
System.out.print(".");
InputStream cnt = client.fetch(pi.getId(), piv.getVersion());
NpmPackage pck = NpmPackage.fromPackage(cnt);
JsonObject json = pck.getNpm();
String fv;
try {
fv = pck.fhirVersion();
} catch (Exception e) {
fv = "--";
}
output.add(pck.name()+"\t"+pck.version()+"\t"+pck.canonical()+"\t"+fv+'\t'+pck.fhirVersionList()+'\t'+JSONUtil.str(json, "kind")+'\t'+JSONUtil.str(json, "type")+'\t'+JsonTrackingParser.writeDense(json)); } catch (Exception e) {
System.out.println("Error acessing "+pi.getId()+"#"+piv.getVersion()+": "+e.getMessage());
e.printStackTrace();
}
}
}
System.out.println("!");
}
}
}

View File

@ -13,7 +13,7 @@ import java.security.cert.X509Certificate;
public class SSLCertTruster {
// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}

View File

@ -1,6 +1,7 @@
package org.hl7.fhir.utilities.tests;
import org.hl7.fhir.utilities.npm.CachingPackageClient;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.hl7.fhir.utilities.npm.PackageInfo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -70,7 +71,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.9"));
Assertions.assertTrue(client.exists(CommonPackages.ID_PUBPACK, CommonPackages.VER_PUBPACK));
}
@Test

View File

@ -1,6 +1,7 @@
package org.hl7.fhir.utilities.tests;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.ToolsVersion;
@ -22,7 +23,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.9");
NpmPackage npm = cache.loadPackage(CommonPackages.ID_PUBPACK, CommonPackages.VER_PUBPACK);
npm.loadAllFiles();
Assertions.assertNotNull(npm);
File dir = new File(Utilities.path("[tmp]", "cache"));
@ -32,7 +33,7 @@ public class PackageCacheTests {
Utilities.createDirectory(dir.getAbsolutePath());
}
npm.save(dir);
NpmPackage npm2 = cache.loadPackage("hl7.fhir.pubpack", "file:" + dir.getAbsolutePath());
NpmPackage npm2 = cache.loadPackage(CommonPackages.ID_PUBPACK, "file:" + dir.getAbsolutePath());
Assertions.assertNotNull(npm2);
list = cache.listPackages();
Assertions.assertFalse(list.isEmpty());
@ -60,7 +61,7 @@ public class PackageCacheTests {
public void testLastReleasedVersion() throws IOException {
FilesystemPackageCacheManager cache = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
cache.clear();
Assertions.assertEquals("0.0.8", cache.loadPackage("hl7.fhir.pubpack", "0.0.8").version());
Assertions.assertEquals("0.0.9", cache.loadPackage("hl7.fhir.pubpack").version());
Assertions.assertEquals("0.0.8", cache.loadPackage(CommonPackages.ID_PUBPACK, "0.0.8").version());
Assertions.assertEquals(CommonPackages.VER_PUBPACK, cache.loadPackage(CommonPackages.ID_PUBPACK).version());
}
}

View File

@ -107,6 +107,11 @@ public class XhtmlNodeTest {
Assertions.assertThrows(FHIRException.class, () -> new XhtmlParser().parse(BaseTestingUtilities.loadTestResource("xhtml", "bad-link.html"), "div"));
}
@Test
public void testParseEntities() throws FHIRFormatError, IOException {
XhtmlNode x = new XhtmlParser().parse(BaseTestingUtilities.loadTestResource("xhtml", "entities.html"), "div");
}
}

View File

@ -18,6 +18,8 @@ import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.ImplementationGuide;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
@ -33,9 +35,7 @@ import org.hl7.fhir.validation.cli.utils.VersionSourceInformation;
import org.w3c.dom.Document;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -273,9 +273,10 @@ public class IgLoader {
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();
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source + "?nocache=" + System.currentTimeMillis());
res.checkThrowException();
return new ByteArrayInputStream(res.getContent());
} catch (IOException e) {
if (optional)
return null;
@ -412,17 +413,16 @@ public class IgLoader {
private byte[] fetchFromUrlSpecific(String source, String contentType, boolean optional, List<String> errors) throws FHIRException, IOException {
try {
SimpleHTTPClient http = new SimpleHTTPClient();
try {
// try with cache-busting option and then try withhout in case the server doesn't support that
URL url = new URL(source + "?nocache=" + System.currentTimeMillis());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Accept", contentType);
return TextFile.streamToBytes(conn.getInputStream());
HTTPResult res = http.get(source + "?nocache=" + System.currentTimeMillis(), contentType);
res.checkThrowException();
return res.getContent();
} catch (Exception e) {
URL url = new URL(source);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Accept", contentType);
return TextFile.streamToBytes(conn.getInputStream());
HTTPResult res = http.get(source, contentType);
res.checkThrowException();
return res.getContent();
}
} catch (IOException e) {
if (errors != null) {

View File

@ -11,6 +11,8 @@ import org.hl7.fhir.r5.renderers.RendererFactory;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
@ -19,8 +21,6 @@ import org.hl7.fhir.validation.cli.model.ScanOutputItem;
import org.hl7.fhir.validation.instance.InstanceValidator;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
@ -240,7 +240,7 @@ public class Scanner {
}
protected void genScanOutputItem(ScanOutputItem item, String filename) throws IOException, FHIRException, EOperationOutcome {
RenderingContext rc = new RenderingContext(getContext(), null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(getContext(), null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.END_USER);
rc.setNoSlowLookup(true);
RendererFactory.factory(item.getOutcome(), rc).render(item.getOutcome());
String s = new XhtmlComposer(XhtmlComposer.HTML).compose(item.getOutcome().getText().getDiv());
@ -294,18 +294,16 @@ public class Scanner {
protected OperationOutcome exceptionToOutcome(Exception ex) throws IOException, FHIRException, EOperationOutcome {
OperationOutcome op = new OperationOutcome();
op.addIssue().setCode(OperationOutcome.IssueType.EXCEPTION).setSeverity(OperationOutcome.IssueSeverity.FATAL).getDetails().setText(ex.getMessage());
RenderingContext rc = new RenderingContext(getContext(), null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(getContext(), null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.END_USER);
RendererFactory.factory(op, rc).render(op);
return op;
}
protected void download(String address, String filename) throws IOException {
URL url = new URL(address);
URLConnection c = url.openConnection();
InputStream s = c.getInputStream();
FileOutputStream f = new FileOutputStream(filename);
transfer(s, f, 1024);
f.close();
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(address);
res.checkThrowException();
TextFile.bytesToFile(res.getContent(), filename);
}
protected void transfer(InputStream in, OutputStream out, int buffer) throws IOException {

View File

@ -41,6 +41,8 @@ import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.structuremap.StructureMapUtilities;
import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.*;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.ToolsVersion;
@ -54,10 +56,8 @@ import org.hl7.fhir.validation.instance.utils.ValidatorHostContext;
import org.xml.sax.SAXException;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
/*
@ -238,7 +238,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
if (tt != null) {
context.setClock(tt);
}
NpmPackage npmX = getPcm().loadPackage("hl7.fhir.xver-extensions", "0.0.4");
NpmPackage npmX = getPcm().loadPackage(CommonPackages.ID_XVER, CommonPackages.VER_XVER);
context.loadFromPackage(npmX, null);
this.fhirPathEngine = new FHIRPathEngine(context);
@ -435,7 +435,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
public Resource generate(String source, String version) throws FHIRException, IOException, EOperationOutcome {
Content cnt = igLoader.loadContent(source, "validate", false);
Resource res = igLoader.loadResourceByVersion(version, cnt.focus, source);
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER);
genResource(res, rc);
return (Resource) res;
}
@ -554,19 +554,9 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
if (output.startsWith("http://")) {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
handleOutputToStream(r, output, bs, version);
URL url = new URL(output);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setDoOutput(true);
c.setDoInput(true);
c.setRequestMethod("POST");
c.setRequestProperty("Content-type", "application/fhir+xml");
c.setRequestProperty("Accept", "application/fhir+xml");
c.getOutputStream().write(bs.toByteArray());
c.getOutputStream().close();
if (c.getResponseCode() >= 300) {
throw new IOException("Unable to PUT to " + output + ": " + c.getResponseMessage());
}
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.post(output, "application/fhir+xml", bs.toByteArray(), "application/fhir+xml");
res.checkThrowException();
} else {
FileOutputStream s = new FileOutputStream(output);
handleOutputToStream(r, output, s, version);
@ -711,9 +701,10 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
@Override
public byte[] fetchRaw(IResourceValidator validator, String source) throws IOException {
URL url = new URL(source);
URLConnection c = url.openConnection();
return TextFile.streamToBytes(c.getInputStream());
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source);
res.checkThrowException();
return res.getContent();
}
@Override

View File

@ -63,6 +63,7 @@ import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.hl7.fhir.validation.cli.model.CliContext;
import org.hl7.fhir.validation.cli.services.ComparisonService;
import org.hl7.fhir.validation.cli.services.ValidationService;
@ -222,7 +223,7 @@ public class ValidatorCli {
String v = VersionUtilities.getCurrentVersion(cliContext.getSv());
String definitions = VersionUtilities.packageForVersion(v) + "#" + v;
ValidationEngine validator = validationService.initializeValidator(cliContext, definitions, tt);
validator.loadPackage("hl7.fhir.pubpack", null);
validator.loadPackage(CommonPackages.ID_PUBPACK, null);
ComparisonService.doLeftRightComparison(args, Params.getParam(args, Params.DESTINATION), validator);
}

View File

@ -91,7 +91,7 @@ public class ValidatorUtils {
if (!op.hasIssue()) {
op.addIssue().setSeverity(OperationOutcome.IssueSeverity.INFORMATION).setCode(OperationOutcome.IssueType.INFORMATIONAL).getDetails().setText(context.formatMessage(I18nConstants.ALL_OK));
}
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, RenderingContext.ResourceRendererMode.END_USER);
RendererFactory.factory(op, rc).render(op);
return op;
}

View File

@ -2,13 +2,14 @@ package org.hl7.fhir.validation.cli.utils;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
public class ProfileLoader {
public static byte[] loadProfileSource(String src) throws FHIRException, IOException {
@ -25,10 +26,10 @@ public class ProfileLoader {
private static byte[] loadProfileFromUrl(String src) throws FHIRException {
try {
URL url = new URL(src + "?nocache=" + System.currentTimeMillis());
URLConnection c = url.openConnection();
return IOUtils.toByteArray(c.getInputStream());
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(src + "?nocache=" + System.currentTimeMillis());
res.checkThrowException();
return res.getContent();
} catch (Exception e) {
throw new FHIRException("Unable to find definitions at URL '" + src + "': " + e.getMessage(), e);
}

View File

@ -49,6 +49,7 @@ import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.ToolsVersion;
@ -121,7 +122,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.9");
NpmPackage npm = pcm.loadPackage(CommonPackages.ID_PUBPACK, CommonPackages.VER_PUBPACK);
for (String f : npm.list("other")) {
TextFile.streamToFile(npm.load("other", f), Utilities.path("[tmp]", "comparison", f));
}

View File

@ -524,7 +524,7 @@ public class SnapShotGenerationXTests {
throw e;
}
if (output.getDifferential().hasElement()) {
RenderingContext rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RenderingContext rc = new RenderingContext(TestingUtilities.context(), null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.END_USER);
rc.setDestDir(makeTempDir());
rc.setProfileUtilities(new ProfileUtilities(TestingUtilities.context(), null, new TestPKP()));
RendererFactory.factory(output, rc).render(output);

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.validation.tests;
import org.hl7.fhir.utilities.npm.CommonPackages;
import org.junit.jupiter.api.Test;
public class ProfileComparisonTests {
@ -13,7 +14,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.9"), new R5ToR5Loader(new String[] {"Binary"}), "Binary");
// ve.getContext().loadFromPackage(new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION).loadPackage(CommonPackages.ID_PUBPACK, CommonPackages.VER_PUBPACK), new R5ToR5Loader(new String[] {"Binary"}), "Binary");
//
//
// String left = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient";

View File

@ -6,7 +6,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
@ -54,6 +53,8 @@ import org.hl7.fhir.r5.utils.IResourceValidator.BestPracticeWarningLevel;
import org.hl7.fhir.r5.utils.IResourceValidator.BundleValidationRule;
import org.hl7.fhir.r5.utils.IResourceValidator.IValidatorResourceFetcher;
import org.hl7.fhir.r5.utils.IResourceValidator.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
@ -554,9 +555,10 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
@Override
public byte[] fetchRaw(IResourceValidator validator, String source) throws MalformedURLException, IOException {
URL url = new URL(source);
URLConnection c = url.openConnection();
return TextFile.streamToBytes(c.getInputStream());
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source);
res.checkThrowException();
return res.getContent();
}
@Override

View File

@ -19,7 +19,7 @@
<properties>
<hapi_fhir_version>5.1.0</hapi_fhir_version>
<validator_test_case_version>1.1.72</validator_test_case_version>
<validator_test_case_version>1.1.73-SNAPSHOT</validator_test_case_version>
<junit_jupiter_version>5.7.1</junit_jupiter_version>
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
<maven_surefire_version>3.0.0-M4</maven_surefire_version>