use of org.hl7.fhir.dstu3.model.Account in project synthea by synthetichealth.
the class FHIRSTU3ExporterTest method testFHIRSTU3Export.
@Test
public void testFHIRSTU3Export() throws Exception {
TestHelper.loadTestProperties();
Generator.DEFAULT_STATE = Config.get("test_state.default", "Massachusetts");
Config.set("exporter.baseDirectory", tempFolder.newFolder().toString());
FhirContext ctx = FhirStu3.getContext();
IParser parser = ctx.newJsonParser().setPrettyPrint(true);
FhirValidator validator = ctx.newValidator();
validator.setValidateAgainstStandardSchema(true);
validator.setValidateAgainstStandardSchematron(true);
ValidationResources validationResources = new ValidationResources();
List<String> errors = ParallelTestingService.runInParallel((person) -> {
List<String> validationErrors = new ArrayList<String>();
TestHelper.exportOff();
Config.set("exporter.fhir_stu3.export", "true");
Config.set("exporter.fhir.use_shr_extensions", "true");
FhirStu3.TRANSACTION_BUNDLE = person.randBoolean();
String fhirJson = FhirStu3.convertToFHIRJson(person, System.currentTimeMillis());
// (these should have been converted into URIs)
if (fhirJson.contains("SNOMED-CT")) {
validationErrors.add("JSON contains unconverted references to 'SNOMED-CT' (should be URIs)");
}
// let's crack open the Bundle and validate
// each individual entry.resource to get context-sensitive error
// messages...
Bundle bundle = parser.parseResource(Bundle.class, fhirJson);
for (BundleEntryComponent entry : bundle.getEntry()) {
ValidationResult eresult = validator.validateWithResult(entry.getResource());
if (!eresult.isSuccessful()) {
for (SingleValidationMessage emessage : eresult.getMessages()) {
boolean valid = false;
if (emessage.getMessage().contains("@ Observation obs-7")) {
/*
* The obs-7 invariant basically says that Observations should have values, unless
* they are made of components. This test replaces an invalid XPath expression
* that was causing correct instances to fail validation.
*/
valid = validateObs7((Observation) entry.getResource());
} else if (emessage.getMessage().contains("@ Condition con-4")) {
/*
* The con-4 invariant says "If condition is abated, then clinicalStatus must be
* either inactive, resolved, or remission" which is very clear and sensical.
* However, the XPath expression does not evaluate correctly for valid instances,
* so we must manually validate.
*/
valid = validateCon4((Condition) entry.getResource());
} else if (emessage.getMessage().contains("@ MedicationRequest mps-1")) {
/*
* The mps-1 invariant says MedicationRequest.requester.onBehalfOf can only be
* specified if MedicationRequest.requester.agent is practitioner or device.
* But the invariant is poorly written and does not correctly handle references
* starting with "urn:uuid"
*/
// ignore this error
valid = true;
} else if (emessage.getMessage().contains("per-1: If present, start SHALL have a lower value than end")) {
/*
* The per-1 invariant does not account for daylight savings time... so, if the
* daylight savings switch happens between the start and end, the validation
* fails, even if it is valid.
*/
// ignore this error
valid = true;
}
if (!valid) {
System.out.println(parser.encodeResourceToString(entry.getResource()));
System.out.println("ERROR: " + emessage.getMessage());
validationErrors.add(emessage.getMessage());
}
}
}
// Check ExplanationOfBenefit Resources against BlueButton
if (entry.getResource().fhirType().equals("ExplanationOfBenefit")) {
ValidationResult bbResult = validationResources.validateSTU3(entry.getResource());
for (SingleValidationMessage message : bbResult.getMessages()) {
if (message.getMessage().contains("extension https://bluebutton.cms.gov/assets")) {
/*
* The instance validator complains about the BlueButton extensions, ignore
*/
continue;
} else if (message.getSeverity() == ResultSeverityEnum.ERROR) {
if (!(message.getMessage().contains("Element 'ExplanationOfBenefit.id': minimum required = 1, but only found 0") || message.getMessage().contains("Could not verify slice for profile"))) {
// For some reason the validator is not detecting the IDs on the resources,
// even though they appear to be present while debugging and during normal
// operations.
System.out.println(message.getSeverity() + ": " + message.getMessage());
Assert.fail(message.getSeverity() + ": " + message.getMessage());
}
}
}
}
}
if (!validationErrors.isEmpty()) {
FailedExportHelper.dumpInfo("FHIRSTU3", fhirJson, validationErrors, person);
}
return validationErrors;
});
assertTrue("Validation of exported FHIR bundle failed: " + String.join("|", errors), errors.size() == 0);
}
use of org.hl7.fhir.dstu3.model.Account in project synthea by synthetichealth.
the class FhirStu3 method basicInfo.
/**
* Map the given Person to a FHIR Patient resource, and add it to the given Bundle.
*
* @param person The Person
* @param bundle The Bundle to add to
* @param stopTime Time the simulation ended
* @return The created Entry
*/
@SuppressWarnings("rawtypes")
private static BundleEntryComponent basicInfo(Person person, Bundle bundle, long stopTime) {
Patient patientResource = new Patient();
patientResource.addIdentifier().setSystem("https://github.com/synthetichealth/synthea").setValue((String) person.attributes.get(Person.ID));
Code mrnCode = new Code("http://hl7.org/fhir/v2/0203", "MR", "Medical Record Number");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(mrnCode, "http://hl7.org/fhir/v2/0203")).setSystem("http://hospital.smarthealthit.org").setValue((String) person.attributes.get(Person.ID));
Code ssnCode = new Code("http://hl7.org/fhir/identifier-type", "SB", "Social Security Number");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(ssnCode, "http://hl7.org/fhir/identifier-type")).setSystem("http://hl7.org/fhir/sid/us-ssn").setValue((String) person.attributes.get(Person.IDENTIFIER_SSN));
if (person.attributes.get(Person.IDENTIFIER_DRIVERS) != null) {
Code driversCode = new Code("http://hl7.org/fhir/v2/0203", "DL", "Driver's License");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(driversCode, "http://hl7.org/fhir/v2/0203")).setSystem("urn:oid:2.16.840.1.113883.4.3.25").setValue((String) person.attributes.get(Person.IDENTIFIER_DRIVERS));
}
if (person.attributes.get(Person.IDENTIFIER_PASSPORT) != null) {
Code passportCode = new Code("http://hl7.org/fhir/v2/0203", "PPN", "Passport Number");
patientResource.addIdentifier().setType(mapCodeToCodeableConcept(passportCode, "http://hl7.org/fhir/v2/0203")).setSystem(SHR_EXT + "passportNumber").setValue((String) person.attributes.get(Person.IDENTIFIER_PASSPORT));
}
if (person.attributes.get(Person.CONTACT_EMAIL) != null) {
ContactComponent contact = new ContactComponent();
HumanName contactName = new HumanName();
contactName.setUse(HumanName.NameUse.OFFICIAL);
contactName.addGiven((String) person.attributes.get(Person.CONTACT_GIVEN_NAME));
contactName.setFamily((String) person.attributes.get(Person.CONTACT_FAMILY_NAME));
contact.setName(contactName);
contact.addTelecom().setSystem(ContactPointSystem.EMAIL).setUse(ContactPointUse.HOME).setValue((String) person.attributes.get(Person.CONTACT_EMAIL));
patientResource.addContact(contact);
}
// We do not yet account for mixed race
Extension raceExtension = new Extension("http://hl7.org/fhir/us/core/StructureDefinition/us-core-race");
String race = (String) person.attributes.get(Person.RACE);
String raceDisplay;
switch(race) {
case "white":
raceDisplay = "White";
break;
case "black":
raceDisplay = "Black or African American";
break;
case "asian":
raceDisplay = "Asian";
break;
case "native":
raceDisplay = "American Indian or Alaska Native";
break;
case "hawaiian":
raceDisplay = "Native Hawaiian or Other Pacific Islander";
break;
default:
raceDisplay = "Other";
break;
}
String raceNum = (String) raceEthnicityCodes.get(race);
Extension raceCodingExtension = new Extension("ombCategory");
Coding raceCoding = new Coding();
if (raceDisplay.equals("Other")) {
raceCoding.setSystem("http://hl7.org/fhir/v3/NullFlavor");
raceCoding.setCode("UNK");
raceCoding.setDisplay("Unknown");
} else {
raceCoding.setSystem("urn:oid:2.16.840.1.113883.6.238");
raceCoding.setCode(raceNum);
raceCoding.setDisplay(raceDisplay);
}
raceCodingExtension.setValue(raceCoding);
raceExtension.addExtension(raceCodingExtension);
Extension raceTextExtension = new Extension("text");
raceTextExtension.setValue(new StringType(raceDisplay));
raceExtension.addExtension(raceTextExtension);
patientResource.addExtension(raceExtension);
// We do not yet account for mixed ethnicity
Extension ethnicityExtension = new Extension("http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity");
String ethnicity = (String) person.attributes.get(Person.ETHNICITY);
String ethnicityDisplay;
if (ethnicity.equals("hispanic")) {
ethnicity = "hispanic";
ethnicityDisplay = "Hispanic or Latino";
} else {
ethnicity = "nonhispanic";
ethnicityDisplay = "Not Hispanic or Latino";
}
String ethnicityNum = (String) raceEthnicityCodes.get(ethnicity);
Extension ethnicityCodingExtension = new Extension("ombCategory");
Coding ethnicityCoding = new Coding();
ethnicityCoding.setSystem("urn:oid:2.16.840.1.113883.6.238");
ethnicityCoding.setCode(ethnicityNum);
ethnicityCoding.setDisplay(ethnicityDisplay);
ethnicityCodingExtension.setValue(ethnicityCoding);
ethnicityExtension.addExtension(ethnicityCodingExtension);
Extension ethnicityTextExtension = new Extension("text");
ethnicityTextExtension.setValue(new StringType(ethnicityDisplay));
ethnicityExtension.addExtension(ethnicityTextExtension);
patientResource.addExtension(ethnicityExtension);
String firstLanguage = (String) person.attributes.get(Person.FIRST_LANGUAGE);
Map languageMap = (Map) languageLookup.get(firstLanguage);
Code languageCode = new Code((String) languageMap.get("system"), (String) languageMap.get("code"), (String) languageMap.get("display"));
List<PatientCommunicationComponent> communication = new ArrayList<PatientCommunicationComponent>();
communication.add(new PatientCommunicationComponent(mapCodeToCodeableConcept(languageCode, (String) languageMap.get("system"))));
patientResource.setCommunication(communication);
HumanName name = patientResource.addName();
name.setUse(HumanName.NameUse.OFFICIAL);
name.addGiven((String) person.attributes.get(Person.FIRST_NAME));
name.setFamily((String) person.attributes.get(Person.LAST_NAME));
if (person.attributes.get(Person.NAME_PREFIX) != null) {
name.addPrefix((String) person.attributes.get(Person.NAME_PREFIX));
}
if (person.attributes.get(Person.NAME_SUFFIX) != null) {
name.addSuffix((String) person.attributes.get(Person.NAME_SUFFIX));
}
if (person.attributes.get(Person.MAIDEN_NAME) != null) {
HumanName maidenName = patientResource.addName();
maidenName.setUse(HumanName.NameUse.MAIDEN);
maidenName.addGiven((String) person.attributes.get(Person.FIRST_NAME));
maidenName.setFamily((String) person.attributes.get(Person.MAIDEN_NAME));
if (person.attributes.get(Person.NAME_PREFIX) != null) {
maidenName.addPrefix((String) person.attributes.get(Person.NAME_PREFIX));
}
if (person.attributes.get(Person.NAME_SUFFIX) != null) {
maidenName.addSuffix((String) person.attributes.get(Person.NAME_SUFFIX));
}
}
Extension mothersMaidenNameExtension = new Extension("http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName");
String mothersMaidenName = (String) person.attributes.get(Person.NAME_MOTHER);
mothersMaidenNameExtension.setValue(new StringType(mothersMaidenName));
patientResource.addExtension(mothersMaidenNameExtension);
long birthdate = (long) person.attributes.get(Person.BIRTHDATE);
patientResource.setBirthDate(new Date(birthdate));
Extension birthSexExtension = new Extension("http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex");
if (person.attributes.get(Person.GENDER).equals("M")) {
patientResource.setGender(AdministrativeGender.MALE);
birthSexExtension.setValue(new CodeType("M"));
} else if (person.attributes.get(Person.GENDER).equals("F")) {
patientResource.setGender(AdministrativeGender.FEMALE);
birthSexExtension.setValue(new CodeType("F"));
}
patientResource.addExtension(birthSexExtension);
String state = (String) person.attributes.get(Person.STATE);
Address addrResource = patientResource.addAddress();
addrResource.addLine((String) person.attributes.get(Person.ADDRESS)).setCity((String) person.attributes.get(Person.CITY)).setPostalCode((String) person.attributes.get(Person.ZIP)).setState(state);
if (COUNTRY_CODE != null) {
addrResource.setCountry(COUNTRY_CODE);
}
Address birthplace = new Address();
birthplace.setCity((String) person.attributes.get(Person.BIRTH_CITY)).setState((String) person.attributes.get(Person.BIRTH_STATE)).setCountry((String) person.attributes.get(Person.BIRTH_COUNTRY));
Extension birthplaceExtension = new Extension("http://hl7.org/fhir/StructureDefinition/birthPlace");
birthplaceExtension.setValue(birthplace);
patientResource.addExtension(birthplaceExtension);
if (person.attributes.get(Person.MULTIPLE_BIRTH_STATUS) != null) {
patientResource.setMultipleBirth(new IntegerType((int) person.attributes.get(Person.MULTIPLE_BIRTH_STATUS)));
} else {
patientResource.setMultipleBirth(new BooleanType(false));
}
patientResource.addTelecom().setSystem(ContactPoint.ContactPointSystem.PHONE).setUse(ContactPoint.ContactPointUse.HOME).setValue((String) person.attributes.get(Person.TELECOM));
String maritalStatus = ((String) person.attributes.get(Person.MARITAL_STATUS));
if (maritalStatus != null) {
Code maritalStatusCode = new Code("http://hl7.org/fhir/v3/MaritalStatus", maritalStatus, maritalStatus);
patientResource.setMaritalStatus(mapCodeToCodeableConcept(maritalStatusCode, "http://hl7.org/fhir/v3/MaritalStatus"));
} else {
Code maritalStatusCode = new Code("http://hl7.org/fhir/v3/MaritalStatus", "S", "Never Married");
patientResource.setMaritalStatus(mapCodeToCodeableConcept(maritalStatusCode, "http://hl7.org/fhir/v3/MaritalStatus"));
}
Point2D.Double coord = person.getLonLat();
if (coord != null) {
Extension geolocation = addrResource.addExtension();
geolocation.setUrl("http://hl7.org/fhir/StructureDefinition/geolocation");
geolocation.addExtension("latitude", new DecimalType(coord.getY()));
geolocation.addExtension("longitude", new DecimalType(coord.getX()));
}
if (!person.alive(stopTime)) {
patientResource.setDeceased(convertFhirDateTime((Long) person.attributes.get(Person.DEATHDATE), true));
}
String generatedBySynthea = "Generated by <a href=\"https://github.com/synthetichealth/synthea\">Synthea</a>." + "Version identifier: " + Utilities.SYNTHEA_VERSION + " . " + " Person seed: " + person.getSeed() + " Population seed: " + person.populationSeed;
patientResource.setText(new Narrative().setStatus(NarrativeStatus.GENERATED).setDiv(new XhtmlNode(NodeType.Element).setValue(generatedBySynthea)));
if (USE_SHR_EXTENSIONS) {
patientResource.setMeta(new Meta().addProfile(SHR_EXT + "shr-entity-Patient"));
// Patient profile requires race, ethnicity, birthsex,
// MothersMaidenName, FathersName, Person-extension
patientResource.addExtension().setUrl(SHR_EXT + "shr-actor-FictionalPerson-extension").setValue(new BooleanType(true));
String fathersName = (String) person.attributes.get(Person.NAME_FATHER);
Extension fathersNameExtension = new Extension(SHR_EXT + "shr-entity-FathersName-extension", new HumanName().setText(fathersName));
patientResource.addExtension(fathersNameExtension);
String ssn = (String) person.attributes.get(Person.IDENTIFIER_SSN);
Extension ssnExtension = new Extension(SHR_EXT + "shr-demographics-SocialSecurityNumber-extension", new StringType(ssn));
patientResource.addExtension(ssnExtension);
Basic personResource = new Basic();
// the only required field on this patient resource is code
Coding fixedCode = new Coding("http://standardhealthrecord.org/fhir/basic-resource-type", "shr-entity-Person", "shr-entity-Person");
personResource.setCode(new CodeableConcept().addCoding(fixedCode));
Meta personMeta = new Meta();
personMeta.addProfile(SHR_EXT + "shr-entity-Person");
personResource.setMeta(personMeta);
BundleEntryComponent personEntry = newEntry(person, bundle, personResource);
patientResource.addExtension().setUrl(SHR_EXT + "shr-entity-Person-extension").setValue(new Reference(personEntry.getFullUrl()));
}
// DALY and QALY values
// we only write the last(current) one to the patient record
Double dalyValue = (Double) person.attributes.get("most-recent-daly");
Double qalyValue = (Double) person.attributes.get("most-recent-qaly");
if (dalyValue != null) {
Extension dalyExtension = new Extension(SYNTHEA_EXT + "disability-adjusted-life-years");
DecimalType daly = new DecimalType(dalyValue);
dalyExtension.setValue(daly);
patientResource.addExtension(dalyExtension);
Extension qalyExtension = new Extension(SYNTHEA_EXT + "quality-adjusted-life-years");
DecimalType qaly = new DecimalType(qalyValue);
qalyExtension.setValue(qaly);
patientResource.addExtension(qalyExtension);
}
return newEntry(bundle, patientResource, (String) person.attributes.get(Person.ID));
}
use of org.hl7.fhir.dstu3.model.Account in project BridgeServer2 by Sage-Bionetworks.
the class CRCControllerTest method operationMissingIdentifiers.
@Test(expectedExceptions = BadRequestException.class, expectedExceptionsMessageRegExp = "Could not find Bridge user ID.")
public void operationMissingIdentifiers() throws Exception {
when(mockRequest.getHeader(AUTHORIZATION)).thenReturn(AUTHORIZATION_HEADER_VALUE);
when(mockAccountService.authenticate(any(), any())).thenReturn(account);
when(mockAccountService.getAccount(ACCOUNT_ID)).thenReturn(Optional.of(account));
Observation observation = new Observation();
String json = FHIR_CONTEXT.newJsonParser().encodeResourceToString(observation);
mockRequestBody(mockRequest, json);
controller.postObservation();
}
use of org.hl7.fhir.dstu3.model.Account in project BridgeServer2 by Sage-Bionetworks.
the class CRCControllerTest method postAppointmentFailsWhenLocationCallFails.
@Test
public void postAppointmentFailsWhenLocationCallFails() throws Exception {
when(mockRequest.getHeader(AUTHORIZATION)).thenReturn(AUTHORIZATION_HEADER_VALUE);
when(mockAccountService.authenticate(any(), any())).thenReturn(account);
when(mockAccountService.getAccount(ACCOUNT_ID)).thenReturn(Optional.of(account));
// mockGetGeocoding();
DateRangeResourceList<? extends ReportData> results = new DateRangeResourceList<>(ImmutableList.of());
doReturn(results).when(mockReportService).getParticipantReport(APP_ID, TEST_USER_ID, APPOINTMENT_REPORT, HEALTH_CODE, JAN1, JAN2);
Appointment appointment = new Appointment();
appointment.setStatus(BOOKED);
// add a wrong participant to verify we go through them all and look for ours
addAppointmentParticipantComponent(appointment, "Location/foo");
addAppointmentSageId(appointment, TEST_USER_ID);
String json = FHIR_CONTEXT.newJsonParser().encodeResourceToString(appointment);
mockRequestBody(mockRequest, json);
HttpResponse mockResponse = mock(HttpResponse.class);
doReturn(mockResponse).when(controller).post(any(), any(), any());
StatusLine mockStatusLine = mock(StatusLine.class);
when(mockResponse.getStatusLine()).thenReturn(mockStatusLine);
when(mockStatusLine.getStatusCode()).thenReturn(400);
HttpEntity mockEntity = mock(HttpEntity.class);
when(mockResponse.getEntity()).thenReturn(mockEntity);
when(mockEntity.getContent()).thenReturn(IOUtils.toInputStream("This was an error.", UTF_8));
ResponseEntity<StatusMessage> retValue = controller.postAppointment();
assertEquals(retValue.getBody().getMessage(), "Appointment created (status = booked).");
assertEquals(retValue.getStatusCodeValue(), 201);
verify(mockAppender).doAppend(loggingEventCaptor.capture());
final LoggingEvent loggingEvent = loggingEventCaptor.getValue();
assertEquals(loggingEvent.getLevel(), Level.WARN);
assertEquals(loggingEvent.getFormattedMessage(), "Error retrieving location, id = foo, status = 400, response body = This was an error.");
}
use of org.hl7.fhir.dstu3.model.Account in project BridgeServer2 by Sage-Bionetworks.
the class CRCControllerTest method procedureMissingIdentifiers.
@Test(expectedExceptions = BadRequestException.class, expectedExceptionsMessageRegExp = "Could not find Bridge user ID.")
public void procedureMissingIdentifiers() throws Exception {
when(mockRequest.getHeader(AUTHORIZATION)).thenReturn(AUTHORIZATION_HEADER_VALUE);
when(mockAccountService.authenticate(any(), any())).thenReturn(account);
when(mockAccountService.getAccount(ACCOUNT_ID)).thenReturn(Optional.of(account));
ProcedureRequest procedure = new ProcedureRequest();
String json = FHIR_CONTEXT.newJsonParser().encodeResourceToString(procedure);
mockRequestBody(mockRequest, json);
controller.postProcedureRequest();
}
Aggregations