tidy up and work on tests.

This commit is contained in:
Grahame Grieve 2019-05-15 13:26:14 +10:00
commit a67693bc4b
43 changed files with 2523 additions and 63 deletions

View File

@ -21868,7 +21868,7 @@ public class VersionConvertor_30_40 {
public static boolean convertsResource(String rt) {
return Utilities.existsInList(rt, "Parameters", "ActivityDefinition", "AllergyIntolerance", "Appointment", "AppointmentResponse", "AuditEvent", "Basic", "Binary", "BodyStructure", "Bundle", "CapabilityStatement",
"CareTeam", "ClinicalImpression", "CodeSystem", "Communication", "CompartmentDefinition", "Composition", "ConceptMap", "Condition", "Consent", "DetectedIssue", "DeviceUseStatement", "DiagnosticReport", "DocumentReference",
"Encounter", "Endpoint", "EpisodeOfCare", "FamilyMemberHistory", "Flag", "Goal", "GraphDefinition", "Group", "HealthcareService", "Immunization", "ImplementationGuide", "Library", "Linkage", "ListResource", "Location",
"Encounter", "Endpoint", "EpisodeOfCare", "FamilyMemberHistory", "Flag", "Goal", "GraphDefinition", "Group", "HealthcareService", "ImagingStudy", "Immunization", "ImplementationGuide", "Library", "Linkage", "ListResource", "Location",
"Medication", "MedicationAdministration", "MedicationDispense", "MedicationRequest", "MedicationStatement", "MessageDefinition", "MessageHeader", "NamingSystem", "Observation", "OperationDefinition", "OperationOutcome",
"Organization", "Patient", "PaymentNotice", "Person", "PlanDefinition", "Practitioner", "PractitionerRole", "ProcessRequest", "Questionnaire", "QuestionnaireResponse", "RiskAssessment", "Schedule", "SearchParameter",
"Sequence", "Slot", "Specimen", "StructureDefinition", "StructureMap", "Subscription", "Substance", "SupplyDelivery", "TestReport", "TestScript", "ValueSet");

View File

@ -11896,6 +11896,327 @@ public class VersionConvertor_30_50 {
return tgt;
}
private static final String URN_DICOM_UID = "urn:dicom:uid";
public static org.hl7.fhir.r5.model.ImagingStudy convertImagingStudy(org.hl7.fhir.dstu3.model.ImagingStudy src) throws FHIRException {
if (src == null)
return null;
org.hl7.fhir.r5.model.ImagingStudy tgt = new org.hl7.fhir.r5.model.ImagingStudy();
copyDomainResource(src, tgt);
if (src.hasUid()) {
org.hl7.fhir.r5.model.Identifier i = new org.hl7.fhir.r5.model.Identifier();
i.setSystem(URN_DICOM_UID);
i.setValue(src.getUid());
tgt.addIdentifier(i);
}
for (org.hl7.fhir.dstu3.model.Identifier t : src.getIdentifier()) {
tgt.addIdentifier(convertIdentifier(t));
}
if (src.hasAccession())
tgt.addIdentifier(convertIdentifier(src.getAccession()));
if (src.hasAvailability()) {
org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability availability = src.getAvailability();
switch (availability) {
case OFFLINE:
tgt.setStatus(org.hl7.fhir.r5.model.ImagingStudy.ImagingStudyStatus.REGISTERED);
break;
case UNAVAILABLE:
tgt.setStatus(org.hl7.fhir.r5.model.ImagingStudy.ImagingStudyStatus.CANCELLED);
break;
case ONLINE:
case NEARLINE:
tgt.setStatus(org.hl7.fhir.r5.model.ImagingStudy.ImagingStudyStatus.AVAILABLE);
break;
default:
break;
}
} else {
tgt.setStatus(org.hl7.fhir.r5.model.ImagingStudy.ImagingStudyStatus.UNKNOWN);
}
for (org.hl7.fhir.dstu3.model.Coding t : src.getModalityList()) {
tgt.addModality(convertCoding(t));
}
if (src.hasPatient())
tgt.setSubject(convertReference(src.getPatient()));
if (src.hasContext()) {
tgt.setEncounter(convertReference(src.getContext()));
}
if (src.hasStarted()) {
tgt.setStartedElement(convertDateTime(src.getStartedElement()));
}
for (org.hl7.fhir.dstu3.model.Reference t : src.getBasedOn()) {
tgt.addBasedOn(convertReference(t));
}
if (src.hasReferrer()) {
tgt.setReferrer(convertReference(src.getReferrer()));
}
for (org.hl7.fhir.dstu3.model.Reference t : src.getInterpreter()) {
tgt.addInterpreter(convertReference(t));
}
for (org.hl7.fhir.dstu3.model.Reference t : src.getEndpoint()) {
tgt.addEndpoint(convertReference(t));
}
if (src.hasNumberOfSeries()) {
tgt.setNumberOfSeries(src.getNumberOfSeries());
}
if (src.hasNumberOfInstances()) {
tgt.setNumberOfInstances(src.getNumberOfInstances());
}
List<org.hl7.fhir.dstu3.model.Reference> procedureReferences = src.getProcedureReference();
if (procedureReferences.size() > 0) {
tgt.setProcedureReference(convertReference(procedureReferences.get(0)));
if (procedureReferences.size() > 1) {
// TODO print a warning that only one procedure reference could be converted
}
}
for (org.hl7.fhir.dstu3.model.CodeableConcept t : src.getProcedureCode()) {
tgt.addProcedureCode(convertCodeableConcept(t));
}
if (src.hasReason()) {
tgt.addReasonCode(convertCodeableConcept(src.getReason()));
}
if (src.hasDescription()) {
tgt.setDescription(src.getDescription());
}
for (org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesComponent t : src.getSeries()) {
tgt.addSeries(convertImagingStudySeriesComponent(t));
}
return tgt;
}
public static org.hl7.fhir.dstu3.model.ImagingStudy convertImagingStudy(org.hl7.fhir.r5.model.ImagingStudy src) throws FHIRException {
if (src == null)
return null;
org.hl7.fhir.dstu3.model.ImagingStudy tgt = new org.hl7.fhir.dstu3.model.ImagingStudy();
copyDomainResource(src, tgt);
for (org.hl7.fhir.r5.model.Identifier t : src.getIdentifier()) {
// assuming that there is only one urn:dicom:uid identifier
if (URN_DICOM_UID.equals(t.getSystem())) {
tgt.setUid(t.getValue());
} else {
tgt.addIdentifier(convertIdentifier(t));
}
}
if (src.hasStatus()) {
org.hl7.fhir.r5.model.ImagingStudy.ImagingStudyStatus s = src.getStatus();
switch (s) {
case REGISTERED:
tgt.setAvailability(org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability.OFFLINE);
break;
case AVAILABLE:
tgt.setAvailability(org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability.ONLINE);
break;
case CANCELLED:
tgt.setAvailability(org.hl7.fhir.dstu3.model.ImagingStudy.InstanceAvailability.UNAVAILABLE);
break;
default:
break;
}
}
for (org.hl7.fhir.r5.model.Coding t : src.getModality()) {
tgt.addModalityList(convertCoding(t));
}
if (src.hasSubject()) {
tgt.setPatient(convertReference(src.getSubject()));
}
if (src.hasEncounter()) {
tgt.setContext(convertReference(src.getEncounter()));
}
if (src.hasStarted()) {
tgt.setStartedElement(convertDateTime(src.getStartedElement()));
}
for (org.hl7.fhir.r5.model.Reference t : src.getBasedOn()) {
tgt.addBasedOn(convertReference(t));
}
if (src.hasReferrer()) {
tgt.setReferrer(convertReference(src.getReferrer()));
}
for (org.hl7.fhir.r5.model.Reference t : src.getInterpreter()) {
tgt.addInterpreter(convertReference(t));
}
for (org.hl7.fhir.r5.model.Reference t : src.getEndpoint()) {
tgt.addEndpoint(convertReference(t));
}
if (src.hasNumberOfSeries()) {
tgt.setNumberOfSeries(src.getNumberOfSeries());
}
if (src.hasNumberOfInstances()) {
tgt.setNumberOfInstances(src.getNumberOfInstances());
}
if (src.hasProcedureReference()) {
tgt.addProcedureReference(convertReference(src.getProcedureReference()));
}
for (org.hl7.fhir.r5.model.CodeableConcept t : src.getProcedureCode()) {
tgt.addProcedureCode(convertCodeableConcept(t));
}
// location was added in R4 and does not exist in DSTU3
List<org.hl7.fhir.r5.model.CodeableConcept> reasonCodes = src.getReasonCode();
if (reasonCodes.size() > 0) {
tgt.setReason(convertCodeableConcept(reasonCodes.get(0)));
if (reasonCodes.size() > 1) {
// TODO print a warning that only one reason could be converted
}
}
// reasonReference was added in R4 and does not exist in DSTU3
// node was added in R4 and does not exist in DSTU3
if (src.hasDescription()) {
tgt.setDescription(src.getDescription());
}
for (org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesComponent t : src.getSeries()) {
tgt.addSeries(convertImagingStudySeriesComponent(t));
}
return tgt;
}
public static org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesComponent convertImagingStudySeriesComponent(org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesComponent src) throws FHIRException {
if (src == null)
return null;
org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesComponent tgt = new org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesComponent();
copyElement(src, tgt);
if (src.hasUid()) {
tgt.setUid(src.getUid());
}
if (src.hasNumber()) {
tgt.setNumber(src.getNumber());
}
if (src.hasModality()) {
tgt.setModality(convertCoding(src.getModality()));
}
if (src.hasDescription()) {
tgt.setDescription(src.getDescription());
}
if (src.hasNumberOfInstances()) {
tgt.setNumberOfInstances(src.getNumberOfInstances());
}
for (org.hl7.fhir.dstu3.model.Reference t : src.getEndpoint()) {
tgt.addEndpoint(convertReference(t));
}
if (src.hasBodySite()) {
tgt.setBodySite(convertCoding(src.getBodySite()));
}
if (src.hasLaterality()) {
tgt.setLaterality(convertCoding(src.getLaterality()));
}
// the specimen element was added in R4 and does not exist in DSTU3
if (src.hasStarted()) {
tgt.setStartedElement(convertDateTime(src.getStartedElement()));
}
for (org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesInstanceComponent t : src.getInstance()) {
tgt.addInstance(convertImagingStudySeriesInstanceComponent(t));
}
return tgt;
}
public static org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesComponent convertImagingStudySeriesComponent(org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesComponent src) throws FHIRException {
if (src == null)
return null;
org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesComponent tgt = new org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesComponent();
copyElement(src, tgt);
if (src.hasUid()) {
tgt.setUid(src.getUid());
}
if (src.hasNumber()) {
tgt.setNumber(src.getNumber());
}
if (src.hasModality()) {
tgt.setModality(convertCoding(src.getModality()));
}
if (src.hasDescription()) {
tgt.setDescription(src.getDescription());
}
if (src.hasNumberOfInstances()) {
tgt.setNumberOfInstances(src.getNumberOfInstances());
}
for (org.hl7.fhir.r5.model.Reference t : src.getEndpoint()) {
tgt.addEndpoint(convertReference(t));
}
if (src.hasBodySite()) {
tgt.setBodySite(convertCoding(src.getBodySite()));
}
if (src.hasLaterality()) {
tgt.setLaterality(convertCoding(src.getLaterality()));
}
if (src.hasStarted()) {
tgt.setStartedElement(convertDateTime(src.getStartedElement()));
}
// the specimen element was added in R4 and does not exist in DSTU3
for (org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesInstanceComponent t : src.getInstance()) {
tgt.addInstance(convertImagingStudySeriesInstanceComponent(t));
}
return tgt;
}
private static final String URN_IETF_RFC_3986 = "urn:ietf:rfc:3986";
private static org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesInstanceComponent convertImagingStudySeriesInstanceComponent(org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesInstanceComponent src) throws FHIRException {
if (src == null)
return null;
org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesInstanceComponent tgt = new org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesInstanceComponent();
copyElement(src, tgt);
if (src.hasUid()) {
tgt.setUid(src.getUid());
}
if (src.hasSopClass()) {
org.hl7.fhir.r5.model.Coding c = new org.hl7.fhir.r5.model.Coding();
c.setSystem(URN_IETF_RFC_3986);
c.setCode(src.getSopClass());
tgt.setSopClass(c);
}
if (src.hasNumber()) {
tgt.setNumber(src.getNumber());
}
if (src.hasTitle()) {
tgt.setTitle(src.getTitle());
}
return tgt;
}
private static org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesInstanceComponent convertImagingStudySeriesInstanceComponent(org.hl7.fhir.r5.model.ImagingStudy.ImagingStudySeriesInstanceComponent src) throws FHIRException {
if (src == null)
return null;
org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesInstanceComponent tgt = new org.hl7.fhir.dstu3.model.ImagingStudy.ImagingStudySeriesInstanceComponent();
copyElement(src, tgt);
if (src.hasUid()) {
tgt.setUid(src.getUid());
}
org.hl7.fhir.r5.model.Coding sop = src.getSopClass();
if (URN_IETF_RFC_3986.equals(sop.getSystem())) {
tgt.setSopClass(sop.getCode());
}
if (src.hasNumber()) {
tgt.setNumber(src.getNumber());
}
if (src.hasTitle()) {
tgt.setTitle(src.getTitle());
}
return tgt;
}
public static org.hl7.fhir.r5.model.Immunization convertImmunization(org.hl7.fhir.dstu3.model.Immunization src) throws FHIRException {
if (src == null)
return null;
@ -21286,6 +21607,8 @@ public class VersionConvertor_30_50 {
return convertGroup((org.hl7.fhir.dstu3.model.Group) src);
if (src instanceof org.hl7.fhir.dstu3.model.HealthcareService)
return convertHealthcareService((org.hl7.fhir.dstu3.model.HealthcareService) src);
if (src instanceof org.hl7.fhir.dstu3.model.ImagingStudy)
return convertImagingStudy((org.hl7.fhir.dstu3.model.ImagingStudy)src);
if (src instanceof org.hl7.fhir.dstu3.model.Immunization)
return convertImmunization((org.hl7.fhir.dstu3.model.Immunization) src);
if (src instanceof org.hl7.fhir.dstu3.model.ImplementationGuide)
@ -21463,6 +21786,8 @@ public class VersionConvertor_30_50 {
return convertGroup((org.hl7.fhir.r5.model.Group) src);
if (src instanceof org.hl7.fhir.r5.model.HealthcareService)
return convertHealthcareService((org.hl7.fhir.r5.model.HealthcareService) src);
if (src instanceof org.hl7.fhir.r5.model.ImagingStudy)
return convertImagingStudy((org.hl7.fhir.r5.model.ImagingStudy)src);
if (src instanceof org.hl7.fhir.r5.model.Immunization)
return convertImmunization((org.hl7.fhir.r5.model.Immunization) src);
if (src instanceof org.hl7.fhir.r5.model.ImplementationGuide)
@ -21567,7 +21892,7 @@ public class VersionConvertor_30_50 {
public static boolean convertsResource(String rt) {
return Utilities.existsInList(rt, "Parameters", "ActivityDefinition", "AllergyIntolerance", "Appointment", "AppointmentResponse", "AuditEvent", "Basic", "Binary", "BodyStructure", "Bundle", "CapabilityStatement",
"CareTeam", "ClinicalImpression", "CodeSystem", "Communication", "CompartmentDefinition", "Composition", "ConceptMap", "Condition", "Consent", "DetectedIssue", "DeviceUseStatement", "DiagnosticReport", "DocumentReference",
"Encounter", "Endpoint", "EpisodeOfCare", "FamilyMemberHistory", "Flag", "Goal", "GraphDefinition", "Group", "HealthcareService", "Immunization", "ImplementationGuide", "Library", "Linkage", "ListResource", "Location",
"Encounter", "Endpoint", "EpisodeOfCare", "FamilyMemberHistory", "Flag", "Goal", "GraphDefinition", "Group", "HealthcareService", "ImagingStudy", "Immunization", "ImplementationGuide", "Library", "Linkage", "ListResource", "Location",
"Medication", "MedicationAdministration", "MedicationDispense", "MedicationRequest", "MedicationStatement", "MessageDefinition", "MessageHeader", "NamingSystem", "Observation", "OperationDefinition", "OperationOutcome",
"Organization", "Patient", "PaymentNotice", "Person", "PlanDefinition", "Practitioner", "PractitionerRole", "ProcessRequest", "Questionnaire", "QuestionnaireResponse", "RiskAssessment", "Schedule", "SearchParameter",
"Sequence", "Slot", "Specimen", "StructureDefinition", "StructureMap", "Subscription", "Substance", "SupplyDelivery", "TestReport", "TestScript", "ValueSet");

View File

@ -34,11 +34,6 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.NotImplementedException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.r4.conformance.ProfileUtilities;
import org.hl7.fhir.r4.conformance.ProfileUtilities.ProfileKnowledgeProvider;
import org.hl7.fhir.r4.context.IWorkerContext;
@ -91,10 +86,10 @@ import org.hl7.fhir.r4.model.StructureMap.StructureMapGroupRuleTargetComponent;
import org.hl7.fhir.r4.model.StructureMap.StructureMapGroupRuleTargetParameterComponent;
import org.hl7.fhir.r4.model.StructureMap.StructureMapGroupTypeMode;
import org.hl7.fhir.r4.model.StructureMap.StructureMapInputMode;
import org.hl7.fhir.r4.model.StructureMap.StructureMapModelMode;
import org.hl7.fhir.r4.model.StructureMap.StructureMapSourceListMode;
import org.hl7.fhir.r4.model.StructureMap.StructureMapStructureComponent;
import org.hl7.fhir.r4.model.StructureMap.StructureMapTargetListMode;
import org.hl7.fhir.r4.model.StructureMap.StructureMapModelMode;
import org.hl7.fhir.r4.model.StructureMap.StructureMapStructureComponent;
import org.hl7.fhir.r4.model.StructureMap.StructureMapTransform;
import org.hl7.fhir.r4.model.Type;
import org.hl7.fhir.r4.model.TypeDetails;
@ -105,6 +100,11 @@ import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r4.utils.FHIRLexer.FHIRLexerException;
import org.hl7.fhir.r4.utils.FHIRPathEngine.IEvaluationContext;
import org.apache.commons.lang3.NotImplementedException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.PathEngineException;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
@ -1170,11 +1170,13 @@ public class StructureMapUtilities {
target.addListMode(StructureMapTargetListMode.SHARE);
lexer.next();
target.setListRuleId(lexer.take());
} else if (lexer.getCurrent().equals("first"))
target.addListMode(StructureMapTargetListMode.FIRST);
else
target.addListMode(StructureMapTargetListMode.LAST);
lexer.next();
} else {
if (lexer.getCurrent().equals("first"))
target.addListMode(StructureMapTargetListMode.FIRST);
else
target.addListMode(StructureMapTargetListMode.LAST);
lexer.next();
}
}
}
@ -1219,7 +1221,7 @@ public class StructureMapUtilities {
}
public enum VariableMode {
INPUT, OUTPUT
INPUT, OUTPUT, SHARED
}
public class Variable {
@ -1277,16 +1279,25 @@ public class StructureMapUtilities {
return null;
}
public String summary() {
CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder();
CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder();
for (Variable v : list)
if (v.mode == VariableMode.INPUT)
s.append(v.summary());
else
t.append(v.summary());
return "source variables ["+s.toString()+"], target variables ["+t.toString()+"]";
}
public String summary() {
CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder();
CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder();
CommaSeparatedStringBuilder sh = new CommaSeparatedStringBuilder();
for (Variable v : list)
switch(v.mode) {
case INPUT:
s.append(v.summary());
break;
case OUTPUT:
t.append(v.summary());
break;
case SHARED:
sh.append(v.summary());
break;
}
return "source variables ["+s.toString()+"], target variables ["+t.toString()+"], shared variables ["+sh.toString()+"]";
}
}
public class TransformContext {
@ -1379,7 +1390,7 @@ public class StructureMapUtilities {
if (source != null) {
for (Variables v : source) {
for (StructureMapGroupRuleTargetComponent t : rule.getTarget()) {
processTarget(rule.getName(), context, v, map, group, t, rule.getSource().size() == 1 ? rule.getSourceFirstRep().getVariable() : null, atRoot);
processTarget(rule.getName(), context, v, map, group, t, rule.getSource().size() == 1 ? rule.getSourceFirstRep().getVariable() : null, atRoot, vars);
}
if (rule.hasRule()) {
for (StructureMapGroupRuleComponent childrule : rule.getRule()) {
@ -1781,7 +1792,7 @@ public class StructureMapUtilities {
return false;
}
private void processTarget(String ruleId, TransformContext context, Variables vars, StructureMap map, StructureMapGroupComponent group, StructureMapGroupRuleTargetComponent tgt, String srcVar, boolean atRoot) throws FHIRException {
private void processTarget(String ruleId, TransformContext context, Variables vars, StructureMap map, StructureMapGroupComponent group, StructureMapGroupRuleTargetComponent tgt, String srcVar, boolean atRoot, Variables sharedVars) throws FHIRException {
Base dest = null;
if (tgt.hasContext()) {
dest = vars.get(VariableMode.OUTPUT, tgt.getContext());
@ -1795,8 +1806,17 @@ public class StructureMapUtilities {
v = runTransform(ruleId, context, map, group, tgt, vars, dest, tgt.getElement(), srcVar, atRoot);
if (v != null && dest != null)
v = dest.setProperty(tgt.getElement().hashCode(), tgt.getElement(), v); // reset v because some implementations may have to rewrite v when setting the value
} else if (dest != null)
v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
} else if (dest != null) {
if (tgt.hasListMode(StructureMapTargetListMode.SHARE)) {
v = sharedVars.get(VariableMode.SHARED, tgt.getListRuleId());
if (v == null) {
v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
sharedVars.add(VariableMode.SHARED, tgt.getListRuleId(), v);
}
} else {
v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
}
}
if (tgt.hasVariable() && v != null)
vars.add(VariableMode.OUTPUT, tgt.getVariable(), v);
}

View File

@ -0,0 +1 @@
*.out

View File

@ -0,0 +1,6 @@
<fml-tests>
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" source="qr.json" map="qr2pat-assignment.map" output="qr2pat-assignment-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" source="qr.json" map="qr2pat-gender.map" output="qr2pat-gender-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" source="qr.json" map="qr2pat-humannametwice.map" output="qr2pat-humannametwice-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" source="qr.json" map="qr2pat-humannameshared.map" output="qr2pat-humannameshared-res.json" />
</fml-tests>

View File

@ -0,0 +1,39 @@
{
"resourceType": "QuestionnaireResponse",
"status": "in-progress",
"item": [
{
"linkId": "patient",
"text": "Patient",
"item": [
{
"linkId": "patient.lastname",
"text": "Name",
"answer": [
{
"valueString": "Brönnimann-Bertholet"
}
]
},
{
"linkId": "patient.firstname",
"text": "Vorname",
"answer": [
{
"valueString": "Elisabeth"
}
]
},
{
"linkId": "patient.sex",
"text": "Geschlecht",
"answer": [
{
"valueString": "female"
}
]
}
]
}
]
}

View File

@ -0,0 +1,4 @@
{
"resourceType" : "Patient",
"gender" : "female"
}

View File

@ -0,0 +1,8 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" = "qr2patassignment"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
src -> tgt.gender = 'female' "Simple Assignment";
}

View File

@ -0,0 +1,4 @@
{
"resourceType" : "Patient",
"gender" : "female"
}

View File

@ -0,0 +1,12 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" = "qr2patgender"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item -> tgt as patient then item(item, patient);
}
group item(source src, target tgt: Patient) {
src.item as item where linkId.value in ('patient.sex') -> tgt.gender = (item.answer.valueString);
}

View File

@ -0,0 +1,8 @@
{
"resourceType" : "Patient",
"name" : [{
"family" : "Brönnimann-Bertholet",
"given" : ["Elisabeth"]
}],
"gender" : "female"
}

View File

@ -0,0 +1,26 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" = "qr2pathumannametwice"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group entry(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item then item(item, tgt);
}
group item(source src, target tgt) {
src.item as item then item(item, tgt);
src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name share patientName then humanNameFamily(item, name);
src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name share patientName then humanNameGiven(item, name);
src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
}
group humanNameFamily(source src, target tgt: HumanName) {
src.answer as answer -> tgt.family = (answer.valueString);
}
group humanNameGiven(source src, target tgt: HumanName) {
src.answer as answer -> tgt.given = (answer.valueString);
}
group administrativeGender(source src, target tgt: code) {
src.answer as answer -> tgt = (answer.valueString);
}

View File

@ -0,0 +1,10 @@
{
"resourceType" : "Patient",
"name" : [{
"family" : "Brönnimann-Bertholet"
},
{
"given" : ["Elisabeth"]
}],
"gender" : "female"
}

View File

@ -0,0 +1,26 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" = "qr2pathumannametwice"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group entry(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item then item(item, tgt);
}
group item(source src, target tgt) {
src.item as item then item(item, tgt);
src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name then humanNameFamily(item, name);
src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name then humanNameGiven(item, name);
src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
}
group humanNameFamily(source src, target tgt: HumanName) {
src.answer as answer -> tgt.family = (answer.valueString);
}
group humanNameGiven(source src, target tgt: HumanName) {
src.answer as answer -> tgt.given = (answer.valueString);
}
group administrativeGender(source src, target tgt: code) {
src.answer as answer -> tgt = (answer.valueString);
}

View File

@ -18,7 +18,8 @@ import org.junit.runners.Suite.SuiteClasses;
NarrativeGeneratorTests.class,
ShexGeneratorTests.class,
BaseDateTimeTypeTest.class,
SnapShotGenerationTests.class})
SnapShotGenerationTests.class,
FHIRMappingLanguageTests.class})
public class AllTests {
}

View File

@ -0,0 +1,167 @@
package org.hl7.fhir.r4.test;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.context.SimpleWorkerContext;
import org.hl7.fhir.r4.elementmodel.Manager;
import org.hl7.fhir.r4.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
import org.hl7.fhir.r4.formats.JsonParser;
import org.hl7.fhir.r4.model.Base;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.ResourceFactory;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r4.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r4.model.StructureMap;
import org.hl7.fhir.r4.terminologies.ConceptMapEngine;
import org.hl7.fhir.r4.test.utils.TestingUtilities;
import org.hl7.fhir.r4.utils.StructureMapUtilities;
import org.hl7.fhir.r4.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
@RunWith(Parameterized.class)
public class FHIRMappingLanguageTests implements ITransformerServices {
private List<Resource> outputs = new ArrayList<Resource>();
static private SimpleWorkerContext context;
static private JsonParser jsonParser;
@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> data()
throws FileNotFoundException, IOException, ParserConfigurationException, SAXException {
Document tests = XMLUtil.parseFileToDom(TestingUtilities.resourceNameToFile("fml", "manifest.xml"));
Element test = XMLUtil.getFirstChild(tests.getDocumentElement());
List<Object[]> objects = new ArrayList<Object[]>();
while (test != null && test.getNodeName().equals("test")) {
objects.add(new Object[] { test.getAttribute("name"), test.getAttribute("source"), test.getAttribute("map"),
test.getAttribute("output") });
test = XMLUtil.getNextSibling(test);
}
return objects;
}
private final String name;
private String source;
private String output;
private String map;
public FHIRMappingLanguageTests(String name, String source, String map, String output) {
this.name = name;
this.source = source;
this.output = output;
this.map = map;
}
@BeforeClass
static public void setUp() throws Exception {
if (context == null) {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);
}
}
@Test
public void test() throws Exception {
String fileSource = TestingUtilities.resourceNameToFile("fml", source);
String fileMap = TestingUtilities.resourceNameToFile("fml", map);
String fileOutput = TestingUtilities.resourceNameToFile("fml", output);
String fileOutputRes = TestingUtilities.resourceNameToFile("fml", output)+".out";
outputs.clear();
boolean ok = false;
String msg = null;
Resource resource = null;
try {
StructureMapUtilities scu = new StructureMapUtilities(context, this);
org.hl7.fhir.r4.elementmodel.Element src = Manager.parse(context,
new ByteArrayInputStream(TextFile.fileToBytes(fileSource)), FhirFormat.JSON);
StructureMap structureMap = scu.parse(TextFile.fileToString(fileMap), name);
String typeName = scu.getTargetType(structureMap).getType();
resource = ResourceFactory.createResource(typeName);
scu.transform(null, src, structureMap, resource);
ok = true;
} catch (Exception e) {
ok = false;
msg = e.getMessage();
}
if (ok) {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
jsonParser.compose(boas, resource);
log(boas.toString());
TextFile.bytesToFile(boas.toByteArray(), fileOutputRes);
msg = TestingUtilities.checkJsonIsSame(fileOutputRes,fileOutput);
assertTrue(msg, Utilities.noString(msg));
} else
assertTrue("Error, but proper output was expected (" + msg + ")", output.equals("$error"));
}
@Override
public void log(String message) {
System.out.println(message);
}
@Override
public Base createType(Object appInfo, String name) throws FHIRException {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, name);
if (sd != null && sd.getKind() == StructureDefinitionKind.LOGICAL) {
return Manager.build(context, sd);
} else {
if (name.startsWith("http://hl7.org/fhir/StructureDefinition/"))
name = name.substring("http://hl7.org/fhir/StructureDefinition/".length());
return ResourceFactory.createResourceOrType(name);
}
}
@Override
public Base createResource(Object appInfo, Base res, boolean atRootofTransform) {
if (atRootofTransform)
outputs.add((Resource) res);
return res;
}
@Override
public Coding translate(Object appInfo, Coding source, String conceptMapUrl) throws FHIRException {
ConceptMapEngine cme = new ConceptMapEngine(context);
return cme.translate(source, conceptMapUrl);
}
@Override
public Base resolveReference(Object appContext, String url) throws FHIRException {
throw new FHIRException("resolveReference is not supported yet");
}
@Override
public List<Base> performSearch(Object appContext, String url) throws FHIRException {
throw new FHIRException("performSearch is not supported yet");
}
}

View File

@ -1170,11 +1170,13 @@ public class StructureMapUtilities {
target.addListMode(StructureMapTargetListMode.SHARE);
lexer.next();
target.setListRuleId(lexer.take());
} else if (lexer.getCurrent().equals("first"))
target.addListMode(StructureMapTargetListMode.FIRST);
else
target.addListMode(StructureMapTargetListMode.LAST);
lexer.next();
} else {
if (lexer.getCurrent().equals("first"))
target.addListMode(StructureMapTargetListMode.FIRST);
else
target.addListMode(StructureMapTargetListMode.LAST);
lexer.next();
}
}
}
@ -1219,7 +1221,7 @@ public class StructureMapUtilities {
}
public enum VariableMode {
INPUT, OUTPUT
INPUT, OUTPUT, SHARED
}
public class Variable {
@ -1277,16 +1279,25 @@ public class StructureMapUtilities {
return null;
}
public String summary() {
CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder();
CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder();
for (Variable v : list)
if (v.mode == VariableMode.INPUT)
s.append(v.summary());
else
t.append(v.summary());
return "source variables ["+s.toString()+"], target variables ["+t.toString()+"]";
}
public String summary() {
CommaSeparatedStringBuilder s = new CommaSeparatedStringBuilder();
CommaSeparatedStringBuilder t = new CommaSeparatedStringBuilder();
CommaSeparatedStringBuilder sh = new CommaSeparatedStringBuilder();
for (Variable v : list)
switch(v.mode) {
case INPUT:
s.append(v.summary());
break;
case OUTPUT:
t.append(v.summary());
break;
case SHARED:
sh.append(v.summary());
break;
}
return "source variables ["+s.toString()+"], target variables ["+t.toString()+"], shared variables ["+sh.toString()+"]";
}
}
public class TransformContext {
@ -1379,7 +1390,7 @@ public class StructureMapUtilities {
if (source != null) {
for (Variables v : source) {
for (StructureMapGroupRuleTargetComponent t : rule.getTarget()) {
processTarget(rule.getName(), context, v, map, group, t, rule.getSource().size() == 1 ? rule.getSourceFirstRep().getVariable() : null, atRoot);
processTarget(rule.getName(), context, v, map, group, t, rule.getSource().size() == 1 ? rule.getSourceFirstRep().getVariable() : null, atRoot, vars);
}
if (rule.hasRule()) {
for (StructureMapGroupRuleComponent childrule : rule.getRule()) {
@ -1781,7 +1792,7 @@ public class StructureMapUtilities {
return false;
}
private void processTarget(String ruleId, TransformContext context, Variables vars, StructureMap map, StructureMapGroupComponent group, StructureMapGroupRuleTargetComponent tgt, String srcVar, boolean atRoot) throws FHIRException {
private void processTarget(String ruleId, TransformContext context, Variables vars, StructureMap map, StructureMapGroupComponent group, StructureMapGroupRuleTargetComponent tgt, String srcVar, boolean atRoot, Variables sharedVars) throws FHIRException {
Base dest = null;
if (tgt.hasContext()) {
dest = vars.get(VariableMode.OUTPUT, tgt.getContext());
@ -1795,8 +1806,17 @@ public class StructureMapUtilities {
v = runTransform(ruleId, context, map, group, tgt, vars, dest, tgt.getElement(), srcVar, atRoot);
if (v != null && dest != null)
v = dest.setProperty(tgt.getElement().hashCode(), tgt.getElement(), v); // reset v because some implementations may have to rewrite v when setting the value
} else if (dest != null)
v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
} else if (dest != null) {
if (tgt.hasListMode(StructureMapTargetListMode.SHARE)) {
v = sharedVars.get(VariableMode.SHARED, tgt.getListRuleId());
if (v == null) {
v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
sharedVars.add(VariableMode.SHARED, tgt.getListRuleId(), v);
}
} else {
v = dest.makeProperty(tgt.getElement().hashCode(), tgt.getElement());
}
}
if (tgt.hasVariable() && v != null)
vars.add(VariableMode.OUTPUT, tgt.getVariable(), v);
}

View File

@ -0,0 +1 @@
*.out

View File

@ -0,0 +1,6 @@
<fml-tests>
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" source="qr.json" map="qr2pat-assignment.map" output="qr2pat-assignment-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" source="qr.json" map="qr2pat-gender.map" output="qr2pat-gender-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" source="qr.json" map="qr2pat-humannametwice.map" output="qr2pat-humannametwice-res.json" />
<test name="http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" source="qr.json" map="qr2pat-humannameshared.map" output="qr2pat-humannameshared-res.json" />
</fml-tests>

View File

@ -0,0 +1,39 @@
{
"resourceType": "QuestionnaireResponse",
"status": "in-progress",
"item": [
{
"linkId": "patient",
"text": "Patient",
"item": [
{
"linkId": "patient.lastname",
"text": "Name",
"answer": [
{
"valueString": "Brönnimann-Bertholet"
}
]
},
{
"linkId": "patient.firstname",
"text": "Vorname",
"answer": [
{
"valueString": "Elisabeth"
}
]
},
{
"linkId": "patient.sex",
"text": "Geschlecht",
"answer": [
{
"valueString": "female"
}
]
}
]
}
]
}

View File

@ -0,0 +1,4 @@
{
"resourceType" : "Patient",
"gender" : "female"
}

View File

@ -0,0 +1,8 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patassignment" = "qr2patassignment"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
src -> tgt.gender = 'female' "Simple Assignment";
}

View File

@ -0,0 +1,4 @@
{
"resourceType" : "Patient",
"gender" : "female"
}

View File

@ -0,0 +1,12 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2patgender" = "qr2patgender"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group QuestionnaireResponse(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item -> tgt as patient then item(item, patient);
}
group item(source src, target tgt: Patient) {
src.item as item where linkId.value in ('patient.sex') -> tgt.gender = (item.answer.valueString);
}

View File

@ -0,0 +1,8 @@
{
"resourceType" : "Patient",
"name" : [{
"family" : "Brönnimann-Bertholet",
"given" : ["Elisabeth"]
}],
"gender" : "female"
}

View File

@ -0,0 +1,26 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannameshared" = "qr2pathumannametwice"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group entry(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item then item(item, tgt);
}
group item(source src, target tgt) {
src.item as item then item(item, tgt);
src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name share patientName then humanNameFamily(item, name);
src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name share patientName then humanNameGiven(item, name);
src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
}
group humanNameFamily(source src, target tgt: HumanName) {
src.answer as answer -> tgt.family = (answer.valueString);
}
group humanNameGiven(source src, target tgt: HumanName) {
src.answer as answer -> tgt.given = (answer.valueString);
}
group administrativeGender(source src, target tgt: code) {
src.answer as answer -> tgt = (answer.valueString);
}

View File

@ -0,0 +1,10 @@
{
"resourceType" : "Patient",
"name" : [{
"family" : "Brönnimann-Bertholet"
},
{
"given" : ["Elisabeth"]
}],
"gender" : "female"
}

View File

@ -0,0 +1,26 @@
map "http://github.com/hapifhir/org.hl7.fhir.core/org.hl7.fhir.r4.tests/qr2pathumannametwice" = "qr2pathumannametwice"
uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse" alias QuestionnaireResponse as source
uses "http://hl7.org/fhir/StructureDefinition/Patient" alias Patient as target
group entry(source src : QuestionnaireResponse, target tgt : Patient) {
src.item as item then item(item, tgt);
}
group item(source src, target tgt) {
src.item as item then item(item, tgt);
src.item as item where linkId.value = 'patient.lastname' -> tgt.name as name then humanNameFamily(item, name);
src.item as item where linkId.value = 'patient.firstname' -> tgt.name as name then humanNameGiven(item, name);
src.item as item where linkId.value = 'patient.sex' -> tgt.gender = (item.answer.valueString);
}
group humanNameFamily(source src, target tgt: HumanName) {
src.answer as answer -> tgt.family = (answer.valueString);
}
group humanNameGiven(source src, target tgt: HumanName) {
src.answer as answer -> tgt.given = (answer.valueString);
}
group administrativeGender(source src, target tgt: code) {
src.answer as answer -> tgt = (answer.valueString);
}

View File

@ -19,6 +19,6 @@ import org.junit.runners.Suite.SuiteClasses;
ShexGeneratorTests.class,
BaseDateTimeTypeTest.class,
SnapShotGenerationTests.class})
public class AllTests {
public class AllR5Tests {
}

View File

@ -0,0 +1,167 @@
package org.hl7.fhir.r5.test;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.elementmodel.Manager;
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.ResourceFactory;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
import org.hl7.fhir.r5.model.StructureMap;
import org.hl7.fhir.r5.terminologies.ConceptMapEngine;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.StructureMapUtilities;
import org.hl7.fhir.r5.utils.StructureMapUtilities.ITransformerServices;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.cache.PackageCacheManager;
import org.hl7.fhir.utilities.cache.ToolsVersion;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
@RunWith(Parameterized.class)
public class FHIRMappingLanguageTests implements ITransformerServices {
private List<Resource> outputs = new ArrayList<Resource>();
static private SimpleWorkerContext context;
static private JsonParser jsonParser;
@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> data()
throws FileNotFoundException, IOException, ParserConfigurationException, SAXException {
Document tests = XMLUtil.parseFileToDom(TestingUtilities.resourceNameToFile("fml", "manifest.xml"));
Element test = XMLUtil.getFirstChild(tests.getDocumentElement());
List<Object[]> objects = new ArrayList<Object[]>();
while (test != null && test.getNodeName().equals("test")) {
objects.add(new Object[] { test.getAttribute("name"), test.getAttribute("source"), test.getAttribute("map"),
test.getAttribute("output") });
test = XMLUtil.getNextSibling(test);
}
return objects;
}
private final String name;
private String source;
private String output;
private String map;
public FHIRMappingLanguageTests(String name, String source, String map, String output) {
this.name = name;
this.source = source;
this.output = output;
this.map = map;
}
@BeforeClass
static public void setUp() throws Exception {
if (context == null) {
PackageCacheManager pcm = new PackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
context = SimpleWorkerContext.fromPackage(pcm.loadPackage("hl7.fhir.core", "4.0.0"));
jsonParser = new JsonParser();
jsonParser.setOutputStyle(OutputStyle.PRETTY);
}
}
@Test
public void test() throws Exception {
String fileSource = TestingUtilities.resourceNameToFile("fml", source);
String fileMap = TestingUtilities.resourceNameToFile("fml", map);
String fileOutput = TestingUtilities.resourceNameToFile("fml", output);
String fileOutputRes = TestingUtilities.resourceNameToFile("fml", output)+".out";
outputs.clear();
boolean ok = false;
String msg = null;
Resource resource = null;
try {
StructureMapUtilities scu = new StructureMapUtilities(context, this);
org.hl7.fhir.r5.elementmodel.Element src = Manager.parse(context,
new ByteArrayInputStream(TextFile.fileToBytes(fileSource)), FhirFormat.JSON);
StructureMap structureMap = scu.parse(TextFile.fileToString(fileMap), name);
String typeName = scu.getTargetType(structureMap).getType();
resource = ResourceFactory.createResource(typeName);
scu.transform(null, src, structureMap, resource);
ok = true;
} catch (Exception e) {
ok = false;
msg = e.getMessage();
}
if (ok) {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
jsonParser.compose(boas, resource);
log(boas.toString());
TextFile.bytesToFile(boas.toByteArray(), fileOutputRes);
msg = TestingUtilities.checkJsonIsSame(fileOutputRes,fileOutput);
assertTrue(msg, Utilities.noString(msg));
} else
assertTrue("Error, but proper output was expected (" + msg + ")", output.equals("$error"));
}
@Override
public void log(String message) {
System.out.println(message);
}
@Override
public Base createType(Object appInfo, String name) throws FHIRException {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, name);
if (sd != null && sd.getKind() == StructureDefinitionKind.LOGICAL) {
return Manager.build(context, sd);
} else {
if (name.startsWith("http://hl7.org/fhir/StructureDefinition/"))
name = name.substring("http://hl7.org/fhir/StructureDefinition/".length());
return ResourceFactory.createResourceOrType(name);
}
}
@Override
public Base createResource(Object appInfo, Base res, boolean atRootofTransform) {
if (atRootofTransform)
outputs.add((Resource) res);
return res;
}
@Override
public Coding translate(Object appInfo, Coding source, String conceptMapUrl) throws FHIRException {
ConceptMapEngine cme = new ConceptMapEngine(context);
return cme.translate(source, conceptMapUrl);
}
@Override
public Base resolveReference(Object appContext, String url) throws FHIRException {
throw new FHIRException("resolveReference is not supported yet");
}
@Override
public List<Base> performSearch(Object appContext, String url) throws FHIRException {
throw new FHIRException("performSearch is not supported yet");
}
}

View File

@ -57,6 +57,8 @@ public class ProfileUtilitiesTests {
else {
b.setBase(null);
f.setBase(null);
b.setRequirements(null);
f.setRequirements(null);
ok = Base.compareDeep(b, f, true);
}
}
@ -98,6 +100,12 @@ public class ProfileUtilitiesTests {
else {
f.setBase(null);
b.setBase(null);
b.setRequirements(null);
f.setRequirements(null);
b.setComment(null);
f.setComment(null);
b.setDefinition(null);
f.setDefinition(null);
ok = Base.compareDeep(b, f, true);
}
}

View File

@ -121,6 +121,7 @@ import org.hl7.fhir.r5.model.TypeDetails;
import org.hl7.fhir.r5.model.UriType;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException;
import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
@ -872,15 +873,55 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return true;
return false;
}
private void checkCodeableConcept(List<ValidationMessage> errors, String path, Element focus, CodeableConcept fixed) {
private boolean hasErrors(List<ValidationMessage> errors) {
if (errors!=null) {
for (ValidationMessage vm : errors) {
if (vm.getLevel() == IssueSeverity.FATAL || vm.getLevel() == IssueSeverity.ERROR) {
return true;
}
}
}
return false;
}
private void checkCodeableConcept(List<ValidationMessage> errors, String path, Element focus, CodeableConcept fixed,
boolean pattern) {
checkFixedValue(errors, path + ".text", focus.getNamedChild("text"), fixed.getTextElement(), "text", focus);
List<Element> codings = new ArrayList<Element>();
focus.getNamedChildren("coding", codings);
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, codings.size() == fixed.getCoding().size(),
"Expected " + Integer.toString(fixed.getCoding().size()) + " but found " + Integer.toString(codings.size()) + " coding elements")) {
for (int i = 0; i < codings.size(); i++)
checkFixedValue(errors, path + ".coding", codings.get(i), fixed.getCoding().get(i), "coding", focus);
if (pattern) {
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, codings.size() >= fixed.getCoding().size(),
"Expected " + Integer.toString(fixed.getCoding().size()) + " but found " + Integer.toString(codings.size())
+ " coding elements")) {
for (int i = 0; i < fixed.getCoding().size(); i++) {
Coding fixedCoding = fixed.getCoding().get(i);
boolean found = false;
List<ValidationMessage> errorsFixed = null;
for (int j = 0; j < codings.size() && !found; ++j) {
errorsFixed = new ArrayList<ValidationMessage>();
checkFixedValue(errorsFixed, path + ".coding", codings.get(j), fixedCoding, "coding", focus);
if (!hasErrors(errorsFixed)) {
found = true;
}
}
if (!found) {
rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, false,
"Expected patternCodeableConcept not found for"+
" system: " + fixedCoding.getSystemElement().asStringValue() +
" code: " + fixedCoding.getCodeElement().asStringValue() +
" display: " + fixedCoding.getDisplayElement().asStringValue());
}
}
}
} else {
if (rule(errors, IssueType.VALUE, focus.line(), focus.col(), path, codings.size() == fixed.getCoding().size(),
"Expected " + Integer.toString(fixed.getCoding().size()) + " but found " + Integer.toString(codings.size())
+ " coding elements")) {
for (int i = 0; i < codings.size(); i++)
checkFixedValue(errors, path + ".coding", codings.get(i), fixed.getCoding().get(i), "coding", focus);
}
}
}
@ -1292,8 +1333,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// return b.toString();
// }
//
private void checkFixedValue(List<ValidationMessage> errors, String path, Element focus, org.hl7.fhir.r5.model.Element fixed, String propName, Element parent) {
checkFixedValue(errors, path, focus, fixed, propName, parent, false);
}
private void checkFixedValue(List<ValidationMessage> errors, String path, Element focus, org.hl7.fhir.r5.model.Element fixed, String propName, Element parent, boolean pattern) {
if ((fixed == null || fixed.isEmpty()) && focus == null)
; // this is all good
else if (fixed == null && focus != null)
@ -1356,7 +1401,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
else if (fixed instanceof HumanName)
checkHumanName(errors, path, focus, (HumanName) fixed);
else if (fixed instanceof CodeableConcept)
checkCodeableConcept(errors, path, focus, (CodeableConcept) fixed);
checkCodeableConcept(errors, path, focus, (CodeableConcept) fixed, pattern);
else if (fixed instanceof Timing)
checkTiming(errors, path, focus, (Timing) fixed);
else if (fixed instanceof Period)
@ -1622,8 +1667,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
if (context.hasFixed())
checkFixedValue(errors,path,e, context.getFixed(), context.getSliceName(), null);
if (context.hasFixed()) {
checkFixedValue(errors,path,e, context.getFixed(), context.getSliceName(), null, false);
}
if (context.hasPattern()) {
checkFixedValue(errors, path, e, context.getPattern(), context.getSliceName(), null, true);
}
// for nothing to check
}
@ -3823,6 +3872,9 @@ private boolean isAnswerRequirementFulfilled(QuestionnaireItemComponent qItem, L
if (ei.definition.hasFixed()) {
checkFixedValue(errors,ei.path, ei.element, ei.definition.getFixed(), ei.definition.getSliceName(), null);
}
if (ei.definition.hasPattern()) {
checkFixedValue(errors,ei.path, ei.element, ei.definition.getPattern(), ei.definition.getSliceName(), null, true);
}
}
if (type.equals("Identifier")) {
checkIdentifier(errors, ei.path, ei.element, ei.definition);

View File

@ -10,6 +10,6 @@ import org.junit.runners.Suite.SuiteClasses;
ValidationEngineTests.class,
JsonSchemaTests.class,
CDAValidationTestCase.class})
public class AllTests {
public class AllR5ValidationTests {
}

View File

@ -467,7 +467,40 @@
"source" : "extension-slice-profile.xml",
"errorCount": 0
}
},
"slice-by-polymorphic-type2.xml" : {
"errorCount": 0,
"profile" : {
"source" : "slice-by-polymorphic-type2-profile.xml",
"errorCount": 0
}
},
"observation-bp-validationfails.xml" : {
"errorCount": 4,
"errors": [
"ERROR: Observation.component[1]: Error in discriminator at Observation.component:SystolicBP.code.coding: slicing found",
"ERROR: Observation.component[2]: Error in discriminator at Observation.component:SystolicBP.code.coding: slicing found",
"ERROR: Observation.component[1]: Error in discriminator at Observation.component:DiastolicBP.code.coding: slicing found",
"ERROR: Observation.component[2]: Error in discriminator at Observation.component:DiastolicBP.code.coding: slicing found"
]
},
"observation-bp.xml" : {
"errorCount": 0,
"profile" : {
"source" : "observation-bp-profile.xml",
"errorCount": 0
}
},
"observation-bp-bad-onlydiastolic.xml" : {
"errorCount": 0,
"profile" : {
"source" : "observation-bp-profile.xml",
"errorCount": 1,
"errors": [
"ERROR: Observation: Profile http://hl7.org/fhir/StructureDefinition/observation-bp-profile, Element 'Observation.component[SystolicBP]': minimum required = 1, but only found 0"
]
}
},
"observation-cholesterol-good.xml" : {
"errorCount": 0
},
@ -489,7 +522,21 @@
"source" : "invariant.profile.xml",
"errorCount": 1
}
},
"observation-triglyceride-good.xml" : {
"warningCount": 1,
"errorCount": 0,
"warnings": ["WARNING: Observation.code.coding[1]: The display \"Triglyceride [Moles/volume] in Serum or Plasma\" is not a valid display for the code {http://loinc.org}35217-9 - should be one of [\"Triglyceride [Mass or Moles/volume] in Serum or Plasma\",\"Trigl SerPl-msCnc\""]
},
"observation-triglyceride-good2.xml" : {
"warningCount": 1,
"errorCount": 0,
"warnings": ["WARNING: Observation.code.coding[2]: The display \"Triglyceride [Moles/volume] in Serum or Plasma\" is not a valid display for the code {http://loinc.org}35217-9 - should be one of [\"Triglyceride [Mass or Moles/volume] in Serum or Plasma\",\"Trigl SerPl-msCnc\""]
},
"observation-triglyceride-bad-wrongcode.xml" : {
"errorCount": 1,
"errors": ["ERROR: Observation.code: Expected patternCodeableConcept not found for system: http://loinc.org code: 35217-9 display: Triglyceride [Moles/volume] in Serum or Plasma"]
}
}
}
}
}

View File

@ -0,0 +1,250 @@
<Observation xmlns="http://hl7.org/fhir">
<!-- extract from https://www.hl7.org/fhir/observation-example-bloodpressure.xml,
changed id from blood-pressure to observation-bp and removed systolic loinc coide that observation fails -->
<id value="observation-bp-bad-onlydiastolic" />
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b>Generated Narrative with Details</b>
</p>
<p>
<b>id</b>
: blood-pressure
</p>
<p>
<b>meta</b>
:
</p>
<p>
<b>identifier</b>
: urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281
</p>
<p>
<b>basedOn</b>
:
</p>
<p>
<b>status</b>
: final
</p>
<p>
<b>category</b>
: Vital Signs
<span>(Details :
{http://terminology.hl7.org/CodeSystem/observation-category code
&#39;vital-signs&#39; = &#39;Vital Signs&#39;, given as &#39;Vital
Signs&#39;})</span>
</p>
<p>
<b>code</b>:
Blood pressure systolic &amp; diastolic
<span>(Details : {LOINC code &#39;85354-9&#39; = &#39;Blood pressure
panel with all children optional&#39;, given as &#39;Blood pressure
panel with all children optional&#39;})</span>
</p>
<p>
<b>subject</b>
:
<a>Patient/example</a>
</p>
<p>
<b>effective</b>
: 17/09/2012
</p>
<p>
<b>performer</b>
:
<a>Practitioner/example</a>
</p>
<p>
<b>interpretation</b>
: Below low normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;L&#39; = &#39;Low&#39;, given as &#39;low&#39;})</span>
</p>
<p>
<b>bodySite</b>
: Right arm
<span>(Details : {SNOMED CT code &#39;368209003&#39; = &#39;Right
upper arm&#39;, given as &#39;Right arm&#39;})</span>
</p>
<blockquote>
<p>
<b>component</b>
</p>
<p>
<b>code</b>
: Systolic blood pressure
<span>(Details : {LOINC code &#39;8480-6&#39; = &#39;Systolic blood
pressure&#39;, given as &#39;Systolic blood pressure&#39;};
{SNOMED CT code &#39;271649006&#39; = &#39;Systolic blood
pressure&#39;, given as &#39;Systolic blood pressure&#39;};
{http://acme.org/devices/clinical-codes code &#39;bp-s&#39; =
&#39;bp-s&#39;, given as &#39;Systolic Blood pressure&#39;})
</span>
</p>
<p>
<b>value</b>
: 107 mmHg
<span> (Details: UCUM code mm[Hg] = &#39;mmHg&#39;)</span>
</p>
<p>
<b>interpretation</b>
: Normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;N&#39; = &#39;Normal&#39;, given as &#39;normal&#39;})
</span>
</p>
</blockquote>
<blockquote>
<p>
<b>component</b>
</p>
<p>
<b>code</b>
: Diastolic blood pressure
<span>(Details : {LOINC code &#39;8462-4&#39; = &#39;Diastolic
blood pressure&#39;, given as &#39;Diastolic blood pressure&#39;})
</span>
</p>
<p>
<b>value</b>
: 60 mmHg
<span> (Details: UCUM code mm[Hg] = &#39;mmHg&#39;)</span>
</p>
<p>
<b>interpretation</b>
: Below low normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;L&#39; = &#39;Low&#39;, given as &#39;low&#39;})</span>
</p>
</blockquote>
</div>
</text>
<identifier>
<system value="urn:ietf:rfc:3986" />
<value value="urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281" />
</identifier><!-- demonstrating the use of the baseOn element with a fictive
identifier -->
<basedOn>
<identifier>
<system value="https://acme.org/identifiers" />
<value value="1234" />
</identifier>
</basedOn>
<status value="final" />
<category>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/observation-category" />
<code value="vital-signs" />
<display value="Vital Signs" />
</coding>
</category>
<code><!-- replaced by 85354-9 <coding> <system value="http://loinc.org"/>
<code value="85354-9"/> <display value="Blood pressure systolic &amp; diastolic"/>
</coding> -->
<coding>
<system value="http://loinc.org" />
<code value="85354-9" />
<display
value="Blood pressure panel with all children optional" />
</coding>
<text value="Blood pressure systolic &amp; diastolic" />
</code>
<subject>
<reference value="Patient/example" />
</subject>
<effectiveDateTime value="2012-09-17" />
<performer>
<reference value="Practitioner/example" />
</performer><!-- an interpretation offered to the combination observation
generally, it would only be appropriate to offer an interpretation of an
observation that has no value if it has "COMP" (component) observations -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="L" />
<display value="low" />
</coding>
<text value="Below low normal" />
</interpretation><!-- The BodySite can be captured in a LOINC code but am
showing it here to demonstrate populating the element -->
<bodySite>
<coding>
<system value="http://snomed.info/sct" />
<code value="368209003" />
<display value="Right arm" />
</coding>
</bodySite>
<component><!-- Observations are often coded in multiple code systems. -
LOINC provides a very specific code (though not more specific in this particular
case) - snomed provides a clinically relevant code that is usually less granular
than LOINC - the source system provides its own code, which may be less or
more granular than LOINC this is shown here to demonstrate the concept of
translations within the codeableConcept datatype. The diastolic code below
only has a LOINC code -->
<code><!-- LOINC -code -->
<!-- removed systolic loinc coide that observation fails <coding>
<system value="http://loinc.org" />
<code value="8480-6" />
<display value="Systolic blood pressure" />
</coding>
--> <!-- SNOMED CT Codes -->
<coding>
<system value="http://snomed.info/sct" />
<code value="271649006" />
<display value="Systolic blood pressure" />
</coding><!-- Also, a local code specific to the source system -->
<coding>
<system value="http://acme.org/devices/clinical-codes" />
<code value="bp-s" />
<display value="Systolic Blood pressure" />
</coding>
</code>
<valueQuantity>
<value value="107" />
<unit value="mmHg" />
<system value="http://unitsofmeasure.org" />
<code value="mm[Hg]" />
</valueQuantity><!-- an interpretation for the individual composite observation -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="N" />
<display value="normal" />
</coding>
<text value="Normal" />
</interpretation><!-- Should have a refrange as well -->
</component>
<component><!-- this codes only has a LOINC code -->
<code>
<coding>
<system value="http://loinc.org" />
<code value="8462-4" />
<display value="Diastolic blood pressure" />
</coding>
</code>
<valueQuantity>
<value value="60" />
<unit value="mmHg" />
<system value="http://unitsofmeasure.org" />
<code value="mm[Hg]" />
</valueQuantity><!-- an interpretation for the individual composite observation -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="L" />
<display value="low" />
</coding>
<text value="Below low normal" />
</interpretation><!-- Should have a refrange as well -->
</component>
</Observation>

View File

@ -0,0 +1,243 @@
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="observation-bp-profile" />
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">reworked official bp profile to use patternCodeableConcept</div>
</text>
<url value="http://hl7.org/fhir/StructureDefinition/observation-bp-profile" />
<version value="4.0.0" />
<name value="observation-bp" />
<title value="Observation Blood Pressure Profile" />
<status value="draft" />
<experimental value="false" />
<date value="2019-05-06" />
<publisher
value="Health Level Seven International (Orders and Observations Workgroup)" />
<contact>
<telecom>
<system value="url" />
<value
value="http://www.hl7.org/Special/committees/orders/index.cfm Orders and Observations" />
</telecom>
</contact>
<description value="FHIR Blood Pressure Profile" />
<fhirVersion value="4.0.0" />
<mapping>
<identity value="workflow" />
<uri value="http://hl7.org/fhir/workflow" />
<name value="Workflow Pattern" />
</mapping>
<mapping>
<identity value="sct-concept" />
<uri value="http://snomed.info/conceptdomain" />
<name value="SNOMED CT Concept Domain Binding" />
</mapping>
<mapping>
<identity value="v2" />
<uri value="http://hl7.org/v2" />
<name value="HL7 v2 Mapping" />
</mapping>
<mapping>
<identity value="rim" />
<uri value="http://hl7.org/v3" />
<name value="RIM Mapping" />
</mapping>
<mapping>
<identity value="w5" />
<uri value="http://hl7.org/fhir/fivews" />
<name value="FiveWs Pattern Mapping" />
</mapping>
<mapping>
<identity value="sct-attr" />
<uri value="http://snomed.org/attributebinding" />
<name value="SNOMED CT Attribute Binding" />
</mapping>
<kind value="resource" />
<abstract value="false" />
<type value="Observation" />
<baseDefinition
value="http://hl7.org/fhir/StructureDefinition/vitalsigns" />
<derivation value="constraint" />
<differential>
<element id="Observation">
<path value="Observation" />
<short value="FHIR Blood Pressure Profile" />
<definition
value="This profile defines how to represent Blood Pressure observations in FHIR using a standard LOINC code and UCUM units of measure. This is a grouping structure. It has no value in Observation.valueQuantity but contains at least one component (systolic and/or diastolic)." />
<min value="0" />
<max value="*" />
</element>
<element id="Observation.code">
<path value="Observation.code" />
<short value="Blood Pressure" />
<definition value="Blood Pressure" />
<min value="1" />
<max value="1" />
<type>
<code value="CodeableConcept" />
</type>
<patternCodeableConcept>
<coding>
<system value="http://loinc.org" />
<code value="85354-9" />
</coding>
</patternCodeableConcept>
<mustSupport value="true" />
</element>
<element id="Observation.valueQuantity">
<path value="Observation.valueQuantity" />
<min value="0" />
<max value="0" />
</element>
<element id="Observation.component">
<path value="Observation.component" />
<slicing>
<discriminator>
<type value="pattern" />
<path value="code" />
</discriminator>
<rules value="open" />
</slicing>
<min value="2" />
<max value="*" />
</element>
<element id="Observation.component:SystolicBP">
<path value="Observation.component" />
<sliceName value="SystolicBP" />
<short value="SystolicBP" />
<min value="1" />
<max value="1" />
</element>
<element id="Observation.component:SystolicBP.code">
<path value="Observation.component.code" />
<min value="1" />
<patternCodeableConcept>
<coding>
<system value="http://loinc.org" />
<code value="8480-6" />
</coding>
</patternCodeableConcept>
</element>
<element id="Observation.component:SystolicBP.valueQuantity">
<path value="Observation.component.valueQuantity" />
<type>
<code value="Quantity" />
</type>
</element>
<element
id="Observation.component:SystolicBP.valueQuantity.value">
<path value="Observation.component.valueQuantity.value" />
<min value="1" />
<max value="1" />
<type>
<code value="decimal" />
</type>
<mustSupport value="true" />
</element>
<element
id="Observation.component:SystolicBP.valueQuantity.unit">
<path value="Observation.component.valueQuantity.unit" />
<min value="1" />
<max value="1" />
<type>
<code value="string" />
</type>
<mustSupport value="true" />
</element>
<element
id="Observation.component:SystolicBP.valueQuantity.system">
<path value="Observation.component.valueQuantity.system" />
<min value="1" />
<max value="1" />
<type>
<code value="uri" />
</type>
<fixedUri value="http://unitsofmeasure.org" />
<mustSupport value="true" />
</element>
<element
id="Observation.component:SystolicBP.valueQuantity.code">
<path value="Observation.component.valueQuantity.code" />
<short
value="Coded responses from the common UCUM units for vital signs value set." />
<definition
value="Coded responses from the common UCUM units for vital signs value set." />
<min value="1" />
<max value="1" />
<type>
<code value="code" />
</type>
<fixedCode value="mm[Hg]" />
<mustSupport value="true" />
</element>
<element id="Observation.component:DiastolicBP">
<path value="Observation.component" />
<sliceName value="DiastolicBP" />
<short value="DiastolicBP" />
<min value="1" />
<max value="1" />
</element>
<element id="Observation.component:DiastolicBP">
<path value="Observation.component.code" />
<min value="1" />
<patternCodeableConcept>
<coding>
<system value="http://loinc.org" />
<code value="8462-4" />
</coding>
</patternCodeableConcept>
</element>
<element id="Observation.component:DiastolicBP.valueQuantity">
<path value="Observation.component.valueQuantity" />
<type>
<code value="Quantity" />
</type>
</element>
<element
id="Observation.component:DiastolicBP.valueQuantity.value">
<path value="Observation.component.valueQuantity.value" />
<min value="1" />
<max value="1" />
<type>
<code value="decimal" />
</type>
<mustSupport value="true" />
</element>
<element
id="Observation.component:DiastolicBP.valueQuantity.unit">
<path value="Observation.component.valueQuantity.unit" />
<min value="1" />
<max value="1" />
<type>
<code value="string" />
</type>
<mustSupport value="true" />
</element>
<element
id="Observation.component:DiastolicBP.valueQuantity.system">
<path value="Observation.component.valueQuantity.system" />
<min value="1" />
<max value="1" />
<type>
<code value="uri" />
</type>
<fixedUri value="http://unitsofmeasure.org" />
<mustSupport value="true" />
</element>
<element
id="Observation.component:DiastolicBP.valueQuantity.code">
<path value="Observation.component.valueQuantity.code" />
<short
value="Coded responses from the common UCUM units for vital signs value set." />
<definition
value="Coded responses from the common UCUM units for vital signs value set." />
<min value="1" />
<max value="1" />
<type>
<code value="code" />
</type>
<fixedCode value="mm[Hg]" />
<mustSupport value="true" />
</element>
</differential>
</StructureDefinition>

View File

@ -0,0 +1,253 @@
<Observation xmlns="http://hl7.org/fhir">
<!-- extract from https://www.hl7.org/fhir/observation-example-bloodpressure.xml,
changed id from blood-pressure to observation-bp-validationfails and added explicit profile
reference to http://hl7.org/fhir/StructureDefinition/bp -->
<id value="observation-bp-validationfails" />
<meta>
<profile value="http://hl7.org/fhir/StructureDefinition/bp" />
</meta>
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b>Generated Narrative with Details</b>
</p>
<p>
<b>id</b>
: blood-pressure
</p>
<p>
<b>meta</b>
:
</p>
<p>
<b>identifier</b>
: urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281
</p>
<p>
<b>basedOn</b>
:
</p>
<p>
<b>status</b>
: final
</p>
<p>
<b>category</b>
: Vital Signs
<span>(Details :
{http://terminology.hl7.org/CodeSystem/observation-category code
&#39;vital-signs&#39; = &#39;Vital Signs&#39;, given as &#39;Vital
Signs&#39;})</span>
</p>
<p>
<b>code</b>:
Blood pressure systolic &amp; diastolic
<span>(Details : {LOINC code &#39;85354-9&#39; = &#39;Blood pressure
panel with all children optional&#39;, given as &#39;Blood pressure
panel with all children optional&#39;})</span>
</p>
<p>
<b>subject</b>
:
<a>Patient/example</a>
</p>
<p>
<b>effective</b>
: 17/09/2012
</p>
<p>
<b>performer</b>
:
<a>Practitioner/example</a>
</p>
<p>
<b>interpretation</b>
: Below low normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;L&#39; = &#39;Low&#39;, given as &#39;low&#39;})</span>
</p>
<p>
<b>bodySite</b>
: Right arm
<span>(Details : {SNOMED CT code &#39;368209003&#39; = &#39;Right
upper arm&#39;, given as &#39;Right arm&#39;})</span>
</p>
<blockquote>
<p>
<b>component</b>
</p>
<p>
<b>code</b>
: Systolic blood pressure
<span>(Details : {LOINC code &#39;8480-6&#39; = &#39;Systolic blood
pressure&#39;, given as &#39;Systolic blood pressure&#39;};
{SNOMED CT code &#39;271649006&#39; = &#39;Systolic blood
pressure&#39;, given as &#39;Systolic blood pressure&#39;};
{http://acme.org/devices/clinical-codes code &#39;bp-s&#39; =
&#39;bp-s&#39;, given as &#39;Systolic Blood pressure&#39;})
</span>
</p>
<p>
<b>value</b>
: 107 mmHg
<span> (Details: UCUM code mm[Hg] = &#39;mmHg&#39;)</span>
</p>
<p>
<b>interpretation</b>
: Normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;N&#39; = &#39;Normal&#39;, given as &#39;normal&#39;})
</span>
</p>
</blockquote>
<blockquote>
<p>
<b>component</b>
</p>
<p>
<b>code</b>
: Diastolic blood pressure
<span>(Details : {LOINC code &#39;8462-4&#39; = &#39;Diastolic
blood pressure&#39;, given as &#39;Diastolic blood pressure&#39;})
</span>
</p>
<p>
<b>value</b>
: 60 mmHg
<span> (Details: UCUM code mm[Hg] = &#39;mmHg&#39;)</span>
</p>
<p>
<b>interpretation</b>
: Below low normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;L&#39; = &#39;Low&#39;, given as &#39;low&#39;})</span>
</p>
</blockquote>
</div>
</text>
<identifier>
<system value="urn:ietf:rfc:3986" />
<value value="urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281" />
</identifier><!-- demonstrating the use of the baseOn element with a fictive
identifier -->
<basedOn>
<identifier>
<system value="https://acme.org/identifiers" />
<value value="1234" />
</identifier>
</basedOn>
<status value="final" />
<category>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/observation-category" />
<code value="vital-signs" />
<display value="Vital Signs" />
</coding>
</category>
<code><!-- replaced by 85354-9 <coding> <system value="http://loinc.org"/>
<code value="85354-9"/> <display value="Blood pressure systolic &amp; diastolic"/>
</coding> -->
<coding>
<system value="http://loinc.org" />
<code value="85354-9" />
<display
value="Blood pressure panel with all children optional" />
</coding>
<text value="Blood pressure systolic &amp; diastolic" />
</code>
<subject>
<reference value="Patient/example" />
</subject>
<effectiveDateTime value="2012-09-17" />
<performer>
<reference value="Practitioner/example" />
</performer><!-- an interpretation offered to the combination observation
generally, it would only be appropriate to offer an interpretation of an
observation that has no value if it has "COMP" (component) observations -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="L" />
<display value="low" />
</coding>
<text value="Below low normal" />
</interpretation><!-- The BodySite can be captured in a LOINC code but am
showing it here to demonstrate populating the element -->
<bodySite>
<coding>
<system value="http://snomed.info/sct" />
<code value="368209003" />
<display value="Right arm" />
</coding>
</bodySite>
<component><!-- Observations are often coded in multiple code systems. -
LOINC provides a very specific code (though not more specific in this particular
case) - snomed provides a clinically relevant code that is usually less granular
than LOINC - the source system provides its own code, which may be less or
more granular than LOINC this is shown here to demonstrate the concept of
translations within the codeableConcept datatype. The diastolic code below
only has a LOINC code -->
<code><!-- LOINC -code -->
<coding>
<system value="http://loinc.org" />
<code value="8480-6" />
<display value="Systolic blood pressure" />
</coding><!-- SNOMED CT Codes -->
<coding>
<system value="http://snomed.info/sct" />
<code value="271649006" />
<display value="Systolic blood pressure" />
</coding><!-- Also, a local code specific to the source system -->
<coding>
<system value="http://acme.org/devices/clinical-codes" />
<code value="bp-s" />
<display value="Systolic Blood pressure" />
</coding>
</code>
<valueQuantity>
<value value="107" />
<unit value="mmHg" />
<system value="http://unitsofmeasure.org" />
<code value="mm[Hg]" />
</valueQuantity><!-- an interpretation for the individual composite observation -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="N" />
<display value="normal" />
</coding>
<text value="Normal" />
</interpretation><!-- Should have a refrange as well -->
</component>
<component><!-- this codes only has a LOINC code -->
<code>
<coding>
<system value="http://loinc.org" />
<code value="8462-4" />
<display value="Diastolic blood pressure" />
</coding>
</code>
<valueQuantity>
<value value="60" />
<unit value="mmHg" />
<system value="http://unitsofmeasure.org" />
<code value="mm[Hg]" />
</valueQuantity><!-- an interpretation for the individual composite observation -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="L" />
<display value="low" />
</coding>
<text value="Below low normal" />
</interpretation><!-- Should have a refrange as well -->
</component>
</Observation>

View File

@ -0,0 +1,249 @@
<Observation xmlns="http://hl7.org/fhir">
<!-- extract from https://www.hl7.org/fhir/observation-example-bloodpressure.xml,
changed id from blood-pressure to observation-bp -->
<id value="observation-bp" />
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b>Generated Narrative with Details</b>
</p>
<p>
<b>id</b>
: blood-pressure
</p>
<p>
<b>meta</b>
:
</p>
<p>
<b>identifier</b>
: urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281
</p>
<p>
<b>basedOn</b>
:
</p>
<p>
<b>status</b>
: final
</p>
<p>
<b>category</b>
: Vital Signs
<span>(Details :
{http://terminology.hl7.org/CodeSystem/observation-category code
&#39;vital-signs&#39; = &#39;Vital Signs&#39;, given as &#39;Vital
Signs&#39;})</span>
</p>
<p>
<b>code</b>:
Blood pressure systolic &amp; diastolic
<span>(Details : {LOINC code &#39;85354-9&#39; = &#39;Blood pressure
panel with all children optional&#39;, given as &#39;Blood pressure
panel with all children optional&#39;})</span>
</p>
<p>
<b>subject</b>
:
<a>Patient/example</a>
</p>
<p>
<b>effective</b>
: 17/09/2012
</p>
<p>
<b>performer</b>
:
<a>Practitioner/example</a>
</p>
<p>
<b>interpretation</b>
: Below low normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;L&#39; = &#39;Low&#39;, given as &#39;low&#39;})</span>
</p>
<p>
<b>bodySite</b>
: Right arm
<span>(Details : {SNOMED CT code &#39;368209003&#39; = &#39;Right
upper arm&#39;, given as &#39;Right arm&#39;})</span>
</p>
<blockquote>
<p>
<b>component</b>
</p>
<p>
<b>code</b>
: Systolic blood pressure
<span>(Details : {LOINC code &#39;8480-6&#39; = &#39;Systolic blood
pressure&#39;, given as &#39;Systolic blood pressure&#39;};
{SNOMED CT code &#39;271649006&#39; = &#39;Systolic blood
pressure&#39;, given as &#39;Systolic blood pressure&#39;};
{http://acme.org/devices/clinical-codes code &#39;bp-s&#39; =
&#39;bp-s&#39;, given as &#39;Systolic Blood pressure&#39;})
</span>
</p>
<p>
<b>value</b>
: 107 mmHg
<span> (Details: UCUM code mm[Hg] = &#39;mmHg&#39;)</span>
</p>
<p>
<b>interpretation</b>
: Normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;N&#39; = &#39;Normal&#39;, given as &#39;normal&#39;})
</span>
</p>
</blockquote>
<blockquote>
<p>
<b>component</b>
</p>
<p>
<b>code</b>
: Diastolic blood pressure
<span>(Details : {LOINC code &#39;8462-4&#39; = &#39;Diastolic
blood pressure&#39;, given as &#39;Diastolic blood pressure&#39;})
</span>
</p>
<p>
<b>value</b>
: 60 mmHg
<span> (Details: UCUM code mm[Hg] = &#39;mmHg&#39;)</span>
</p>
<p>
<b>interpretation</b>
: Below low normal
<span>(Details :
{http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation
code &#39;L&#39; = &#39;Low&#39;, given as &#39;low&#39;})</span>
</p>
</blockquote>
</div>
</text>
<identifier>
<system value="urn:ietf:rfc:3986" />
<value value="urn:uuid:187e0c12-8dd2-67e2-99b2-bf273c878281" />
</identifier><!-- demonstrating the use of the baseOn element with a fictive
identifier -->
<basedOn>
<identifier>
<system value="https://acme.org/identifiers" />
<value value="1234" />
</identifier>
</basedOn>
<status value="final" />
<category>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/observation-category" />
<code value="vital-signs" />
<display value="Vital Signs" />
</coding>
</category>
<code><!-- replaced by 85354-9 <coding> <system value="http://loinc.org"/>
<code value="85354-9"/> <display value="Blood pressure systolic &amp; diastolic"/>
</coding> -->
<coding>
<system value="http://loinc.org" />
<code value="85354-9" />
<display
value="Blood pressure panel with all children optional" />
</coding>
<text value="Blood pressure systolic &amp; diastolic" />
</code>
<subject>
<reference value="Patient/example" />
</subject>
<effectiveDateTime value="2012-09-17" />
<performer>
<reference value="Practitioner/example" />
</performer><!-- an interpretation offered to the combination observation
generally, it would only be appropriate to offer an interpretation of an
observation that has no value if it has "COMP" (component) observations -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="L" />
<display value="low" />
</coding>
<text value="Below low normal" />
</interpretation><!-- The BodySite can be captured in a LOINC code but am
showing it here to demonstrate populating the element -->
<bodySite>
<coding>
<system value="http://snomed.info/sct" />
<code value="368209003" />
<display value="Right arm" />
</coding>
</bodySite>
<component><!-- Observations are often coded in multiple code systems. -
LOINC provides a very specific code (though not more specific in this particular
case) - snomed provides a clinically relevant code that is usually less granular
than LOINC - the source system provides its own code, which may be less or
more granular than LOINC this is shown here to demonstrate the concept of
translations within the codeableConcept datatype. The diastolic code below
only has a LOINC code -->
<code><!-- LOINC -code -->
<coding>
<system value="http://loinc.org" />
<code value="8480-6" />
<display value="Systolic blood pressure" />
</coding><!-- SNOMED CT Codes -->
<coding>
<system value="http://snomed.info/sct" />
<code value="271649006" />
<display value="Systolic blood pressure" />
</coding><!-- Also, a local code specific to the source system -->
<coding>
<system value="http://acme.org/devices/clinical-codes" />
<code value="bp-s" />
<display value="Systolic Blood pressure" />
</coding>
</code>
<valueQuantity>
<value value="107" />
<unit value="mmHg" />
<system value="http://unitsofmeasure.org" />
<code value="mm[Hg]" />
</valueQuantity><!-- an interpretation for the individual composite observation -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="N" />
<display value="normal" />
</coding>
<text value="Normal" />
</interpretation><!-- Should have a refrange as well -->
</component>
<component><!-- this codes only has a LOINC code -->
<code>
<coding>
<system value="http://loinc.org" />
<code value="8462-4" />
<display value="Diastolic blood pressure" />
</coding>
</code>
<valueQuantity>
<value value="60" />
<unit value="mmHg" />
<system value="http://unitsofmeasure.org" />
<code value="mm[Hg]" />
</valueQuantity><!-- an interpretation for the individual composite observation -->
<interpretation>
<coding>
<system
value="http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation" />
<code value="L" />
<display value="low" />
</coding>
<text value="Below low normal" />
</interpretation><!-- Should have a refrange as well -->
</component>
</Observation>

View File

@ -0,0 +1,103 @@
<Observation xmlns="http://hl7.org/fhir">
<!-- extract from http://hl7.org/fhir/triglyceride-examples.html, changed
id from triglyceride and added explivit profile reference to http://hl7.org/fhir/StructureDefinition/triglyceride
and added snomed ct code for triglyceride -->
<id value="observation-triglyceride-bad-wrongcode" />
<meta>
<profile
value="http://hl7.org/fhir/StructureDefinition/triglyceride" />
</meta>
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b> Generated Narrative with Details</b>
</p>
<p>
<b> id</b>
: triglyceride
</p>
<p>
<b> status</b>
: final
</p>
<p>
<b> code</b>
: Triglyceride
<span> (Details : {LOINC code '35217-9' = 'Triglyceride [Mass or
Moles/volume] in Serum or Plasma',
given as 'Triglyceride
[Moles/ââ¬â€¹volume] in Serum or Plasma'})
</span>
</p>
<p>
<b> subject</b>
:
<a> Patient/pat2</a>
</p>
<p>
<b> performer</b>
:
<a> Acme Laboratory, Inc</a>
</p>
<p>
<b> value</b>
: 1.3 mmol/L
<span> (Details: UCUM code mmol/L = 'mmol/L')</span>
</p>
<h3> ReferenceRanges</h3>
<table>
<tr>
<td> -</td>
<td>
<b> High</b>
</td>
</tr>
<tr>
<td> *</td>
<td>
2.0 mmol/L
<span> (Details: UCUM code mmol/L = 'mmol/L')</span>
</td>
</tr>
</table>
</div>
</text>
<status value="final" />
<code>
<coding>
<system value="http://loinc.org" />
<code value="35200-5" />
<display
value="Cholest SerPl-msCnc" />
</coding>
<coding>
<system value="http://snomed.info/sct" />
<code value="85600001" />
<display value="Triacylglycerol" />
</coding>
<text value="Cholesterol" />
</code>
<subject>
<reference value="Patient/pat2" />
</subject>
<performer>
<reference
value="Organization/1832473e-2fe0-452d-abe9-3cdb9879522f" />
<display value="Acme Laboratory, Inc" />
</performer>
<valueQuantity>
<value value="1.3" />
<unit value="mmol/L" />
<system value="http://unitsofmeasure.org" />
<code value="mmol/L" />
</valueQuantity>
<referenceRange>
<high>
<value value="2.0" />
<unit value="mmol/L" />
<system value="http://unitsofmeasure.org" />
<code value="mmol/L" />
</high>
</referenceRange>
</Observation>

View File

@ -0,0 +1,103 @@
<Observation xmlns="http://hl7.org/fhir">
<!-- extract from http://hl7.org/fhir/triglyceride-examples.html, changed
id from triglyceride and added explicit profile reference to http://hl7.org/fhir/StructureDefinition/triglyceride
and added snomed ct code for triglyceride -->
<id value="observation-triglyceride-good" />
<meta>
<profile
value="http://hl7.org/fhir/StructureDefinition/triglyceride" />
</meta>
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b> Generated Narrative with Details</b>
</p>
<p>
<b> id</b>
: triglyceride
</p>
<p>
<b> status</b>
: final
</p>
<p>
<b> code</b>
: Triglyceride
<span> (Details : {LOINC code '35217-9' = 'Triglyceride [Mass or
Moles/volume] in Serum or Plasma',
given as 'Triglyceride
[Moles/ââ¬â€¹volume] in Serum or Plasma'})
</span>
</p>
<p>
<b> subject</b>
:
<a> Patient/pat2</a>
</p>
<p>
<b> performer</b>
:
<a> Acme Laboratory, Inc</a>
</p>
<p>
<b> value</b>
: 1.3 mmol/L
<span> (Details: UCUM code mmol/L = 'mmol/L')</span>
</p>
<h3> ReferenceRanges</h3>
<table>
<tr>
<td> -</td>
<td>
<b> High</b>
</td>
</tr>
<tr>
<td> *</td>
<td>
2.0 mmol/L
<span> (Details: UCUM code mmol/L = 'mmol/L')</span>
</td>
</tr>
</table>
</div>
</text>
<status value="final" />
<code>
<coding>
<system value="http://loinc.org" />
<code value="35217-9" />
<display
value="Triglyceride [Moles/&#x200B;volume] in Serum or Plasma" />
</coding>
<coding>
<system value="http://snomed.info/sct" />
<code value="85600001" />
<display value="Triacylglycerol" />
</coding>
<text value="Triglyceride" />
</code>
<subject>
<reference value="Patient/pat2" />
</subject>
<performer>
<reference
value="Organization/1832473e-2fe0-452d-abe9-3cdb9879522f" />
<display value="Acme Laboratory, Inc" />
</performer>
<valueQuantity>
<value value="1.3" />
<unit value="mmol/L" />
<system value="http://unitsofmeasure.org" />
<code value="mmol/L" />
</valueQuantity>
<referenceRange>
<high>
<value value="2.0" />
<unit value="mmol/L" />
<system value="http://unitsofmeasure.org" />
<code value="mmol/L" />
</high>
</referenceRange>
</Observation>

View File

@ -0,0 +1,108 @@
<Observation xmlns="http://hl7.org/fhir">
<!-- extract from http://hl7.org/fhir/triglyceride-examples.html, changed
id from triglyceride and added explicit profile reference to http://hl7.org/fhir/StructureDefinition/triglyceride
and added snomed ct code for triglyceride -->
<id value="observation-triglyceride-good2" />
<meta>
<profile
value="http://hl7.org/fhir/StructureDefinition/triglyceride" />
</meta>
<text>
<status value="generated" />
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b> Generated Narrative with Details</b>
</p>
<p>
<b> id</b>
: triglyceride
</p>
<p>
<b> status</b>
: final
</p>
<p>
<b> code</b>
: Triglyceride
<span> (Details : {LOINC code '35217-9' = 'Triglyceride [Mass or
Moles/volume] in Serum or Plasma',
given as 'Triglyceride
[Moles/ââ¬â€¹volume] in Serum or Plasma'})
</span>
</p>
<p>
<b> subject</b>
:
<a> Patient/pat2</a>
</p>
<p>
<b> performer</b>
:
<a> Acme Laboratory, Inc</a>
</p>
<p>
<b> value</b>
: 1.3 mmol/L
<span> (Details: UCUM code mmol/L = 'mmol/L')</span>
</p>
<h3> ReferenceRanges</h3>
<table>
<tr>
<td> -</td>
<td>
<b> High</b>
</td>
</tr>
<tr>
<td> *</td>
<td>
2.0 mmol/L
<span> (Details: UCUM code mmol/L = 'mmol/L')</span>
</td>
</tr>
</table>
</div>
</text>
<status value="final" />
<code>
<coding>
<system value="http://snomed.info/sct" />
<code value="85600001" />
<display value="Triacylglycerol" />
</coding>
<coding>
<system value="http://loinc.org" />
<code value="35217-9" />
<display
value="Triglyceride [Moles/&#x200B;volume] in Serum or Plasma" />
</coding>
<coding>
<system value="http://snomed.info/sct" />
<code value="85600001" />
<display value="Triacylglycerol" />
</coding>
<text value="Triglyceride" />
</code>
<subject>
<reference value="Patient/pat2" />
</subject>
<performer>
<reference
value="Organization/1832473e-2fe0-452d-abe9-3cdb9879522f" />
<display value="Acme Laboratory, Inc" />
</performer>
<valueQuantity>
<value value="1.3" />
<unit value="mmol/L" />
<system value="http://unitsofmeasure.org" />
<code value="mmol/L" />
</valueQuantity>
<referenceRange>
<high>
<value value="2.0" />
<unit value="mmol/L" />
<system value="http://unitsofmeasure.org" />
<code value="mmol/L" />
</high>
</referenceRange>
</Observation>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="slice-by-polymorphic-type2-profile"/>
<url value="http://hl7.org/fhir/StructureDefinition/slice-by-polymorphic-type2-profile"/>
<name value="SliceByPolymorphicType2Profile"/>
<title value="Test slicing by polymorphic type"/>
<status value="draft"/>
<kind value="resource"/>
<abstract value="false"/>
<type value="PlanDefinition"/>
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/PlanDefinition"/>
<derivation value="constraint"/>
<differential>
<element id="PlanDefinition">
<path value="PlanDefinition"/>
</element>
<element id="PlanDefinition.goal">
<path value="PlanDefinition.goal"/>
</element>
<element id="PlanDefinition.goal.target">
<path value="PlanDefinition.goal.target"/>
</element>
<element id="PlanDefinition.goal.target.detail[x]">
<path value="PlanDefinition.goal.target.detail[x]"/>
<type>
<code value="CodeableConcept"/>
</type>
<type>
<code value="Range"/>
</type>
</element>
<element id="PlanDefinition.goal.target.detailCodeableConcept">
<path value="PlanDefinition.goal.target.detailCodeableConcept"/>
<type>
<code value="CodeableConcept"/>
</type>
<mustSupport value="true"/>
</element>
</differential>
</StructureDefinition>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--<PlanDefinition xmlns="http://hl7.org/fhir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://hl7.org/fhir ../../../../../../FHIR/schema/fhir-single.xsd">-->
<PlanDefinition xmlns="http://hl7.org/fhir">
<id value="slice-by-polymorphic-type2"/>
<status value="active"/>
<goal>
<description>
<text value="Some goal"/>
</description>
<target>
<detailCodeableConcept>
<text value="Some Text"/>
</detailCodeableConcept>
</target>
</goal>
</PlanDefinition>