fix document validation + add questionnaire validation tests
This commit is contained in:
parent
5afc745424
commit
22f4a5a58f
|
@ -0,0 +1,162 @@
|
|||
package org.hl7.fhir.dstu3.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.hl7.fhir.dstu3.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.dstu3.formats.JsonParser;
|
||||
import org.hl7.fhir.dstu3.formats.XmlParser;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.DomainResource;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
|
||||
public class R3TEchnicalCorrectionProcessor {
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException, IOException {
|
||||
new R3TEchnicalCorrectionProcessor().execute(args[0], args[1]);
|
||||
|
||||
}
|
||||
|
||||
private void execute(String src, String packageRoot) throws FileNotFoundException, IOException {
|
||||
System.out.println("Loading resources from "+src);
|
||||
List<Resource> resources = new ArrayList<>();
|
||||
Map<String, Resource> definitions = new HashMap<>();
|
||||
for (File f : new File(src).listFiles()) {
|
||||
if (f.getName().endsWith(".xml") && !(f.getName().endsWith("warnings.xml") || f.getName().endsWith(".diff.xml"))) {
|
||||
try {
|
||||
Resource r = new XmlParser().parse(new FileInputStream(f));
|
||||
if (f.getName().contains("canonical")) {
|
||||
resources.add(r);
|
||||
}
|
||||
if (Utilities.existsInList(f.getName(), "conceptmaps.xml", "dataelements.xml", "extension-definitions.xml", "profiles-others.xml", "profiles-resources.xml",
|
||||
"profiles-types.xml", "search-parameters.xml", "v2-tables.xml", "v3-codesystems.xml", "valuesets.xml")) {
|
||||
definitions.put(f.getName(), r);
|
||||
}
|
||||
r.setUserData("path", f.getName().substring(0, f.getName().indexOf(".")));
|
||||
// FileUtils.copyFile(f, new File(f.getAbsolutePath()+"1"));
|
||||
// FileUtils.copyFile(f, new File(f.getAbsolutePath()+"2"));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Unable to load "+f.getName()+": "+e.getMessage());
|
||||
}
|
||||
}
|
||||
if (f.getName().endsWith(".json") && !(f.getName().endsWith("schema.json") || f.getName().endsWith(".diff.json"))) {
|
||||
try {
|
||||
// new JsonParser().parse(new FileInputStream(f));
|
||||
// FileUtils.copyFile(f, new File(f.getAbsolutePath()+"1"));
|
||||
// FileUtils.copyFile(f, new File(f.getAbsolutePath()+"2"));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Unable to load "+f.getName()+": "+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(Integer.toString(resources.size())+" resources");
|
||||
System.out.println(Integer.toString(definitions.size())+" resources");
|
||||
produceExamplesXml(resources, src);
|
||||
produceDefinitionsXml(definitions, src);
|
||||
produceExamplesJson(resources, src);
|
||||
produceDefinitionsJson(definitions, src);
|
||||
for (Resource r : definitions.values()) {
|
||||
if (r instanceof Bundle) {
|
||||
Bundle bnd = (Bundle) r;
|
||||
for (BundleEntryComponent be : bnd.getEntry()) {
|
||||
resources.add(be.getResource());
|
||||
}
|
||||
}
|
||||
}
|
||||
extractToPackageMaster(resources, packageRoot);
|
||||
System.out.println("Done");
|
||||
}
|
||||
|
||||
private void produceDefinitionsXml(Map<String, Resource> definitions, String dest) throws IOException {
|
||||
for (String n : definitions.keySet()) {
|
||||
File f = new File(Utilities.path(dest, "definitions.xml", n));
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(f), definitions.get(n));
|
||||
}
|
||||
}
|
||||
|
||||
private void produceDefinitionsJson(Map<String, Resource> definitions, String dest) throws IOException {
|
||||
for (String n : definitions.keySet()) {
|
||||
File f = new File(Utilities.path(dest, "definitions.json", Utilities.changeFileExt(n, ".json")));
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(f), definitions.get(n));
|
||||
}
|
||||
}
|
||||
|
||||
private void produceExamplesJson(List<Resource> resources, String dest) throws FileNotFoundException, IOException {
|
||||
for (Resource r : resources) {
|
||||
String n = r.fhirType().toLowerCase()+"-"+r.getUserString("path");
|
||||
if (!r.getId().equals(r.getUserString("path"))) {
|
||||
n = n+"("+r.getId()+")";
|
||||
}
|
||||
File f = new File(Utilities.path(dest, "examples-json", n+".json"));
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(f), r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void produceExamplesXml(List<Resource> resources, String dest) throws FileNotFoundException, IOException {
|
||||
for (Resource r : resources) {
|
||||
String n = r.fhirType().toLowerCase()+"-"+r.getUserString("path");
|
||||
if (!r.getId().equals(r.getUserString("path"))) {
|
||||
n = n+"("+r.getId()+")";
|
||||
}
|
||||
File f = new File(Utilities.path(dest, "examples", n+".xml"));
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(f), r);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractToPackageMaster(List<Resource> list, String root) throws IOException, FHIRFormatError {
|
||||
System.out.println("Updating Packages Master");
|
||||
String corePath = Utilities.path(root, "hl7.fhir.r3.core", "package");
|
||||
String examplesPath = Utilities.path(root, "hl7.fhir.r3.examples", "package");
|
||||
String elementsPath = Utilities.path(root, "hl7.fhir.r3.elements", "package");
|
||||
int coreTotal = new File(corePath).list().length-1;
|
||||
int examplesTotal = new File(examplesPath).list().length-1;
|
||||
int elementsTotal = new File(elementsPath).list().length-1;
|
||||
|
||||
int coreCount = 0;
|
||||
int examplesCount = 0;
|
||||
int elementsCount = 0;
|
||||
for (Resource r : list) {
|
||||
String n = r.fhirType()+"-"+r.getId()+".json";
|
||||
FileOutputStream dst = null;
|
||||
if (n.startsWith("DataElement-")) {
|
||||
elementsCount++;
|
||||
dst = new FileOutputStream(Utilities.path(elementsPath, n));
|
||||
new JsonParser().setOutputStyle(OutputStyle.NORMAL).compose(dst, r);
|
||||
} else {
|
||||
dst = new FileOutputStream(Utilities.path(examplesPath, n));
|
||||
new JsonParser().setOutputStyle(OutputStyle.NORMAL).compose(dst, r);
|
||||
if (isCoreResource(r.fhirType())) {
|
||||
coreCount++;
|
||||
DomainResource dr = (DomainResource) r;
|
||||
dr.setText(null);
|
||||
new JsonParser().setOutputStyle(OutputStyle.NORMAL).compose(new FileOutputStream(Utilities.path(corePath, n)), r);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(" Core @ "+corePath+": Replaced "+coreCount+" of "+coreTotal);
|
||||
System.out.println(" Examples @ "+examplesPath+": Replaced "+examplesCount+" of "+examplesTotal);
|
||||
System.out.println(" Elements @ "+elementsPath+": Replaced "+elementsCount+" of "+elementsTotal);
|
||||
}
|
||||
|
||||
private boolean isCoreResource(String rt) {
|
||||
return Utilities.existsInList(rt, "CapabilityStatement", "CodeSystem", "CompartmentDefinition", "ConceptMap", "NamingSystem", "OperationDefinition", "SearchParameter", "StructureDefinition", "StructureMap", "ValueSet");
|
||||
}
|
||||
|
||||
}
|
|
@ -91,7 +91,7 @@ public abstract class ParserBase {
|
|||
|
||||
protected StructureDefinition getDefinition(int line, int col, String ns, String name) throws FHIRFormatError {
|
||||
if (ns == null) {
|
||||
logError(line, col, name, IssueType.STRUCTURE, "This cannot be parsed as a FHIR object (no namespace)", IssueSeverity.FATAL);
|
||||
logError(line, col, name, IssueType.STRUCTURE, "This '"+name+"' cannot be parsed as a FHIR object (no namespace)", IssueSeverity.FATAL);
|
||||
return null;
|
||||
}
|
||||
if (name == null) {
|
||||
|
|
|
@ -2306,6 +2306,8 @@ public class ElementDefinition extends BackboneType implements ICompositeType {
|
|||
return "integer";
|
||||
if ("xsd:decimal OR xsd:double".equals(s))
|
||||
return "decimal";
|
||||
if ("xsd:decimal".equals(s))
|
||||
return "decimal";
|
||||
if ("xsd:base64Binary".equals(s))
|
||||
return "base64Binary";
|
||||
if ("xsd:positiveInteger".equals(s))
|
||||
|
|
|
@ -1001,7 +1001,7 @@ public class TurtleTests {
|
|||
}
|
||||
@Test
|
||||
public void test_turtle_syntax_bad_number_dot_in_anon() throws Exception {
|
||||
doTest(TestingUtilities.resourceNameToFile("turtle", "turtle-syntax-bad-number-dot-in-anon.ttl"), true);
|
||||
doTest(TestingUtilities.resourceNameToFile("turtle", "turtle-syntax-bad-number-dot-in-anon.ttl"), false);
|
||||
}
|
||||
@Test
|
||||
public void test_turtle_syntax_bad_pname_01() throws Exception {
|
||||
|
|
|
@ -131,6 +131,9 @@ public class EnableWhenEvaluator {
|
|||
* @return
|
||||
*/
|
||||
public boolean isQuestionEnabled(QuestionnaireItemComponent qitem, QStack qstack) {
|
||||
if (hasExpressionExtension(qitem)) {
|
||||
throw new Error("Not Done Yet");
|
||||
}
|
||||
if (!qitem.hasEnableWhen()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -142,6 +145,12 @@ public class EnableWhenEvaluator {
|
|||
}
|
||||
|
||||
|
||||
private boolean hasExpressionExtension(QuestionnaireItemComponent qitem) {
|
||||
return qitem.hasExtension("http://phr.kanta.fi/StructureDefinition/fiphr-ext-questionnaire-enablewhen") || // finnish extension
|
||||
qitem.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression"); // sdc extension
|
||||
}
|
||||
|
||||
|
||||
public boolean checkConditionResults(List<EnableWhenResult> evaluationResults, QuestionnaireItemComponent questionnaireItem) {
|
||||
if ((questionnaireItem.hasEnableBehavior() && questionnaireItem.getEnableBehavior() == EnableWhenBehavior.ANY) || evaluationResults.size() == 1){
|
||||
return evaluationResults.stream().anyMatch(EnableWhenResult::isEnabled);
|
||||
|
|
|
@ -3905,7 +3905,7 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
|
||||
if (ref != null && !Utilities.noString(reference)) {
|
||||
Element target = resolveInBundle(entries, reference, fullUrl, type, id);
|
||||
rule(errors, IssueType.INVALID, ref.line(), ref.col(), stack.addToLiteralPath("reference"), target != null, "Unable to resolve the target of the reference in the bundle (" + name + ")");
|
||||
rule(errors, IssueType.INVALID, ref.line(), ref.col(), stack.addToLiteralPath("reference"), target != null, "Can't find '"+reference+"' in the bundle (" + name + ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3925,13 +3925,47 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
// first entry must be a composition
|
||||
if (rule(errors, IssueType.INVALID, composition.line(), composition.col(), stack.getLiteralPath(), composition.getType().equals("Composition"),
|
||||
"The first entry in a document must be a composition")) {
|
||||
// the composition subject and section references must resolve in the bundle
|
||||
Element elem = composition.getNamedChild("subject");
|
||||
if (rule(errors, IssueType.INVALID, composition.line(), composition.col(), stack.getLiteralPath(), elem != null, "A document composition must have a subject"))
|
||||
validateBundleReference(errors, entries, elem, "Composition Subject", stack.push(elem, -1, null, null), fullUrl, "Composition", id);
|
||||
|
||||
// the composition subject etc references must resolve in the bundle
|
||||
validateDocumentReference(errors, entries, composition, stack, fullUrl, id, false, "subject", "Composition");
|
||||
validateDocumentReference(errors, entries, composition, stack, fullUrl, id, true, "author", "Composition");
|
||||
validateDocumentReference(errors, entries, composition, stack, fullUrl, id, false, "encounter", "Composition");
|
||||
validateDocumentReference(errors, entries, composition, stack, fullUrl, id, false, "custodian", "Composition");
|
||||
validateDocumentSubReference(errors, entries, composition, stack, fullUrl, id, "Composition", "attester", false, "party");
|
||||
validateDocumentSubReference(errors, entries, composition, stack, fullUrl, id, "Composition", "event", true, "detail");
|
||||
|
||||
validateSections(errors, entries, composition, stack, fullUrl, id);
|
||||
}
|
||||
}
|
||||
|
||||
public void validateDocumentSubReference(List<ValidationMessage> errors, List<Element> entries, Element composition, NodeStack stack, String fullUrl, String id, String title, String parent, boolean repeats, String propName) {
|
||||
List<Element> list = new ArrayList<>();
|
||||
composition.getNamedChildren(parent, list);
|
||||
int i = 1;
|
||||
for (Element elem : list) {
|
||||
validateDocumentReference(errors, entries, elem, stack.push(elem, i, null, null), fullUrl, id, repeats, propName, title+"."+parent);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public void validateDocumentReference(List<ValidationMessage> errors, List<Element> entries, Element composition, NodeStack stack, String fullUrl, String id, boolean repeats, String propName, String title) {
|
||||
if (repeats) {
|
||||
List<Element> list = new ArrayList<>();
|
||||
composition.getNamedChildren(propName, list);
|
||||
int i = 1;
|
||||
for (Element elem : list) {
|
||||
validateBundleReference(errors, entries, elem, title+"."+propName, stack.push(elem, i, null, null), fullUrl, "Composition", id);
|
||||
i++;
|
||||
}
|
||||
|
||||
} else {
|
||||
Element elem = composition.getNamedChild(propName);
|
||||
if (elem != null) {
|
||||
validateBundleReference(errors, entries, elem, title+"."+propName, stack.push(elem, -1, null, null), fullUrl, "Composition", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), "Bundle", !"urn:guid:".equals(base), "The base 'urn:guid:' is not valid (use urn:uuid:)");
|
||||
// rule(errors, IssueType.INVALID, entry.line(), entry.col(), localStack.getLiteralPath(), !"urn:guid:".equals(ebase), "The base 'urn:guid:' is not valid");
|
||||
// rule(errors, IssueType.INVALID, entry.line(), entry.col(), localStack.getLiteralPath(), !Utilities.noString(base) || !Utilities.noString(ebase), "entry
|
||||
|
@ -4590,11 +4624,23 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
|
|||
|
||||
private void validateSections(List<ValidationMessage> errors, List<Element> entries, Element focus, NodeStack stack, String fullUrl, String id) {
|
||||
List<Element> sections = new ArrayList<Element>();
|
||||
focus.getNamedChildren("entry", sections);
|
||||
int i = 0;
|
||||
focus.getNamedChildren("section", sections);
|
||||
int i = 1;
|
||||
for (Element section : sections) {
|
||||
NodeStack localStack = stack.push(section, 1, null, null);
|
||||
validateBundleReference(errors, entries, section.getNamedChild("content"), "Section Content", localStack, fullUrl, "Composition", id);
|
||||
NodeStack localStack = stack.push(section, i, null, null);
|
||||
|
||||
// technically R4+, but there won't be matches from before that
|
||||
validateDocumentReference(errors, entries, section, stack, fullUrl, id, false, "author", "Section");
|
||||
validateDocumentReference(errors, entries, section, stack, fullUrl, id, false, "focus", "Section");
|
||||
|
||||
List<Element> sectionEntries = new ArrayList<Element>();
|
||||
section.getNamedChildren("entry", sectionEntries);
|
||||
int j = 1;
|
||||
for (Element sectionEntry : sectionEntries) {
|
||||
NodeStack localStack2 = localStack.push(sectionEntry, j, null, null);
|
||||
validateBundleReference(errors, entries, sectionEntry, "Section Entry", localStack2, fullUrl, "Composition", id);
|
||||
j++;
|
||||
}
|
||||
validateSections(errors, entries, section, localStack, fullUrl, id);
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,641 @@
|
|||
|
||||
{
|
||||
"resourceType" : "Bundle",
|
||||
"id" : "9e11848b-0e37-4bc6-92cf-153b0917cd22",
|
||||
"identifier" : {
|
||||
"value" : "889977665544",
|
||||
"system" : "http://spms.min-saude.pt/SClinico/code"
|
||||
},
|
||||
"type" : "document",
|
||||
"entry" : [
|
||||
{
|
||||
"fullUrl" : "http://spms.min-saude.pt/fhir/Composition/27eab09d-74bc-4ad3-95b1-d890b7db4c2b",
|
||||
"resource" : {
|
||||
"resourceType" : "Composition",
|
||||
"id" : "27eab09d-74bc-4ad3-95b1-d890b7db4c2b",
|
||||
"identifier" : {
|
||||
"system" : "http://spms.min-saude.pt/SClinico/code",
|
||||
"value" : "889977665544"
|
||||
},
|
||||
"status" : "final",
|
||||
"type" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "18842-5",
|
||||
"display" : "Discharge Summary"
|
||||
}
|
||||
]
|
||||
},
|
||||
"subject" : {
|
||||
"reference" : "Patient/94615767-9ba1-482c-8930-fdda1a0baea8"
|
||||
},
|
||||
"encounter" : {
|
||||
"reference" : "Encounter/17bcea80-37a6-43ec-a40c-427ab904edd8"
|
||||
},
|
||||
"date" : "2019-10-02T16:48:19.000+00:00",
|
||||
"author" : [
|
||||
{
|
||||
"reference" : "Practitioner/88b07e2d-73dc-4b87-b1cf-c0d0eddd0e5c"
|
||||
},
|
||||
{
|
||||
"reference" : "Practitioner/09b68ca1-4088-48bd-9768-1c8bf6118607"
|
||||
},
|
||||
{
|
||||
"reference" : "Practitioner/ca85c061-8c81-4ff8-8188-cae8d231d872"
|
||||
},
|
||||
{
|
||||
"reference" : "Practitioner/46d2e8af-e3fb-408d-a042-43c3561291e3"
|
||||
}
|
||||
],
|
||||
"attester" : [
|
||||
{
|
||||
"mode" : ["personal"],
|
||||
"party" : {
|
||||
"reference" : "Practitioner/46d2e8af-e3fb-408d-a042-43c3561291e3"
|
||||
}
|
||||
}
|
||||
],
|
||||
"title" : "Nota de alta de internamento",
|
||||
"custodian" : {
|
||||
"reference" : "Organization/08748631-6f66-46fd-a8c5-528b574dc33d"
|
||||
},
|
||||
"event" : [
|
||||
{
|
||||
"detail" : [
|
||||
{
|
||||
"reference" : "Encounter/17bcea80-37a6-43ec-a40c-427ab904edd8"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"section" : [
|
||||
{
|
||||
"title" : "Allergies",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "48765-2",
|
||||
"display" : "Allergies"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "AllergyIntolerance/4f9ad961-d5f1-4888-aa6c-05d003fce450"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Hospital course Narrative",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "8648-8",
|
||||
"display" : "Hospital course Narrative"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Observation/5da5de2d-93c8-40db-90b6-7d1763fed7f5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Discharge diagnosis Narrative",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "78375-3",
|
||||
"display" : "Discharge diagnosis Narrative"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Encounter/17bcea80-37a6-43ec-a40c-427ab904edd8"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Discharge medications Narrative",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "75311-1",
|
||||
"display" : "Discharge medications Narrative"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "MedicationRequest/b684690b-bb71-45b3-9779-88fd89f1d0b5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Admission diagnosis (narrative)",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "42347-5",
|
||||
"display" : "Admission diagnosis (narrative)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Encounter/17bcea80-37a6-43ec-a40c-427ab904edd8"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Medications on admission (narrative)",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "42346-7",
|
||||
"display" : "Medications on admission (narrative)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "MedicationAdministration/199a4838-e1ba-4408-8ca2-da6a826373da"
|
||||
},
|
||||
{
|
||||
"reference" : "MedicationAdministration/d6c8c9b2-da4e-4aac-9200-b79b05480402"
|
||||
},
|
||||
{
|
||||
"reference" : "MedicationAdministration/4db8b223-8c95-4554-9e7f-86906a6c80da"
|
||||
},
|
||||
{
|
||||
"reference" : "MedicationAdministration/d8adcea3-f539-4dcb-baef-f049bb5eae33"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Discharge diet (narrative)",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "42344-2",
|
||||
"display" : "Discharge diet (narrative)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Observation/20b06357-2287-4246-b637-0c0c510ac2d5"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "History of Present illness Narrative",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "10164-2",
|
||||
"display" : "History of Present illness Narrative"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Observation/aaa443d5-222d-4e4b-8291-155750ba9bf6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Plan of Care",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "18776-5",
|
||||
"display" : "Plan of care"
|
||||
}
|
||||
]
|
||||
},
|
||||
"section" : [
|
||||
{
|
||||
"title" : "Proposta de monitorização e tratamento",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "PMT",
|
||||
"display" : "Proposta de monitorização e tratamento"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Observation/cfddbb48-045d-4853-b4f4-e18a2d72701f"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Orientação/agendamentos",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "ORI",
|
||||
"display" : "Orientação/agendamentos"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Appointment/ac28d16e-0631-4e9b-9bbf-873339010e29"
|
||||
},
|
||||
{
|
||||
"reference" : "Appointment/b54abdba-8f77-4900-9c79-bda7e0348eed"
|
||||
},
|
||||
{
|
||||
"reference" : "Appointment/e1574ddd-7a92-42cd-8a6f-733180dd1291"
|
||||
},
|
||||
{
|
||||
"reference" : "Appointment/5c5af0ca-ccc6-4821-91eb-ef32b7d483e6"
|
||||
},
|
||||
{
|
||||
"reference" : "Appointment/42e5f192-32aa-4eb2-a90e-7e3ff2f8d701"
|
||||
},
|
||||
{
|
||||
"reference" : "Appointment/c960cc20-15fb-4ef9-867d-d13c96750ea8"
|
||||
},
|
||||
{
|
||||
"reference" : "Appointment/f1d8748c-057e-437b-a8b2-5f7642250e5e"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Meios complementares de diagnóstico marcados",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "MCDTM",
|
||||
"display" : "Meios complementares de diagnóstico marcados"
|
||||
}
|
||||
]
|
||||
},
|
||||
"emptyReason" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list-empty-reason",
|
||||
"code" : "not-found",
|
||||
"display" : "Not Found"
|
||||
}
|
||||
],
|
||||
"text" : "Não foram encontrados registos para este utente"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Functional status assessment note",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "47420-5",
|
||||
"display" : "Functional status assessment note"
|
||||
}
|
||||
]
|
||||
},
|
||||
"section" : [
|
||||
{
|
||||
"title" : "Focos de diagnóstico de enfermagem",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "FDE",
|
||||
"display" : "Focos de diagnóstio de enfermagem"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Condition/3d4dcb01-5e84-4de3-bfd1-2c7a873acd74"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Atitudes Terapêuticas",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "ATI",
|
||||
"display" : "Atitudes terapêuticas"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Procedure/1cdba079-e745-4ff3-bfd6-6fae81238be8"
|
||||
},
|
||||
{
|
||||
"reference" : "Procedure/42077cf6-64c0-4309-ab0d-bb1859da03ae"
|
||||
},
|
||||
{
|
||||
"reference" : "Procedure/85b5f07c-f1cf-4038-be23-5ad2b9d89e92"
|
||||
},
|
||||
{
|
||||
"reference" : "Procedure/2afedeb5-0c0f-4e0a-a506-93f03c8bd382"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "History of Procedures Document",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "47519-4",
|
||||
"display" : "History of Procedures Document"
|
||||
}
|
||||
]
|
||||
},
|
||||
"section" : [
|
||||
{
|
||||
"title" : "Dispositivos implantáveis",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "DIS",
|
||||
"display" : "Dispositivos implantáveis"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Device/5b237d94-0ae3-49a2-9a8a-ef39607cc68d"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Intervenções Cirúrgicas",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "INT",
|
||||
"display" : "Intervenções cirúrgicas"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Procedure/59b211c5-32aa-4c28-91df-d81de43b1bd1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Ventilação Mecânica",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "VEN",
|
||||
"display" : "Ventilação mecânica"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Procedure/ce38198b-f2e1-4625-85d7-5c58a9eb8c94"
|
||||
},
|
||||
{
|
||||
"reference" : "Procedure/4a42b0a8-d198-42fc-9658-d24a2214fc8d"
|
||||
},
|
||||
{
|
||||
"reference" : "Procedure/0ee5087f-d047-453a-afdc-d6eccba2d2df"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Infeção nosocomial",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "INF",
|
||||
"display" : "Infeção nosocomial"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Procedure/a96a4c64-976a-42e5-938a-f54b844e07b0"
|
||||
},
|
||||
{
|
||||
"reference" : "Procedure/b18f9160-91eb-4d19-b7d2-25dc4e66cc2c"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Meios complementares de diagnósticos efetuados",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://spms.min-saude.pt/valueset-list",
|
||||
"code" : "MCDTE",
|
||||
"display" : "Meios complementares de diagnósticos efetuados"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "ProcedureRequest/47d0cf17-65aa-4f65-abb0-1f4e4cf53f35"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/e8814151-03c6-4f85-9caf-a8ea606acb5c"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/1b1ae576-fae6-425c-a85b-78e222b269f7"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/7ed52dda-afde-4b4a-bb60-0b5600d598bd"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/8a426c75-119e-441e-bfea-55fdc50118ba"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/82a006cd-939b-4dde-8982-5f875ed862cc"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/cc8b9f10-cd3b-4240-8352-b8346cf48205"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/8b7fbb19-5ca1-4f47-8b0b-6fedcc543b5f"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/c8e08048-0c43-42b9-a611-6c92705a910d"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/26587c9f-5041-4313-ac03-ab8feda7951a"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/d65a5ce6-97fe-4959-9660-6c096d70b3a1"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/018aea83-70f9-44db-908b-bd8a0f475cd3"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/3346f637-c83f-4a3f-a82d-fbfce6286f3d"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/38ca8f90-71b2-44d9-a6cb-97aaf2df8781"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/c9320c07-569c-413f-8ffa-ef0fdaacac23"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/b4c2ec41-e1fe-43be-9ea4-97f34deca878"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/921f8560-5eb5-46fa-8dcd-0972756f5880"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/7de5bf65-09a5-4be8-8edb-9e909296e8e0"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/ff40f491-2a57-44ee-be62-19c63a5e5481"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/a2c80ea2-9b8d-46ce-a846-1b5b6a98d2a6"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/c9daa080-ef42-4b67-b252-566c4a334f81"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/206615ca-448a-418f-a287-96cb9e4ba4c4"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/307bc183-46fc-44f5-930d-af9602573204"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/a8ae7ec5-e2e4-402b-b578-4f52de17865f"
|
||||
},
|
||||
{
|
||||
"reference" : "ProcedureRequest/43dd4257-cd53-4cba-a851-beec3730c98f"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Review of systems Narrative - Reporte",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "10187-3",
|
||||
"display" : "Review of systems Narrative Reporte"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Observation/74f5c1f7-e6d9-4cac-bff8-5f22bbbdd501"
|
||||
},
|
||||
{
|
||||
"reference" : "Observation/5957c0e2-ad3c-43e0-b45e-c002d2b45f05"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title" : "Administrative information",
|
||||
"code" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://loinc.org",
|
||||
"code" : "87504-7",
|
||||
"display" : "Administrative information"
|
||||
}
|
||||
]
|
||||
},
|
||||
"entry" : [
|
||||
{
|
||||
"reference" : "Patient/94615767-9ba1-482c-8930-fdda1a0baea8"
|
||||
},
|
||||
{
|
||||
"reference" : "Encounter/17bcea80-37a6-43ec-a40c-427ab904edd8"
|
||||
},
|
||||
{
|
||||
"reference" : "List/0f1eedb7-9d71-456b-b228-e910a9723dd6"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"fullUrl" : "http://spms.min-saude.pt/fhir/Patient/94615767-9ba1-482c-8930-fdda1a0baea8",
|
||||
"resource" : {
|
||||
"resourceType" : "Patient",
|
||||
"id" : "94615767-9ba1-482c-8930-fdda1a0baea8",
|
||||
"identifier" : [
|
||||
{
|
||||
"type" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://hl7.org/fhir/v2/0203",
|
||||
"code" : "HC",
|
||||
"display" : "Health Card Number"
|
||||
}
|
||||
],
|
||||
"text" : "NNU"
|
||||
},
|
||||
"system" : "http://spms.min-saude.pt/rnu/identifiers/patient-id",
|
||||
"value" : "383816471"
|
||||
},
|
||||
{
|
||||
"type" : {
|
||||
"coding" : [
|
||||
{
|
||||
"system" : "http://hl7.org/fhir/v2/0203",
|
||||
"code" : "MR",
|
||||
"display" : "Medical Record Number"
|
||||
}
|
||||
],
|
||||
"text" : "Número do Processo"
|
||||
},
|
||||
"system" : "https://www.sns.gov.pt/hospitalfacilities/1137006/identifiers/patient-id",
|
||||
"value" : "99149257"
|
||||
}
|
||||
],
|
||||
"name" : [
|
||||
{
|
||||
"text" : "MARTIM RICARDO FERREIRA",
|
||||
"given" : [
|
||||
"RICARDO",
|
||||
"FERREIRA"
|
||||
],
|
||||
"family" : "MARTIM"
|
||||
}
|
||||
],
|
||||
"gender" : "male",
|
||||
"birthDate" : "1943-11-24"
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -200,6 +200,11 @@
|
|||
},
|
||||
"fhirpath-null.json": {
|
||||
"errorCount": 1
|
||||
},
|
||||
"Bundle.document.json": {
|
||||
"version" : "3.0",
|
||||
"errorCount": 68,
|
||||
"errors-for-debugging" : ["68 errors to do with things not found in the bundle"],
|
||||
},
|
||||
"qr-ex.json": {
|
||||
"questionnaire": "q-ex.json",
|
||||
|
@ -653,6 +658,18 @@
|
|||
"questionnaire": "questionnaire-enableWhen-test.xml",
|
||||
"errorCount": 0
|
||||
},
|
||||
"questionnaireResponse-enableWhen-test-fail.xml": {
|
||||
"questionnaire": "questionnaire-enableWhen-test.xml",
|
||||
"errorCount": 1
|
||||
},
|
||||
"questionnaireResponse-enableWhenEx-test.xml": {
|
||||
"questionnaire": "questionnaire-enableWhenEx-test.xml",
|
||||
"errorCount": 0
|
||||
},
|
||||
"questionnaireResponse-enableWhenEx-test-fail.xml": {
|
||||
"questionnaire": "questionnaire-enableWhenEx-test.xml",
|
||||
"errorCount": 1
|
||||
},
|
||||
"questionnaireResponse-enableWhen-test-nested.xml": {
|
||||
"questionnaire": "questionnaire-enableWhen-test-nested.xml",
|
||||
"errorCount": 2
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Questionnaire xmlns="http://hl7.org/fhir">
|
||||
<id value="questionnaire-enableWhen-test" />
|
||||
<language value="en-US" />
|
||||
<text>
|
||||
<status value="generated" />
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
|
||||
<p>enableWhen test</p>
|
||||
</div>
|
||||
</text>
|
||||
<url value="http://hl7.org/fhir/us/hai/Questionnaire/questionnaire-enableWhenEx-test" />
|
||||
<status value="draft" />
|
||||
<item>
|
||||
<linkId value="condition" />
|
||||
<text value="condition" />
|
||||
<type value="boolean" />
|
||||
<required value="true" />
|
||||
<repeats value="false" />
|
||||
</item>
|
||||
<item>
|
||||
<extension url="http://phr.kanta.fi/StructureDefinition/fiphr-ext-questionnaire-enablewhen">
|
||||
<valueString value="QuestionnaireResponse.descendants().select(item).where(linkId='condition').answer.value.ofType('boolean')" />
|
||||
</extension>
|
||||
<linkId value="enable-when" />
|
||||
<text value="enable when condition true" />
|
||||
<type value="boolean" />
|
||||
<required value="true" />
|
||||
<repeats value="false" />
|
||||
</item>
|
||||
</Questionnaire>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<QuestionnaireResponse xmlns="http://hl7.org/fhir">
|
||||
<id value="questionnaireResponse-enableWhen-test" />
|
||||
<text>
|
||||
<status value="generated" />
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
|
||||
<p>enableWhen test response</p>
|
||||
</div>
|
||||
</text>
|
||||
<questionnaire value="http://hl7.org/fhir/us/hai/Questionnaire/questionnaire-enableWhen-test" />
|
||||
<status value="completed" />
|
||||
<item>
|
||||
<linkId value="condition" />
|
||||
<text value="condition" />
|
||||
<answer>
|
||||
<valueBoolean value="false" />
|
||||
</answer>
|
||||
</item>
|
||||
<item>
|
||||
<linkId value="enable-when" />
|
||||
<text value="enable when condition true" />
|
||||
<answer>
|
||||
<valueBoolean value="false" />
|
||||
</answer>
|
||||
</item>
|
||||
</QuestionnaireResponse>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<QuestionnaireResponse xmlns="http://hl7.org/fhir">
|
||||
<id value="questionnaireResponse-enableWhen-test" />
|
||||
<text>
|
||||
<status value="generated" />
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
|
||||
<p>enableWhen test response</p>
|
||||
</div>
|
||||
</text>
|
||||
<questionnaire value="http://hl7.org/fhir/us/hai/Questionnaire/questionnaire-enableWhenEx-test" />
|
||||
<status value="completed" />
|
||||
<item>
|
||||
<linkId value="condition" />
|
||||
<text value="condition" />
|
||||
<answer>
|
||||
<valueBoolean value="false" />
|
||||
</answer>
|
||||
</item>
|
||||
<item>
|
||||
<linkId value="enable-when" />
|
||||
<text value="enable when condition true" />
|
||||
<answer>
|
||||
<valueBoolean value="false" />
|
||||
</answer>
|
||||
</item>
|
||||
</QuestionnaireResponse>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<QuestionnaireResponse xmlns="http://hl7.org/fhir">
|
||||
<id value="questionnaireResponse-enableWhen-test" />
|
||||
<text>
|
||||
<status value="generated" />
|
||||
<div xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
|
||||
<p>enableWhen test response</p>
|
||||
</div>
|
||||
</text>
|
||||
<questionnaire value="http://hl7.org/fhir/us/hai/Questionnaire/questionnaire-enableWhenEx-test" />
|
||||
<status value="completed" />
|
||||
<item>
|
||||
<linkId value="condition" />
|
||||
<text value="condition" />
|
||||
<answer>
|
||||
<valueBoolean value="true" />
|
||||
</answer>
|
||||
</item>
|
||||
<item>
|
||||
<linkId value="enable-when" />
|
||||
<text value="enable when condition true" />
|
||||
<answer>
|
||||
<valueBoolean value="false" />
|
||||
</answer>
|
||||
</item>
|
||||
</QuestionnaireResponse>
|
Loading…
Reference in New Issue