package edu.gatech.i3l.fhir.dstu2.entities; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import org.hibernate.envers.Audited; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.dstu2.composite.AddressDt; import ca.uhn.fhir.model.dstu2.composite.BoundCodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.ContactPointDt; import ca.uhn.fhir.model.dstu2.composite.HumanNameDt; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.valueset.ContactPointSystemEnum; import ca.uhn.fhir.model.dstu2.valueset.ContactPointUseEnum; import ca.uhn.fhir.model.dstu2.valueset.MaritalStatusCodesEnum; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.StringDt; import edu.gatech.i3l.fhir.jpa.entity.IResourceEntity; import edu.gatech.i3l.omop.mapping.OmopConceptMapping; /** * This class adds some properties to the Omop data model Person, in order to provide * all the data specified for FHIR. * @author Ismael Sarmento */ @Entity @Table(name="f_person") @PrimaryKeyJoinColumn(name="person_id") @Audited public class PersonComplement extends Person{ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PersonComplement.class); @Column(name="family_name") private String familyName; @Column(name="given1_name") private String givenName1; @Column(name="given2_name") private String givenName2; @Column(name="prefix_name") private String prefixName; @Column(name="suffix_name") private String suffixName; @Column(name="preferred_language") private String preferredLanguage; @Column(name="ssn") private String ssn; @Column(name="maritalstatus") private String maritalStatus; @Column(name="active") private Short active; @Column(name="contact_point1") String contactPoint1; @Column(name="contact_point2") String contactPoint2; @Column(name="contact_point3") String contactPoint3; public PersonComplement() { super(); } public String getFamilyName() { return familyName; } public void setFamilyName(String familyName) { this.familyName = familyName; } public String getGivenName1() { return givenName1; } public void setGivenName1(String givenName1) { this.givenName1 = givenName1; } public String getGivenName2() { return givenName2; } public void setGivenName2(String givenName2) { this.givenName2 = givenName2; } public String getPrefixName() { return prefixName; } public void setPrefixName(String prefixName) { this.prefixName = prefixName; } public String getSuffixName() { return suffixName; } public void setSuffixName(String suffixName) { this.suffixName = suffixName; } public String getPreferredLanguage() { return preferredLanguage; } public void setPreferredLanguage(String preferredLanguage) { this.preferredLanguage = preferredLanguage; } public String getSsn() { return ssn; } public void setSsn(String ssn) { this.ssn = ssn; } public String getMaritalStatus() { return maritalStatus; } public void setMaritalStatus(String maritalStatus) { this.maritalStatus = maritalStatus; } public Short getActive() { return active; } public void setActive(Short active) { this.active = active; } public String getContactPoint1() { return contactPoint1; } public void setContactPoint1(String contactPoint1) { this.contactPoint1 = contactPoint1; } public String getContactPoint2() { return contactPoint2; } public void setContactPoint2(String contactPoint2) { this.contactPoint2 = contactPoint2; } public String getContactPoint3() { return contactPoint3; } public void setContactPoint3(String contactPoint3) { this.contactPoint3 = contactPoint3; } @Override public Patient getRelatedResource() { Patient patient = (Patient) super.getRelatedResource(); patient.addName().addFamily(this.familyName).addGiven(this.givenName1); if(this.givenName2 != null) patient.getName().get(0).addGiven(this.givenName2); // short active = this.active != null ? this.active : 0; if (this.active == null || this.active == 0) patient.setActive(false); else patient.setActive(true); if (this.maritalStatus != null && !this.maritalStatus.isEmpty()) { patient.setMaritalStatus(MaritalStatusCodesEnum.valueOf(this.maritalStatus.toUpperCase())); } List<ContactPointDt> contactPoints = new ArrayList<ContactPointDt>(); if (this.contactPoint1 != null && !this.contactPoint1.isEmpty()) { String[] contactInfo = this.contactPoint1.split(":"); if (contactInfo.length == 3) { ContactPointDt contactPoint = new ContactPointDt(); contactPoint.setSystem(ContactPointSystemEnum.valueOf(contactInfo[0].toUpperCase())); contactPoint.setUse(ContactPointUseEnum.valueOf(contactInfo[1].toUpperCase())); contactPoint.setValue(contactInfo[2]); contactPoints.add(contactPoint); } } if (this.contactPoint2 != null && !this.contactPoint2.isEmpty()) { String[] contactInfo = this.contactPoint2.split(":"); if (contactInfo.length == 3) { ContactPointDt contactPoint = new ContactPointDt(); contactPoint.setSystem(ContactPointSystemEnum.valueOf(contactInfo[0].toUpperCase())); contactPoint.setUse(ContactPointUseEnum.valueOf(contactInfo[1].toUpperCase())); contactPoint.setValue(contactInfo[2]); contactPoints.add(contactPoint); } } if (this.contactPoint3 != null && !this.contactPoint3.isEmpty()) { String[] contactInfo = this.contactPoint3.split(":"); if (contactInfo.length == 3) { ContactPointDt contactPoint = new ContactPointDt(); contactPoint.setSystem(ContactPointSystemEnum.valueOf(contactInfo[0].toUpperCase())); contactPoint.setUse(ContactPointUseEnum.valueOf(contactInfo[1].toUpperCase())); contactPoint.setValue(contactInfo[2]); contactPoints.add(contactPoint); } } patient.setTelecom(contactPoints); //MARITAL STATUS // MaritalStatusCodesEnum[] values = MaritalStatusCodesEnum.values(); // for (int i = 0; i < values.length; i++) { // if(values[i].equals(this.maritalStatus.getName())){ // patient.setMaritalStatus(values[i]); // break; // } // } // or patient.setMaritalStatus(MaritalStatusCodesEnum.valueOf("")); return patient; } /** * @notice In Fhir model, {@link Patient} has a collection of names, while in this extension table, {@link PersonComplement}, * there is only one name for each {@link Person}. */ @Override public IResourceEntity constructEntityFromResource(IResource resource) { super.constructEntityFromResource(resource); if(resource instanceof Patient){ Patient patient = (Patient)resource; Iterator<HumanNameDt> iterator = patient.getName().iterator(); //while(iterator.hasNext()){ if(iterator.hasNext()){ HumanNameDt next = iterator.next(); this.givenName1 = next.getGiven().get(0).getValue();//the next method was not advancing to the next element, then the need to use the get(index) method if(next.getGiven().size() > 1) //TODO add unit tests, to assure this won't be changed to hasNext this.givenName2 = next.getGiven().get(1).getValue(); Iterator<StringDt> family = next.getFamily().iterator(); this.familyName = ""; while(family.hasNext()){ if (this.familyName == "") { this.familyName = this.familyName.concat(family.next().getValue()); } else { this.familyName = this.familyName.concat(" "+family.next().getValue()); } } if(next.getSuffix().iterator().hasNext()) this.suffixName = next.getSuffix().iterator().next().getValue(); if(next.getPrefix().iterator().hasNext()) this.prefixName = next.getPrefix().iterator().next().getValue(); } //} IdDt myID = patient.getId(); if (myID != null && myID.getIdPartAsLong() != null && myID.getIdPart() != null) { PersonComplement person = (PersonComplement) OmopConceptMapping.getInstance().loadEntityById(PersonComplement.class, myID.getIdPartAsLong()); if (person != null) { this.setId(myID.getIdPartAsLong()); } else { person = (PersonComplement) OmopConceptMapping.getInstance().loadEntityBySource(PersonComplement.class, "PersonComplement", "personSourceValue", myID.getIdPart()); if (person != null) { this.setId(person.getId()); } this.setPersonSourceValue(myID.getIdPart()); } } else { // We have no Patient ID. However, we could have a matching patient. Compare // name and address. System.out.println("No Patient ID provided"); List<AddressDt> addresses = patient.getAddress(); AddressDt newAddress = null; if (addresses.size() > 0) { newAddress = addresses.get(0); } Long existingID = OmopConceptMapping.getInstance().getPersonByNameAndLocation(this, Location.searchByAddressDt(newAddress)); System.out.println("Patient Exists with PID="+existingID); if (existingID != null) { this.setId(existingID); } else { //TODO: Add this to OmopConceptMapping class. Race Concept is required in OMOP v5 // But, FHIR Patient does not have race data element Concept race = new Concept(); race.setId(8552L); this.setRaceConcept(race); // Ethnicity is not available in FHIR resource. Set to 0L as there is no unknown ethnicity. Concept ethnicity = new Concept(); ethnicity.setId(0L); this.setEthnicityConcept(ethnicity); } } if (patient.getActive()) this.setActive((short)1); else this.setActive((short)0); BoundCodeableConceptDt<MaritalStatusCodesEnum> maritalStat = patient.getMaritalStatus(); if (maritalStat != null) { Set<MaritalStatusCodesEnum> maritalEnum = maritalStat.getValueAsEnum(); if (maritalEnum != null) { for (MaritalStatusCodesEnum myCode : maritalEnum) { System.out.println("MARITAL STATUS:"+myCode.name()); this.setMaritalStatus(myCode.name()); break; } } } // Get contact information. List<ContactPointDt> contactPoints = patient.getTelecom(); if (contactPoints.size() > 0) { ContactPointDt contactPoint = contactPoints.get(0); String system = contactPoint.getSystem(); String use = contactPoint.getUse(); String value = contactPoint.getValue(); this.setContactPoint1(system+":"+use+":"+value); } if (contactPoints.size() > 1) { ContactPointDt contactPoint = contactPoints.get(1); String system = contactPoint.getSystem(); String use = contactPoint.getUse(); String value = contactPoint.getValue(); this.setContactPoint2(system+":"+use+":"+value); } if (contactPoints.size() > 2) { ContactPointDt contactPoint = contactPoints.get(2); String system = contactPoint.getSystem(); String use = contactPoint.getUse(); String value = contactPoint.getValue(); this.setContactPoint3(system+":"+use+":"+value); } //MARITAL STATUS // this.maritalStatus.setId(OmopConceptMapping.getInstance().get(patient.getMaritalStatus().getText(), OmopConceptMapping.MARITAL_STATUS)); } else { ourLog.error("There was not possible to construct the entity ? using the resource ?. It should be used the resource ?.", this.getClass().getSimpleName(), resource.getResourceName(), getResourceType()); } return this; } public String getNameAsSingleString() { String name=""; if (this.givenName1 != null && !this.givenName1.isEmpty()) name = this.givenName1; if (this.givenName2 != null && !this.givenName2.isEmpty()) name = name+" "+this.givenName2; if (this.familyName != null && !this.familyName.isEmpty()) name = name+" "+this.familyName; return name; } public void setNameFromString(String fullName) { if (fullName == null || fullName.isEmpty()) return; String[] names = fullName.trim().split(",", 2); if (names.length > 1) { this.setFamilyName(names[0]); String[] subNames = names[1].trim().split(" ", 2); if (subNames.length > 1) { this.setGivenName1(subNames[0]); this.setGivenName2(subNames[1]); } else { this.setGivenName1(subNames[0]); } } else { String[] subNames = names[0].trim().split(" ", 2); if (subNames.length > 1) { this.setGivenName1(subNames[0]); this.setFamilyName(subNames[1]); } else { this.setFamilyName(subNames[0]); } } } public static PersonComplement searchAndUpdate(ResourceReferenceDt patientResourceRef) { if (patientResourceRef == null) return null; Long patientRef = patientResourceRef.getReference().getIdPartAsLong(); PersonComplement person = (PersonComplement) OmopConceptMapping.getInstance() .loadEntityById(PersonComplement.class, patientRef); if (person != null) { return person; } else { // See if we have already received this. person = (PersonComplement) OmopConceptMapping.getInstance() .loadEntityBySource(PersonComplement.class, "PersonComplement", "personSourceValue", patientRef.toString()); if (person != null) { return person; } else { person = new PersonComplement(); person.setNameFromString(patientResourceRef.getDisplay().toString()); person.setPersonSourceValue(patientRef.toString()); return person; } } } }