refs/refs/ETL-German-FHIR-Core/src/main/java/org/miracum/etl/fhirtoomop/mapper/PatientMapper.java
lines 607–641
700 lines · java
1package org.miracum.etl.fhirtoomop.mapper; 3import static org.miracum.etl.fhirtoomop.Constants.CONCEPT_EHR_RECORD_STATUS_DECEASED; 4import static org.miracum.etl.fhirtoomop.Constants.CONCEPT_GENDER_UNKNOWN; 5import static org.miracum.etl.fhirtoomop.Constants.CONCEPT_HISPANIC_OR_LATINO; 6import static org.miracum.etl.fhirtoomop.Constants.CONCEPT_NO_MATCHING_CONCEPT; 7import static org.miracum.etl.fhirtoomop.Constants.CONCEPT_UNKNOWN_RACIAL_GROUP; 8import static org.miracum.etl.fhirtoomop.Constants.ETHNICITY_SOURCE_HISPANIC_OR_LATINO; 9import static org.miracum.etl.fhirtoomop.Constants.ETHNICITY_SOURCE_MIXED; 10import static org.miracum.etl.fhirtoomop.Constants.MAX_LOCATION_CITY_LENGTH; 11import static org.miracum.etl.fhirtoomop.Constants.MAX_LOCATION_COUNTRY_LENGTH; 12import static org.miracum.etl.fhirtoomop.Constants.MAX_LOCATION_STATE_LENGTH; 13import static org.miracum.etl.fhirtoomop.Constants.MAX_LOCATION_ZIP_LENGTH; 14import static org.miracum.etl.fhirtoomop.Constants.MAX_SOURCE_VALUE_LENGTH; 15import static org.miracum.etl.fhirtoomop.Constants.SOURCE_VOCABULARY_ID_GENDER; 17import ca.uhn.fhir.fhirpath.IFhirPath; 18import com.google.common.base.Strings; 19import io.micrometer.core.instrument.Counter; 20import java.sql.Timestamp; 21import java.time.LocalDateTime; 22import java.time.ZoneId; 23import java.time.format.DateTimeFormatter; 24import java.util.Collections; 26import java.util.stream.Collectors; 27import lombok.extern.slf4j.Slf4j; 28import org.apache.commons.lang3.StringUtils; 29import org.hl7.fhir.r4.model.Address; 30import org.hl7.fhir.r4.model.Age; 31import org.hl7.fhir.r4.model.Coding; 32import org.hl7.fhir.r4.model.DateTimeType; 33import org.hl7.fhir.r4.model.DateType; 34import org.hl7.fhir.r4.model.Enumerations.ResourceType; 35import org.hl7.fhir.r4.model.Extension; 36import org.hl7.fhir.r4.model.Patient; 37import org.miracum.etl.fhirtoomop.DbMappings; 38import org.miracum.etl.fhirtoomop.config.FhirSystems; 39import org.miracum.etl.fhirtoomop.mapper.helpers.FindOmopConcepts; 40import org.miracum.etl.fhirtoomop.mapper.helpers.MapperMetrics; 41import org.miracum.etl.fhirtoomop.mapper.helpers.ResourceCheckDataAbsentReason; 42import org.miracum.etl.fhirtoomop.mapper.helpers.ResourceFhirReferenceUtils; 43import org.miracum.etl.fhirtoomop.mapper.helpers.ResourceOmopReferenceUtils; 44import org.miracum.etl.fhirtoomop.model.OmopModelWrapper; 45import org.miracum.etl.fhirtoomop.model.PostProcessMap; 46import org.miracum.etl.fhirtoomop.model.omop.Person; 47import org.miracum.etl.fhirtoomop.repository.service.PatientMapperServiceImpl; 48import org.springframework.beans.factory.annotation.Autowired; 49import org.springframework.stereotype.Component; 52 * The PatientMapper class describes the business logic of transforming a FHIR Patient resource to 60public class PatientMapper implements FhirMapper<Patient> { 61 private static final FhirSystems fhirSystems = new FhirSystems(); 62 private final IFhirPath fhirPath; 63 private final Boolean bulkload; 64 private final DbMappings dbMappings; 66 @Autowired ResourceOmopReferenceUtils omopReferenceUtils; 67 @Autowired ResourceFhirReferenceUtils fhirReferenceUtils; 68 @Autowired PatientMapperServiceImpl patientService; 69 @Autowired ResourceCheckDataAbsentReason checkDataAbsentReason; 70 @Autowired FindOmopConcepts findOmopConcepts; 72 private static final Counter noFhirReferenceCounter = 73 MapperMetrics.setNoFhirReferenceCounter("stepProcessPatients"); 74 private static final Counter deletedFhirReferenceCounter = 75 MapperMetrics.setDeletedFhirRessourceCounter("stepProcessPatients"); 78 * Constructor for objects of the class PatientMapper. 80 * @param fhirPath FhirPath engine to evaluate path expressions over FHIR resources 81 * @param bulkload parameter which indicates whether the Job should be run as bulk load or 83 * @param dbMappings collections for the intermediate storage of data from OMOP CDM in RAM 86 public PatientMapper(IFhirPath fhirPath, Boolean bulkload, DbMappings dbMappings) { 88 this.fhirPath = fhirPath; 89 this.bulkload = bulkload; 90 this.dbMappings = dbMappings; 94 * Maps a FHIR Patient resource to several OMOP CDM tables. 96 * @param srcPatient FHIR Patient resource 97 * @param isDeleted a flag, whether the FHIR resource is deleted in the source 98 * @return OmopModelWrapper cache of newly created OMOP CDM records from the FHIR Patient resource 101 public OmopModelWrapper map(Patient srcPatient, boolean isDeleted) { 103 var wrapper = new OmopModelWrapper(); 105 var patientSourceIdentifier = fhirReferenceUtils.extractIdentifier(srcPatient, "MR"); 106 var patientLogicId = fhirReferenceUtils.extractId(srcPatient); 107 if (Strings.isNullOrEmpty(patientLogicId) && Strings.isNullOrEmpty(patientSourceIdentifier)) { 108 log.warn("No [Identifier] or [Id] found. [Patient] resource is invalid. Skip resource"); 109 noFhirReferenceCounter.increment(); 113 String patientId = ""; 114 if (!Strings.isNullOrEmpty(patientLogicId)) { 115 patientId = srcPatient.getId(); 118 var ageExtensionMap = extractAgeExtension(srcPatient); 119 var ageAtDiagnosis = setAgeAtDiagnosis(patientLogicId, patientSourceIdentifier); 120 var realBirthDate = extractBirthDate(srcPatient); 121 var calculatedBirthDate = 122 extractCalculatedBirthDate(ageExtensionMap, ageAtDiagnosis, patientId); 124 if (realBirthDate == null && calculatedBirthDate == null) { 125 log.info("No [Birthdate] found for [Patient]: {}. Skip Resource.", patientId); 126 if (bulkload.equals(Boolean.FALSE)) { 127 deleteExistingPatients(patientLogicId, patientSourceIdentifier); 132 if (bulkload.equals(Boolean.FALSE) && isDeleted) { 133 log.info("Found a deleted [Patient] resource {}. Deleting from OMOP DB.", patientId); 134 deleteExistingPatients(patientLogicId, patientSourceIdentifier); 135 deletedFhirReferenceCounter.increment(); 139 if (bulkload.equals(Boolean.FALSE)) { 140 deleteExistingDeath(patientLogicId, patientSourceIdentifier); 141 deleteExistingCalculatedBirthYear(patientLogicId, patientSourceIdentifier); 144 var newPerson = createNewPerson(srcPatient, patientLogicId, patientSourceIdentifier, patientId); 145 setBirthDate(realBirthDate, calculatedBirthDate, newPerson); 147 var ethnicGroupCoding = extractEthnicGroup(srcPatient); 148 setRaceConcept(ethnicGroupCoding, newPerson, patientLogicId); 149 setEthnicityConcept(ethnicGroupCoding, newPerson); 151 var death = setDeath(srcPatient, patientLogicId, patientSourceIdentifier); 153 wrapper.getPostProcessMap().add(death); 156 var location = setLocation(srcPatient, patientLogicId, patientSourceIdentifier); 157 if (location != null) { 158 wrapper.getPostProcessMap().add(location); 161 wrapper.setPerson(newPerson); 163 if (ageAtDiagnosis.getDataOne() != null) { 164 wrapper.getPostProcessMap().add(ageAtDiagnosis); 169 private PostProcessMap setAgeAtDiagnosis(String patientLogicId, String patientSourceIdentifier) { 170 return PostProcessMap.builder() 171 .type(ResourceType.PATIENT.name()) 172 .omopTable("age_at_diagnosis") 173 .omopId(Long.valueOf(4307859)) 174 .fhirIdentifier(patientSourceIdentifier) 175 .fhirLogicalId(patientLogicId) 180 * Delete FHIR Patient resources from OMOP CDM tables using fhir_logical_id and fhir_identifier 182 * @param patientLogicId logical id of the FHIR Patient resource 183 * @param patientSourceIdentifier identifier of the FHIR Patient resource 185 private void deleteExistingPatients(String patientLogicId, String patientSourceIdentifier) { 186 if (!Strings.isNullOrEmpty(patientLogicId)) { 187 patientService.deletePersonByFhirLogicalId(patientLogicId); 189 patientService.deletePersonByFhirIdentifier(patientSourceIdentifier); 194 * Creates a new record of the person table in OMOP CDM for the processed FHIR Patient resource. 196 * @param srcPatient FHIR Patient resource 197 * @param patientLogicId logical id of the FHIR Patient resource 198 * @param patientSourceIdentifier identifier of the FHIR Patient resource 199 * @return new record of the person table in OMOP CDM for the processed FHIR Patient resource 201 private Person createNewPerson( 202 Patient srcPatient, String patientLogicId, String patientSourceIdentifier, String patientId) { 203 var personSourceValue = cutString(patientSourceIdentifier, MAX_SOURCE_VALUE_LENGTH); 207 .personSourceValue(personSourceValue == null ? null : personSourceValue.substring(4)) 208 .fhirLogicalId(patientLogicId) 209 .fhirIdentifier(patientSourceIdentifier) 211 var gender = getGender(srcPatient); 212 person.setGenderConceptId(getGenderConceptId(gender)); 213 person.setGenderSourceValue(gender); 215 if (bulkload.equals(Boolean.FALSE)) { 216 var existingPersonId = 217 omopReferenceUtils.getExistingPersonId(patientSourceIdentifier, patientLogicId); 218 if (existingPersonId != null) { 219 log.debug("[Patient] {} exists already in person. Update existing person", patientId); 221 person.setPersonId(existingPersonId); 228 * Set the information for ethnicity in person record. 230 * @param ethnicGroupCoding coding of ethnic group 231 * @param person new record of the person table in OMOP CDM 233 private void setEthnicityConcept(Coding ethnicGroupCoding, Person person) { 234 if (ethnicGroupCoding == null || Strings.isNullOrEmpty(ethnicGroupCoding.getCode())) { 235 person.setEthnicityConceptId(CONCEPT_NO_MATCHING_CONCEPT); 239 var ethnicGroupCode = ethnicGroupCoding.getCode(); 240 if (ethnicGroupCode.equals(ETHNICITY_SOURCE_HISPANIC_OR_LATINO)) { 241 person.setEthnicityConceptId(CONCEPT_HISPANIC_OR_LATINO); 242 person.setEthnicitySourceConceptId(CONCEPT_HISPANIC_OR_LATINO); 243 person.setEthnicitySourceValue(ETHNICITY_SOURCE_HISPANIC_OR_LATINO); 245 } else if (ethnicGroupCode.equals(ETHNICITY_SOURCE_MIXED)) { 246 person.setEthnicityConceptId(CONCEPT_NO_MATCHING_CONCEPT); 247 person.setEthnicitySourceValue(ethnicGroupCode); 249 person.setEthnicityConceptId(CONCEPT_NO_MATCHING_CONCEPT); 254 * Set the information for race in person record. 256 * @param ethnicGroupCoding coding of ethnic group 257 * @param person new record of the person table in OMOP CDM 259 private void setRaceConcept(Coding ethnicGroupCoding, Person person, String patientLogicId) { 261 if (ethnicGroupCoding == null || Strings.isNullOrEmpty(ethnicGroupCoding.getCode())) { 262 person.setRaceConceptId(CONCEPT_UNKNOWN_RACIAL_GROUP); 265 var ethnicGroupCode = ethnicGroupCoding.getCode(); 266 if (ethnicGroupCode.equals(ETHNICITY_SOURCE_HISPANIC_OR_LATINO)) { 267 person.setRaceConceptId(CONCEPT_UNKNOWN_RACIAL_GROUP); 268 } else if (ethnicGroupCode.equals(ETHNICITY_SOURCE_MIXED)) { 269 person.setRaceConceptId(CONCEPT_NO_MATCHING_CONCEPT); 270 person.setRaceSourceValue(ethnicGroupCode); 273 findOmopConcepts.getSnomedRaceConcepts( 274 ethnicGroupCoding, bulkload, dbMappings, patientLogicId); 275 if (ethnicConcept != null) { 276 person.setRaceConceptId(ethnicConcept.getStandardRaceConceptId()); 277 person.setRaceSourceConceptId(ethnicConcept.getSnomedConceptId()); 278 person.setRaceSourceValue(ethnicGroupCode); 284 * Creates a new record of the post_process_map table in OMOP CDM for extracted location 285 * informations from the processed FHIR Patient resource. 287 * @param srcPatient FHIR Patient resource 288 * @param patientLogicId logical id of the FHIR Patient resource 289 * @param patientSourceIdentifier identifier of the FHIR Patient resource 290 * @return new record of the post_process_map table in OMOP CDM for extracted location 291 * informations from the processed FHIR Patient resource 293 private PostProcessMap setLocation( 294 Patient srcPatient, String patientLogicId, String patientSourceIdentifier) { 295 if (!srcPatient.hasAddress() || srcPatient.getAddress().isEmpty()) { 299 var address = srcPatient.getAddressFirstRep(); 300 if (address.getExtensionByUrl(fhirSystems.getDataAbsentReason()) != null) { 303 StringBuilder dataOne = new StringBuilder(); 304 StringBuilder dataTwo = new StringBuilder(); 306 addZip(address, dataOne); 308 addCity(address, dataOne); 310 addCountry(address, dataOne); 312 addLines(address, dataTwo); 314 addState(address, dataTwo); 316 var dataOneStr = dataOne.toString(); 317 var dataTwoStr = dataTwo.toString(); 318 // if (Strings.isNullOrEmpty(dataOneStr) && Strings.isNullOrEmpty(dataTwoStr)) { 322 if (dataOneStr.equals(";;") && dataTwoStr.equals(";")) { 326 return PostProcessMap.builder() 327 .dataOne(dataOne.toString()) 328 .dataTwo(dataTwo.toString()) 329 .omopTable(OmopModelWrapper.Tablename.LOCATION.name()) 330 .type(ResourceType.PATIENT.name()) 331 .fhirLogicalId(patientLogicId) 332 .fhirIdentifier(patientSourceIdentifier) 337 * Append the state information (if exists) to column dataTwo from POST_PROCESS_MAP table. 339 * @param address Address component from Patient FHIR resource 340 * @param dataTwo StringBuilder for the dataTwo column from POST_PROCESS_MAP table 342 private void addState(Address address, StringBuilder dataTwo) { 343 var stateElement = address.getStateElement(); 344 if (stateElement.isEmpty()) { 347 var state = checkDataAbsentReason.getValue(stateElement); 349 if (!Strings.isNullOrEmpty(state)) { 350 dataTwo.append(cutString(state, MAX_LOCATION_STATE_LENGTH)); 355 * Append the street information (if exists) to column dataTwo from POST_PROCESS_MAP table. 357 * @param address Address component from Patient FHIR resource 358 * @param dataTwo StringBuilder for the dataTwo column from POST_PROCESS_MAP table 360 private void addLines(Address address, StringBuilder dataTwo) { 361 var lines = address.getLine(); 362 if (lines.isEmpty()) { 366 for (var line : lines) { 367 if (line.isEmpty()) { 370 var lineStr = checkDataAbsentReason.getValue(line); 371 if (!Strings.isNullOrEmpty(lineStr)) { 372 dataTwo.append(line); 376 // if (!dataTwo.isEmpty()) { 377 // dataTwo.append(";"); 382 * Append the country information (if exists) to column dataTwo from POST_PROCESS_MAP table. 384 * @param address Address component from Patient FHIR resource 385 * @param dataOne StringBuilder for the dataOne column from POST_PROCESS_MAP table 387 private void addCountry(Address address, StringBuilder dataOne) { 388 var countryElement = address.getCountryElement(); 389 if (countryElement.isEmpty()) { 392 var country = checkDataAbsentReason.getValue(countryElement); 393 if (!Strings.isNullOrEmpty(country)) { 394 dataOne.append(cutString(country.replaceAll("\\s+", ""), MAX_LOCATION_COUNTRY_LENGTH)); 399 * Append the city information (if exists) to column dataTwo from POST_PROCESS_MAP table. 401 * @param address Address component from Patient FHIR resource 402 * @param dataOne StringBuilder for the dataOne column from POST_PROCESS_MAP table 404 private void addCity(Address address, StringBuilder dataOne) { 405 var cityElement = address.getCityElement(); 406 if (cityElement.isEmpty()) { 409 var city = checkDataAbsentReason.getValue(cityElement); 410 if (!Strings.isNullOrEmpty(city)) { 411 dataOne.append(cutString(city, MAX_LOCATION_CITY_LENGTH)); 416 * Append the zip code information (if exists) to column dataTwo from POST_PROCESS_MAP table. 418 * @param address Address component from Patient FHIR resource 419 * @param dataOne StringBuilder for the dataOne column from POST_PROCESS_MAP table 421 private void addZip(Address address, StringBuilder dataOne) { 422 var zipElement = address.getPostalCodeElement(); 423 if (zipElement.isEmpty()) { 426 var zip = checkDataAbsentReason.getValue(zipElement); 427 if (!Strings.isNullOrEmpty(zip)) { 428 dataOne.append(cutString(zip, MAX_LOCATION_ZIP_LENGTH)); 433 * Shortens a string value to a specified maximum length. 435 * @param stringToBeCut string value to be shortened 436 * @param maxLength maximum length of the string value 437 * @return shortened string value 439 private String cutString(String stringToBeCut, int maxLength) { 440 if (!Strings.isNullOrEmpty(stringToBeCut) && stringToBeCut.length() > maxLength) { 442 "The String: {} is longer than allowed. Cut it to a length of {}.", 445 return StringUtils.left(stringToBeCut, maxLength); 447 return stringToBeCut; 451 * Sets the extracted birth date information from FHIR Patient resource to the new person record. 453 * @param birthDate the birth date in dateType from FHIR Patient resource 454 * @param person record of the person table in OMOP CDM for the processed FHIR Patient resource 456 private void setBirthDate( 457 LocalDateTime realBirthDate, LocalDateTime calculatedBirthDate, Person person) { 458 if (realBirthDate != null) { 459 person.setYearOfBirth(realBirthDate.getYear()); 460 person.setMonthOfBirth(realBirthDate.getMonthValue()); 461 person.setDayOfBirth(realBirthDate.getDayOfMonth()); 463 person.setYearOfBirth(calculatedBirthDate.getYear()); 468 * Extracts birth date information from FHIR Patient resource. 470 * @param srcPatient FHIR Patient resource 471 * @param patientLogicId logical id of the FHIR Patient resource 472 * @return birth date or the calculated birth date from FHIR Patient resource 474 private LocalDateTime extractBirthDate(Patient srcPatient) { 475 var birthDate = fhirPath.evaluateFirst(srcPatient, "Patient.birthDate", DateType.class); 476 if (birthDate.isPresent()) { 477 var birthDateElement = birthDate.get(); 478 if (!birthDateElement.hasValue() || birthDateElement.getValue() == null) { 481 return LocalDateTime.ofInstant( 482 birthDateElement.getValue().toInstant(), ZoneId.of("Europe/Berlin")); 489 * Calculate birth date from FHIR Patient resource. 491 * @param srcPatient FHIR Patient resource 492 * @return calculated birth date from FHIR Patient resource 494 private LocalDateTime extractCalculatedBirthDate( 495 Map<String, Extension> ageExtensionMap, PostProcessMap ageAtDiagnosis, String patientId) { 496 if (ageExtensionMap.isEmpty()) { 500 Age ageValue = extractAgeValue(ageExtensionMap); 501 var documentationDateTime = extractDocumentationDateTime(ageExtensionMap); 502 if (ageValue == null || documentationDateTime == null || ageValue.getCode() == null) { 506 var ageUnit = ageValue.getCode(); 507 var age = ageValue.getValue().intValue(); 509 ageAtDiagnosis.setDataOne(documentationDateTime.toString()); 510 ageAtDiagnosis.setDataTwo(age + ":" + ageValue.getUnit() + ":" + ageValue.getCode()); 514 return documentationDateTime.minusYears(age); 516 return documentationDateTime.minusMonths(age); 519 return documentationDateTime.minusDays(age); 521 log.warn("Unable to calculate [Birthdate] for [Patient]: {}.", patientId); 530 private Map<String, Extension> extractAgeExtension(Patient srcPatient) { 531 var ageExtension = srcPatient.getExtensionByUrl(fhirSystems.getAgeExtension()); 532 if (ageExtension == null) { 533 return Collections.emptyMap(); 536 var subExtensions = ageExtension.getExtension(); 538 return subExtensions.stream().collect(Collectors.toMap(Extension::getUrl, v -> v)); 542 * @param ageExtensionMap 545 private Age extractAgeValue(Map<String, Extension> ageExtensionMap) { 546 if (ageExtensionMap.isEmpty()) { 549 var ageExtensionAge = ageExtensionMap.get("age"); 550 if (ageExtensionAge == null) { 554 Age ageValue = (Age) ageExtensionAge.getValue(); 555 if (ageValue == null) { 562 * Extract the date of documentation from a FHIR Patient resource 564 * @param ageExtensionMap the extensions from ageExtention element in a FHIR Patient resource as a 566 * @return the date of documentation 568 private LocalDateTime extractDocumentationDateTime(Map<String, Extension> ageExtensionMap) { 569 if (ageExtensionMap.isEmpty()) { 572 var documentationDateTimeExtension = ageExtensionMap.get("dateTimeOfDocumentation"); 573 if (documentationDateTimeExtension == null) { 576 var extensionValue = (DateTimeType) documentationDateTimeExtension.getValue(); 577 if (extensionValue == null) { 580 return extensionValue 583 .atZone(ZoneId.of("Europe/Berlin")) 588 * Extract coding of ethnic group from a FHIR Patient resource 590 * @param srcPatient FHIR Patient resource 591 * @return coding of ethnic group 593 private Coding extractEthnicGroup(Patient srcPatient) { 594 var ethnicGroupExtension = srcPatient.getExtensionByUrl(fhirSystems.getEthnicGroupExtension()); 595 if (ethnicGroupExtension == null) { 598 return ethnicGroupExtension.getValue().castToCoding(ethnicGroupExtension.getValue()); 602 * Extracts gender information from FHIR Patient resource. 604 * @param srcPatient FHIR Patient resource 605 * @return the gender from FHIR Patient resource 607 private String getGender(Patient srcPatient) { 608 var genderElement = srcPatient.getGenderElement(); 609 if (genderElement.isEmpty()) { 612 var gender = checkDataAbsentReason.getValue(genderElement); 613 if (Strings.isNullOrEmpty(gender)) { 617 if (gender.equals("other") 618 && genderElement.hasExtension(fhirSystems.getGenderAmtlichDeExtension())) { 619 var administrativeGenderType = 620 genderElement.getExtensionByUrl(fhirSystems.getGenderAmtlichDeExtension()).getValue(); 621 var administrativeGender = administrativeGenderType.castToCoding(administrativeGenderType); 622 if (administrativeGender.hasCode()) { 623 return administrativeGender.getCode(); 629 * Mapping gender information from FHIR Patient resource to OMOP Concept. 631 * @param gender gender as String from FHIR Patient resource 632 * @return the gender_concept_id of the gender from FHIR Patient resource 634 private Integer getGenderConceptId(String gender) { 635 if (StringUtils.isBlank(gender)) { 636 return CONCEPT_GENDER_UNKNOWN; 638 var sourceToConcepMap = 639 findOmopConcepts.getCustomConcepts(gender, SOURCE_VOCABULARY_ID_GENDER, dbMappings); 640 return sourceToConcepMap.getTargetConceptId(); 644 * Extracts death information from the processed FHIR Patient resource and creates a new record of 645 * the post_process_map table in OMOP CDM. 647 * @param srcPatient FHIR Patient resource 648 * @param patientLogicId logical id of the FHIR Patient resource 649 * @param patientSourceIdentifier identifier of the FHIR Patient resource 650 * @return new record of the post_process_map table in OMOP CDM for death data from the processed 651 * FHIR Patient resource 653 private PostProcessMap setDeath( 654 Patient srcPatient, String patientLogicId, String patientSourceIdentifier) { 656 if (!srcPatient.hasDeceasedDateTimeType() 657 || srcPatient.getDeceasedDateTimeType() == null 658 || !srcPatient.getDeceasedDateTimeType().hasValue() 659 && srcPatient.getDeceasedDateTimeType().getValue() == null) { 664 new Timestamp(srcPatient.getDeceasedDateTimeType().getValue().getTime()).toLocalDateTime(); 666 return PostProcessMap.builder() 667 .dataOne(deathDateTime.toLocalDate().toString()) 668 .dataTwo(deathDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))) 669 .type(ResourceType.PATIENT.name()) 670 .omopId(Long.valueOf(CONCEPT_EHR_RECORD_STATUS_DECEASED)) 671 .omopTable(OmopModelWrapper.Tablename.DEATH.getTableName()) 672 .fhirLogicalId(patientLogicId) 673 .fhirIdentifier(patientSourceIdentifier) 678 * Delete FHIR Patient resources from OMOP CDM tables using fhir_logical_id and fhir_identifier 680 * @param patientLogicId logical id of the FHIR Patient resource 681 * @param patientSourceIdentifier identifier of the FHIR Patient resource 683 private void deleteExistingDeath(String patientLogicId, String patientSourceIdentifier) { 684 if (!Strings.isNullOrEmpty(patientLogicId)) { 685 patientService.deleteExistingDeathByFhirLogicalId(patientLogicId); 687 patientService.deleteExistingDeathByFhirIdentifier(patientSourceIdentifier); 691 private void deleteExistingCalculatedBirthYear( 692 String patientLogicId, String patientSourceIdentifier) { 693 if (!Strings.isNullOrEmpty(patientLogicId)) { 694 patientService.deleteExistingCalculatedBirthYearByFhirLogicalId(patientLogicId); 696 patientService.deleteExistingCalculatedBirthYearByFhirIdentifier(patientSourceIdentifier);