IPS development
This commit is contained in:
parent
74893e42e7
commit
70af787438
|
@ -0,0 +1,440 @@
|
|||
package org.hl7.fhir.r5.ips;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.ips.IPSBuilder.TypeAndId;
|
||||
import org.hl7.fhir.r5.model.Age;
|
||||
import org.hl7.fhir.r5.model.Annotation;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r5.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.CodeableReference;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.Composition;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
import org.hl7.fhir.r5.model.Period;
|
||||
import org.hl7.fhir.r5.model.Quantity;
|
||||
import org.hl7.fhir.r5.model.Range;
|
||||
import org.hl7.fhir.r5.model.Reference;
|
||||
import org.hl7.fhir.r5.model.Composition.SectionComponent;
|
||||
import org.hl7.fhir.r5.model.Condition;
|
||||
import org.hl7.fhir.r5.model.Condition.ConditionParticipantComponent;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.Device;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Dosage;
|
||||
import org.hl7.fhir.r5.model.Enumerations.CompositionStatus;
|
||||
import org.hl7.fhir.r5.model.Identifier;
|
||||
import org.hl7.fhir.r5.model.Medication;
|
||||
import org.hl7.fhir.r5.model.MedicationStatement;
|
||||
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.r5.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtil;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class IPSBuilder {
|
||||
|
||||
public static class TypeAndId {
|
||||
private String type;
|
||||
private String id;
|
||||
protected TypeAndId(String type, String id) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
}
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public static Bundle generateIPS(FHIRToolingClient server, String patientId) {
|
||||
Patient pat = server.fetchResource(Patient.class, patientId);
|
||||
Bundle bnd = initBundle();
|
||||
Composition cmp = initComposition(bnd, server.getAddress(), pat);
|
||||
pat = processPatient(bnd, server.getAddress(), pat);
|
||||
// addMedications(bnd, cmp, server, patientId);
|
||||
addConditions(bnd, cmp, server, patientId);
|
||||
return bnd;
|
||||
}
|
||||
|
||||
private static Bundle initBundle() {
|
||||
Bundle bnd = new Bundle();
|
||||
bnd.getIdentifier().setSystem("urn:ietf:rfc:3986");
|
||||
bnd.getIdentifier().setValue(Utilities.makeUuidUrn());
|
||||
bnd.setType(BundleType.DOCUMENT);
|
||||
bnd.setTimestamp(new Date());
|
||||
return bnd;
|
||||
}
|
||||
|
||||
private static Composition initComposition(Bundle bnd, String url, Patient pat) {
|
||||
Composition cmp = new Composition();
|
||||
cmp.setIdBase(Utilities.makeUuidLC());
|
||||
cmp.setStatus(CompositionStatus.FINAL);
|
||||
cmp.getType().addCoding().setSystem("http://loinc.org").setCode("60591-5");
|
||||
cmp.setDate(new Date());
|
||||
cmp.setTitle("International Patient Summary");
|
||||
cmp.addSubject().setReference("Patient/"+pat.getIdBase());
|
||||
cmp.addAuthor().setReference("Device/java");
|
||||
bnd.addEntry().setResource(cmp).setFullUrl(Utilities.pathURL(url, "Composition", cmp.getIdBase()));
|
||||
Device dev = new Device();
|
||||
dev.setId("java");
|
||||
dev.addName().setValue("Java Core Library");
|
||||
dev.addVersion().setValue(VersionUtil.getVersion());
|
||||
bnd.addEntry().setResource(dev).setFullUrl(Utilities.pathURL(url, "Device", dev.getIdBase()));
|
||||
return cmp;
|
||||
}
|
||||
|
||||
private static Patient processPatient(Bundle bnd, String url, Patient pat) {
|
||||
bnd.addEntry().setResource(pat).setFullUrl(Utilities.pathURL(url, "Patient", pat.getIdBase()));
|
||||
return pat;
|
||||
}
|
||||
|
||||
private static void addMedications(Bundle bnd, Composition cmp, FHIRToolingClient server, String patientId) {
|
||||
Bundle sb = server.search("MedicationStatement", "?patient="+patientId+"&_include=MedicationStatement:medication&_include=MedicationStatement:source");
|
||||
SectionComponent sct = cmp.addSection();
|
||||
sct.setTitle("Medications");
|
||||
sct.getCode().addCoding().setSystem("http://loinc.org").setCode("10160-0");
|
||||
sct.getText().setStatus(NarrativeStatus.GENERATED);
|
||||
var x = sct.getText().getDiv();
|
||||
var tbl = x.table("grid");
|
||||
var tr = tbl.tr();
|
||||
tr.th().tx("Medication");
|
||||
tr.th().tx("Category");
|
||||
tr.th().tx("Status");
|
||||
tr.th().tx("When");
|
||||
tr.th().tx("Dosage");
|
||||
tr.th().tx("Reason");
|
||||
tr.th().tx("Source");
|
||||
tr.th().tx("Notes");
|
||||
|
||||
boolean ok = false;
|
||||
for (BundleEntryComponent be : sb.getEntry()) {
|
||||
if (be.hasResource() && be.getResource() instanceof MedicationStatement) {
|
||||
MedicationStatement mdstmt = (MedicationStatement) be.getResource();
|
||||
ok = true;
|
||||
bnd.addEntry().setResource(mdstmt).setFullUrl(Utilities.pathURL(server.getAddress(), "MedicationStatement", mdstmt.getIdBase()));
|
||||
sct.addEntry().setReference("MedicationStatement/"+mdstmt.getIdBase());
|
||||
tr = tbl.tr();
|
||||
if (mdstmt.hasMedication() && mdstmt.getMedication().hasReference()) {
|
||||
Medication med = findMedication(sb, server, mdstmt, mdstmt.getMedication().getReference());
|
||||
if (med == null) {
|
||||
tr.td().b().tx("Unknown?");
|
||||
} else {
|
||||
tr.td().tx(summarise(med));
|
||||
bnd.addEntry().setResource(med).setFullUrl(Utilities.pathURL(server.getAddress(), "Medication", med.getIdBase()));
|
||||
}
|
||||
} else {
|
||||
tr.td().tx(genCC(mdstmt.getMedication().getConcept()));
|
||||
}
|
||||
tr.td().tx(genCC(mdstmt.getCategory()));
|
||||
var td = tr.td();
|
||||
td.tx(mdstmt.getStatus().getDisplay());
|
||||
if (mdstmt.hasReason()) {
|
||||
td.tx(" (");
|
||||
for (CodeableReference cc : mdstmt.getReason()) {
|
||||
if (cc.hasConcept()) {
|
||||
td.tx(genCC(cc.getConcept()));
|
||||
} else {
|
||||
td.tx(genReference(mdstmt, cc.getReference(), bnd, sb, server));
|
||||
}
|
||||
}
|
||||
td.tx(")");
|
||||
}
|
||||
tr.td().tx(genDT(mdstmt.getEffective()));
|
||||
genDosages(tr.td(), mdstmt.getDosage());
|
||||
for (Reference is : mdstmt.getInformationSource()) {
|
||||
tr.td().tx(genReference(mdstmt, is, bnd, sb, server));
|
||||
}
|
||||
genNotes(tr.td(), mdstmt.getNote());
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
Condition cnd = new Condition();
|
||||
cnd.setId(Utilities.makeUuidLC());
|
||||
|
||||
cnd.getText().setStatus(NarrativeStatus.GENERATED);
|
||||
var rx = cnd.getText().getDiv();
|
||||
rx.tx("No information is provided about the patient's medical problems");
|
||||
tr = tbl.tr();
|
||||
tr.td().colspan(7).tx("No information is provided about the patient's medical problems");
|
||||
cnd.getClinicalStatus().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/condition-clinical").setCode("active").setDisplay("Active");
|
||||
cnd.getCode().addCoding().setSystem("http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips").setCode("no-problem-info").setDisplay("No information about current problems");
|
||||
cnd.getSubject().setReference("Patient/"+patientId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void genDosages(XhtmlNode x, List<Dosage> dosages) {
|
||||
if (dosages == null || dosages.size() == 0) {
|
||||
|
||||
} else if (dosages.size() == 1) {
|
||||
genDosage(x, dosages.get(0));
|
||||
} else {
|
||||
var ul = x.ul();
|
||||
for (Dosage d : dosages) {
|
||||
genDosage(ul.li(), d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void genDosage(XhtmlNode x, Dosage dosage) {
|
||||
x.tx(dosage.getText());
|
||||
if (dosage.hasAsNeeded() || dosage.hasAsNeededFor()) {
|
||||
x.nbsp();
|
||||
if (dosage.hasAsNeeded()) {
|
||||
if (dosage.getAsNeeded()) {
|
||||
x.tx(" (as needed)");
|
||||
}
|
||||
} else {
|
||||
for (CodeableConcept cc : dosage.getAsNeededFor()) {
|
||||
x.tx(genDT(cc));
|
||||
}
|
||||
}
|
||||
} else if (dosage.hasTiming()) {
|
||||
x.nbsp();
|
||||
x.tx(genDT(dosage.getTiming()));
|
||||
}
|
||||
if (dosage.hasSite()) {
|
||||
x.tx(". ");
|
||||
x.tx(genDT(dosage.getSite()));
|
||||
}
|
||||
if (dosage.hasRoute()) {
|
||||
x.tx(". ");
|
||||
x.tx(genDT(dosage.getRoute()));
|
||||
}
|
||||
}
|
||||
|
||||
private static Medication findMedication(Bundle sb, FHIRToolingClient server, MedicationStatement mdstmt, Reference ref) {
|
||||
if (ref == null || !ref.hasReference()) {
|
||||
return null;
|
||||
}
|
||||
if (ref.getReference().startsWith("#")) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void addConditions(Bundle bnd, Composition cmp, FHIRToolingClient server, String patientId) {
|
||||
Bundle sb = server.search("Condition", "?patient="+patientId+"&_include=Condition:asserter");
|
||||
SectionComponent sct = cmp.addSection();
|
||||
sct.setTitle("Problems");
|
||||
sct.getCode().addCoding().setSystem("http://loinc.org").setCode("11450-4");
|
||||
sct.getText().setStatus(NarrativeStatus.GENERATED);
|
||||
var x = sct.getText().getDiv();
|
||||
var tbl = x.table("grid");
|
||||
var tr = tbl.tr();
|
||||
tr.th().tx("Code");
|
||||
tr.th().tx("Category");
|
||||
tr.th().tx("Severity");
|
||||
tr.th().tx("Status");
|
||||
tr.th().tx("Onset");
|
||||
tr.th().tx("Abatement");
|
||||
tr.th().tx("Source");
|
||||
tr.th().tx("Notes");
|
||||
|
||||
boolean ok = false;
|
||||
for (BundleEntryComponent be : sb.getEntry()) {
|
||||
if (be.hasResource() && be.getResource() instanceof Condition) {
|
||||
Condition cnd = (Condition) be.getResource();
|
||||
ok = true;
|
||||
bnd.addEntry().setResource(cnd).setFullUrl(Utilities.pathURL(server.getAddress(), "Condition", cnd.getIdBase()));
|
||||
sct.addEntry().setReference("Condition/"+cnd.getIdBase());
|
||||
tr = tbl.tr();
|
||||
tr.td().tx(genCC(cnd.getCode()));
|
||||
tr.td().tx(genCC(cnd.getCategory()));
|
||||
tr.td().tx(genCC(cnd.getSeverity()));
|
||||
tr.td().tx(genStatus(cnd));
|
||||
tr.td().tx(genDT(cnd.getOnset()));
|
||||
tr.td().tx(genDT(cnd.getAbatement()));
|
||||
tr.td().tx(genSource(cnd, bnd, sb, server));
|
||||
genNotes(tr.td(), cnd.getNote());
|
||||
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
Condition cnd = new Condition();
|
||||
cnd.setId(Utilities.makeUuidLC());
|
||||
|
||||
cnd.getText().setStatus(NarrativeStatus.GENERATED);
|
||||
var rx = cnd.getText().getDiv();
|
||||
rx.tx("No information is provided about the patient's medical problems");
|
||||
tr = tbl.tr();
|
||||
tr.td().colspan(7).tx("No information is provided about the patient's medical problems");
|
||||
cnd.getClinicalStatus().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/condition-clinical").setCode("active").setDisplay("Active");
|
||||
cnd.getCode().addCoding().setSystem("http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips").setCode("no-problem-info").setDisplay("No information about current problems");
|
||||
cnd.getSubject().setReference("Patient/"+patientId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String genReference(DomainResource src, Reference ref, Bundle bnd, Bundle search, FHIRToolingClient server) {
|
||||
if (ref == null || ref.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
boolean contained = false;
|
||||
DomainResource tgt = null;
|
||||
if (ref.hasReference()) {
|
||||
if (ref.getReference().startsWith("#")) {
|
||||
tgt = (DomainResource) src.getContained(ref.getReference());
|
||||
contained = true;
|
||||
} else {
|
||||
TypeAndId tid = getTypeAndId(server.getAddress(), ref.getReference());
|
||||
if (tid != null) {
|
||||
tgt = findInBundle(bnd, Utilities.pathURL(server.getAddress(), tid.getType(), tid.getId()));
|
||||
if (tgt == null) {
|
||||
tgt = findInBundle(search, Utilities.pathURL(server.getAddress(), tid.getType(), tid.getId()));
|
||||
if (tgt == null) {
|
||||
tgt = (DomainResource) server.read(tid.getType(), tid.getId());
|
||||
}
|
||||
} else {
|
||||
contained = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tgt != null) {
|
||||
if (!contained) {
|
||||
bnd.addEntry().setResource(tgt).setFullUrl(Utilities.pathURL(server.getAddress(), tgt.fhirType(), tgt.getIdBase()));
|
||||
}
|
||||
return summarise(tgt);
|
||||
} else if (ref.hasDisplay()) {
|
||||
return ref.getDisplay();
|
||||
} else if (ref.hasReference()) {
|
||||
return ref.getReference();
|
||||
} else if (ref.hasIdentifier()) {
|
||||
return genIdentifier(ref.getIdentifier());
|
||||
} else {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static TypeAndId getTypeAndId(String baseUrl, String url) {
|
||||
if (Utilities.noString(url)) {
|
||||
return null;
|
||||
}
|
||||
if (url.startsWith(baseUrl+"/")) {
|
||||
url = url.substring(baseUrl.length()+1);
|
||||
}
|
||||
String[] p = url.split("\\/");
|
||||
if (p.length > 1) {
|
||||
if ("_history".equals(p[p.length-2]) && p.length > 3) {
|
||||
return new TypeAndId(p[p.length-4], p[p.length-3]);
|
||||
} else {
|
||||
return new TypeAndId(p[p.length-2], p[p.length-1]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DomainResource findInBundle(Bundle bnd, String url) {
|
||||
for (BundleEntryComponent be : bnd.getEntry()) {
|
||||
if (url.equals(be.getFullUrl()) && be.hasResource() && be.getResource() instanceof DomainResource) {
|
||||
return (DomainResource) be.getResource();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String summarise(DomainResource tgt) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String genIdentifier(Identifier id) {
|
||||
return id.getValue();
|
||||
}
|
||||
|
||||
private static void genNotes(XhtmlNode td, List<Annotation> notes) {
|
||||
if (notes.size() > 0) {
|
||||
if (notes.size() == 1) {
|
||||
genNote(td, notes.get(0));
|
||||
} else {
|
||||
var ul = td.ul();
|
||||
for (Annotation a : notes) {
|
||||
genNote(ul.li(), a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void genNote(XhtmlNode td, Annotation annotation) {
|
||||
td.tx(annotation.getText());
|
||||
}
|
||||
|
||||
private static String genSource(Condition cnd, Bundle bnd, Bundle sb, FHIRToolingClient server) {
|
||||
for (ConditionParticipantComponent t: cnd.getParticipant()) {
|
||||
return genCC(t.getFunction()) + " : "+genReference(cnd, t.getActor(), bnd, sb, server);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String genDT(DataType v) {
|
||||
if (v == null) {
|
||||
return null;
|
||||
}
|
||||
if (v.isPrimitive()) {
|
||||
return v.primitiveValue();
|
||||
}
|
||||
if (v instanceof Age) {
|
||||
return genQty((Age) v);
|
||||
}
|
||||
if (v instanceof Period) {
|
||||
Period p = (Period) v;
|
||||
return genDT(p.getStartElement())+" - "+genDT(p.getStartElement());
|
||||
}
|
||||
if (v instanceof Range) {
|
||||
Range p = (Range) v;
|
||||
return genDT(p.getLow())+" - "+genDT(p.getHigh());
|
||||
}
|
||||
return "not done: "+v.fhirType();
|
||||
}
|
||||
|
||||
private static String genQty(Quantity v) {
|
||||
return v.getValue().toPlainString()+v.getUnit();
|
||||
}
|
||||
|
||||
private static String genStatus(Condition cnd) {
|
||||
if (cnd.hasClinicalStatus() && cnd.hasVerificationStatus()) {
|
||||
return genCC(cnd.getClinicalStatus()) +"/"+genCC(cnd.getVerificationStatus());
|
||||
} else if (cnd.hasClinicalStatus()) {
|
||||
return genCC(cnd.getClinicalStatus());
|
||||
} else if (cnd.hasVerificationStatus()) {
|
||||
return genCC(cnd.getVerificationStatus());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String genCC(List<CodeableConcept> list) {
|
||||
if (list != null && list.size() == 1) {
|
||||
return genCC(list.get(0));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String genCC(CodeableConcept code) {
|
||||
if (code.hasText()) {
|
||||
return code.getText();
|
||||
} else if (code.hasCoding()) {
|
||||
Coding c = code.getCodingFirstRep();
|
||||
if (c.hasDisplay()) {
|
||||
return c.getDisplay();
|
||||
} else {
|
||||
return c.getCode();
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package org.hl7.fhir.r5.ips;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.r5.ips.IPSRenderer.InternalTemplateEngine;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.Composition;
|
||||
import org.hl7.fhir.r5.model.Composition.SectionComponent;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Reference;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class IPSRenderer {
|
||||
|
||||
public class InternalTemplateEngine implements ITemplateImplementer {
|
||||
|
||||
@Override
|
||||
public String buildPage(Map<String, String> headers, String content) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private interface ITemplateImplementer {
|
||||
public String buildPage(Map<String, String> headers, String content);
|
||||
}
|
||||
private ITerminologyClient tx;
|
||||
private String folder; // for images etc
|
||||
private Map<String, byte[]> binaries; // from the pubpack
|
||||
private ITemplateImplementer templater;
|
||||
private Map<String, String> headers;
|
||||
|
||||
public IPSRenderer(ITerminologyClient tx, String folder, Map<String, byte[]> binaries, ITemplateImplementer templater) {
|
||||
super();
|
||||
this.tx = tx;
|
||||
this.folder = folder;
|
||||
this.binaries = binaries;
|
||||
this.templater = templater;
|
||||
}
|
||||
|
||||
public IPSRenderer(ITerminologyClient tx, String folder, Map<String, byte[]> binaries) {
|
||||
super();
|
||||
this.tx = tx;
|
||||
this.folder = folder;
|
||||
this.binaries = binaries;
|
||||
this.templater = new InternalTemplateEngine();
|
||||
}
|
||||
|
||||
public String render(Bundle document) throws IOException {
|
||||
headers = new HashMap<>();
|
||||
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
|
||||
generate(x, document);
|
||||
return templater.buildPage(headers, new XhtmlComposer(false, true).compose(x));
|
||||
}
|
||||
|
||||
private void generate(XhtmlNode x, Bundle document) {
|
||||
Composition cmp = (Composition) document.getEntryFirstRep().getResource();
|
||||
int sectionDepth = findSectionDepth(cmp.getSection());
|
||||
XhtmlNode table = x.table("grid");
|
||||
|
||||
// row 1: header
|
||||
XhtmlNode tr = table.tr();
|
||||
XhtmlNode td = tr.td().colspan(1+sectionDepth);
|
||||
td.b().tx("Provided");
|
||||
td = tr.td().colspan(1+sectionDepth);
|
||||
td.b().tx("Generated");
|
||||
|
||||
// row 2: Subject
|
||||
DomainResource subject = findResource(document, cmp.getSubjectFirstRep());
|
||||
tr = table.tr();
|
||||
td = tr.td().colspan(1+sectionDepth);
|
||||
// genNarrative("subject", subject, td);
|
||||
td = tr.td().colspan(1+sectionDepth);
|
||||
td.b().tx("Generated");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private DomainResource findResource(Bundle document, Reference subject) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
private int findSectionDepth(List<SectionComponent> list) {
|
||||
int i = 1;
|
||||
for (SectionComponent sect : list) {
|
||||
i = Integer.max(i, 1+findSectionDepth(sect.getSection()));
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,10 @@ package org.hl7.fhir.r5.utils.client;
|
|||
import okhttp3.Headers;
|
||||
import okhttp3.internal.http2.Header;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.OperationOutcome;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.utils.client.EFhirClientException;
|
||||
|
||||
/*
|
||||
Copyright (c) 2011+, HL7, Inc.
|
||||
|
@ -200,6 +204,23 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
|||
return capabilities;
|
||||
}
|
||||
|
||||
public Resource read(String resourceClass, String id) {// TODO Change this to AddressableResource
|
||||
ResourceRequest<Resource> result = null;
|
||||
try {
|
||||
result = client.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
|
||||
getPreferredResourceFormat(), generateHeaders(), "Read " + resourceClass + "/" + id,
|
||||
timeoutNormal);
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
return result.getPayload();
|
||||
}
|
||||
|
||||
|
||||
public <T extends Resource> T read(Class<T> resourceClass, String id) {//TODO Change this to AddressableResource
|
||||
ResourceRequest<T> result = null;
|
||||
try {
|
||||
|
@ -622,7 +643,25 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
|||
public void setLanguage(String lang) {
|
||||
this.acceptLang = lang;
|
||||
}
|
||||
|
||||
public Bundle search(String type, String criteria) {
|
||||
return fetchFeed(Utilities.pathURL(base, type+criteria));
|
||||
}
|
||||
|
||||
public <T extends Resource> T fetchResource(Class<T> resourceClass, String id) {
|
||||
org.hl7.fhir.r5.utils.client.network.ResourceRequest<Resource> result = null;
|
||||
try {
|
||||
result = client.issueGetResourceRequest(resourceAddress.resolveGetResource(resourceClass, id),
|
||||
getPreferredResourceFormat(), generateHeaders(), resourceClass.getName()+"/"+id, timeoutNormal);
|
||||
} catch (IOException e) {
|
||||
throw new FHIRException(e);
|
||||
}
|
||||
if (result.isUnsuccessfulRequest()) {
|
||||
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
|
||||
(OperationOutcome) result.getPayload());
|
||||
}
|
||||
return (T) result.getPayload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,15 @@ public class ResourceAddress {
|
|||
return this.baseServiceUri;
|
||||
}
|
||||
|
||||
|
||||
public URI resolveGetUriFromResourceClassAndId(String resourceClass, String id) {
|
||||
return baseServiceUri.resolve(resourceClass + "/" + id);
|
||||
}
|
||||
|
||||
public <T extends Resource> URI resolveGetResource(Class<T> resourceClass, String id) {
|
||||
return baseServiceUri.resolve(nameForClassWithSlash(resourceClass) + "/" + id);
|
||||
}
|
||||
|
||||
public <T extends Resource> URI resolveOperationURLFromClass(Class<T> resourceClass, String name, String parameters) {
|
||||
return baseServiceUri.resolve(nameForClassWithSlash(resourceClass) +"$"+name+"?"+ parameters);
|
||||
}
|
||||
|
|
|
@ -1038,6 +1038,7 @@ public class I18nConstants {
|
|||
public static final String XHTML_IDREF_NOT_FOUND = "XHTML_IDREF_NOT_FOUND";
|
||||
public static final String XHTML_IDREF_NOT_MULTIPLE_MATCHES = "XHTML_IDREF_NOT_MULTIPLE_MATCHES";
|
||||
public static final String SD_CONTEXT_SHOULD_NOT_BE_FHIRPATH = "SD_CONTEXT_SHOULD_NOT_BE_FHIRPATH";
|
||||
public static final String TX_GENERAL_CC_ERROR_MESSAGE = "TX_GENERAL_CC_ERROR_MESSAGE";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ public class JsonLexer {
|
|||
private boolean allowUnquotedStrings;
|
||||
private List<JsonComment> comments = new ArrayList<>();
|
||||
private boolean isUnquoted;
|
||||
private String sourceName;
|
||||
|
||||
public JsonLexer(String source, boolean allowComments, boolean allowUnquotedStrings) throws IOException {
|
||||
this.source = source;
|
||||
|
@ -116,7 +117,7 @@ public class JsonLexer {
|
|||
}
|
||||
|
||||
public IOException error(String msg) {
|
||||
return new IOException("Error parsing JSON source: "+msg+" at Line "+Integer.toString(location.getLine())+" (path=["+path()+"])");
|
||||
return new IOException("Error parsing JSON source: "+msg+" at Line "+Integer.toString(location.getLine())+" (path=["+path()+"])"+(sourceName == null ? "" : " from '"+sourceName+"'"));
|
||||
}
|
||||
|
||||
private String path() {
|
||||
|
@ -300,5 +301,13 @@ public class JsonLexer {
|
|||
return "JsonLexer [cursor=" + cursor + ", peek=" + peek + ", type=" + type + ", location=" + location.toString() + "]";
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
public void setSourceName(String sourceName) {
|
||||
this.sourceName = sourceName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -52,43 +52,46 @@ import org.hl7.fhir.utilities.json.parser.JsonLexer.TokenType;
|
|||
public class JsonParser {
|
||||
|
||||
public static JsonObject parseObject(InputStream stream) throws IOException, JsonException {
|
||||
return parseObject(TextFile.streamToString(stream));
|
||||
return new JsonParser().parseJsonObject(TextFile.streamToString(stream), false, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(byte[] stream) throws IOException, JsonException {
|
||||
return parseObject(TextFile.bytesToString(stream));
|
||||
public static JsonObject parseObject(byte[] content) throws IOException, JsonException {
|
||||
return new JsonParser().parseJsonObject(TextFile.bytesToString(content), false, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(String source) throws IOException, JsonException {
|
||||
return parseObject(source, false);
|
||||
return new JsonParser().parseJsonObject(source, false, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(File source) throws IOException, JsonException {
|
||||
return parseObject(TextFile.fileToString(source));
|
||||
if (!source.exists()) {
|
||||
throw new IOException("File "+source+" not found");
|
||||
}
|
||||
return new JsonParser().setSourceName(source.getAbsolutePath()).parseJsonObject(TextFile.fileToString(source), false, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObjectFromFile(String source) throws IOException, JsonException {
|
||||
return parseObject(TextFile.fileToString(source));
|
||||
return new JsonParser().setSourceName(source).parseJsonObject(TextFile.fileToString(source), false, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObjectFromUrl(String source) throws IOException, JsonException {
|
||||
return parseObject(fetch(source));
|
||||
return new JsonParser().setSourceName(source).parseJsonObject(TextFile.bytesToString(fetch(source)), false, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(InputStream stream, boolean isJson5) throws IOException, JsonException {
|
||||
return parseObject(TextFile.streamToString(stream), isJson5);
|
||||
return new JsonParser().parseJsonObject(TextFile.streamToString(stream), isJson5, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(byte[] stream, boolean isJson5) throws IOException, JsonException {
|
||||
return parseObject(TextFile.bytesToString(stream), isJson5);
|
||||
public static JsonObject parseObject(byte[] content, boolean isJson5) throws IOException, JsonException {
|
||||
return new JsonParser().parseJsonObject(TextFile.bytesToString(content), isJson5, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(String source, boolean isJson5) throws IOException, JsonException {
|
||||
return parseObject(source, isJson5, false);
|
||||
return new JsonParser().parseJsonObject(source, isJson5, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObjectFromUrl(String source, boolean isJson5) throws IOException, JsonException {
|
||||
return parseObject(fetch(source), isJson5);
|
||||
return new JsonParser().setSourceName(source).parseJsonObject(TextFile.bytesToString(fetch(source)), isJson5, false);
|
||||
}
|
||||
|
||||
public static JsonObject parseObject(InputStream stream, boolean isJson5, boolean allowDuplicates) throws IOException, JsonException {
|
||||
|
@ -98,7 +101,7 @@ public class JsonParser {
|
|||
public static JsonObject parseObject(byte[] stream, boolean isJson5, boolean allowDuplicates) throws IOException, JsonException {
|
||||
return parseObject(TextFile.bytesToString(stream), isJson5, allowDuplicates);
|
||||
}
|
||||
|
||||
|
||||
public static JsonObject parseObject(String source, boolean isJson5, boolean allowDuplicates) throws IOException, JsonException {
|
||||
return new JsonParser().parseJsonObject(source, isJson5, allowDuplicates);
|
||||
}
|
||||
|
@ -216,6 +219,7 @@ public class JsonParser {
|
|||
private boolean allowUnquotedStrings;
|
||||
private boolean itemUnquoted;
|
||||
private boolean valueUnquoted;
|
||||
private String sourceName;
|
||||
|
||||
private JsonObject parseJsonObject(String source, boolean isJson5, boolean allowDuplicates) throws IOException, JsonException {
|
||||
this.allowDuplicates = allowDuplicates;
|
||||
|
@ -227,6 +231,7 @@ public class JsonParser {
|
|||
|
||||
private JsonObject parseSource(String source) throws IOException, JsonException {
|
||||
lexer = new JsonLexer(source, allowComments, allowUnquotedStrings);
|
||||
lexer.setSourceName(sourceName);
|
||||
JsonObject result = new JsonObject();
|
||||
lexer.takeComments(result);
|
||||
result.setStart(lexer.getLastLocationAWS().copy());
|
||||
|
@ -671,4 +676,15 @@ public class JsonParser {
|
|||
res.checkThrowException();
|
||||
return res.getContent();
|
||||
}
|
||||
|
||||
public String getSourceName() {
|
||||
return sourceName;
|
||||
}
|
||||
|
||||
public JsonParser setSourceName(String sourceName) {
|
||||
this.sourceName = sourceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue