/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.xforms;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.kxml2.kdom.Document;
import org.kxml2.kdom.Element;
import org.openmrs.Patient;
import org.openmrs.PersonAddress;
import org.openmrs.PersonAttribute;
import org.openmrs.PersonAttributeType;
import org.openmrs.PersonName;
import org.openmrs.api.APIException;
import org.openmrs.api.context.Context;
import org.openmrs.module.xforms.util.XformsUtil;
/**
* Updates a patient object with demographic, address and attribute data from an encounter xform.
*/
public class XformObsPatientEdit {
public static Patient updatePatientDemographics(String patientId, String xml) throws Exception {
Patient patient = Context.getPatientService().getPatient(Integer.parseInt(patientId));
Document doc = XformBuilder.getDocument(xml);
updatePatientDemographics(patient, doc.getRootElement());
Context.getPatientService().savePatient(patient);
return patient;
}
public static void updatePatientDemographics(Patient patient, Element formNode) throws Exception {
Element patientNode = XformBuilder.getElement(formNode, "patient");
for (int i = 0; i < patientNode.getChildCount(); i++) {
if (patientNode.getType(i) != Element.ELEMENT)
continue;
Element child = (Element) patientNode.getChild(i);
String tableName = child.getAttributeValue(null, "openmrs_table");
String attributeValue = child.getAttributeValue(null, "openmrs_attribute");
String dataValue = XformBuilder.getTextValue(child);
//We intentionally do not want to use the xforms module for clearing
//patient demographic data. In such cases, they should use the official
//OpenMRS pages for editing such data. That will prevent the module from
//accidentally clearing data in case of a bug. We also do not update
//patient identifier because we have not yet written code to tell which
//identifier type we are dealing with.
if (StringUtils.isBlank(dataValue)) {
continue;
}
if ("person".equals(tableName) || "patient".equals(tableName)) {
updatePerson(patient, attributeValue, dataValue, child);
} else if ("person_name".equals(tableName) || "patient_name".equals(tableName)) {
updatePersonName(patient, attributeValue, dataValue, child);
} else if ("person_address".equals(tableName) || "patient_address".equals(tableName)) {
updatePersonAddress(patient, attributeValue, dataValue, child);
} else if ("person_attribute".equals(tableName) || "patient_attribute".equals(tableName)) {
updatePersonAttribute(patient, attributeValue, dataValue, child);
}
}
}
private static void updatePerson(Patient patient, String attributeValue, String dataValue, Element node)
throws Exception {
if (XformBuilder.NODE_GENDER.equals(attributeValue))
patient.setGender(dataValue);
else if (XformBuilder.NODE_BIRTHDATE_ESTIMATED.equals(attributeValue))
patient.setBirthdateEstimated("true".equals(dataValue));
else if (XformBuilder.NODE_BIRTHDATE.equals(attributeValue)) {
patient.setBirthdate(XformsUtil.fromSubmitString2Date(dataValue));
} else if (!"patient_id".equals(attributeValue))
throw new APIException("Cannot find person field with name = " + attributeValue);
//TODO do we need these two calls below?
//patient.setDateChanged(new Date());
//patient.setChangedBy(Context.getAuthenticatedUser());
}
private static void updatePersonName(Patient patient, String attributeValue, String dataValue, Element node)
throws Exception {
PersonName personName = patient.getPersonName();
if (XformBuilder.NODE_FAMILY_NAME.equals(attributeValue))
personName.setFamilyName(dataValue);
else if (XformBuilder.NODE_MIDDLE_NAME.equals(attributeValue))
personName.setMiddleName(dataValue);
else if (XformBuilder.NODE_GIVEN_NAME.equals(attributeValue))
personName.setGivenName(dataValue);
else if (XformBuilder.NODE_DEGREE.equals(attributeValue))
personName.setDegree(dataValue);
else if (XformBuilder.NODE_FAMILY_NAME2.equals(attributeValue))
personName.setFamilyName2(dataValue);
else if (XformBuilder.NODE_FAMILY_NAME_PREFIX.equals(attributeValue))
personName.setFamilyNamePrefix(dataValue);
else if (XformBuilder.NODE_FAMILY_NAME_SUFFIX.equals(attributeValue))
personName.setFamilyNameSuffix(dataValue);
else if (XformBuilder.NODE_PREFIX.equals(attributeValue))
personName.setPrefix(dataValue);
else
throw new APIException("Cannot find person name called = " + attributeValue);
}
private static void updatePersonAddress(Patient patient, String attributeValue, String dataValue, Element node) {
boolean addressIsNew = false;
PersonAddress pa = patient.getPersonAddress();
if (pa == null) {
pa = new PersonAddress();
pa.setDateCreated(new Date());
pa.setCreator(Context.getAuthenticatedUser());
pa.setPreferred(true);
addressIsNew = true;
}
if (XformBuilder.NODE_NAME_ADDRESS1.equals(attributeValue))
pa.setAddress1(dataValue);
else if (XformBuilder.NODE_NAME_ADDRESS2.equals(attributeValue))
pa.setAddress2(dataValue);
else if (XformBuilder.NODE_NAME_CITY_VILLAGE.equals(attributeValue))
pa.setCityVillage(dataValue);
else if (XformBuilder.NODE_NAME_STATE_PROVINCE.equals(attributeValue))
pa.setStateProvince(dataValue);
else if (XformBuilder.NODE_NAME_POSTAL_CODE.equals(attributeValue))
pa.setPostalCode(dataValue);
else if (XformBuilder.NODE_NAME_COUNTRY.equals(attributeValue))
pa.setCountry(dataValue);
else if (XformBuilder.NODE_NAME_LATITUDE.equals(attributeValue))
pa.setLatitude(dataValue);
else if (XformBuilder.NODE_NAME_LONGITUDE.equals(attributeValue))
pa.setLongitude(dataValue);
else if (XformBuilder.NODE_NAME_COUNTY_DISTRICT.equals(attributeValue))
pa.setCountyDistrict(dataValue);
else if (XformBuilder.NODE_NAME_NEIGHBORHOOD_CELL.equals(attributeValue))
pa.setNeighborhoodCell(dataValue);
else if (XformBuilder.NODE_NAME_REGION.equals(attributeValue))
pa.setRegion(dataValue);
else if (XformBuilder.NODE_NAME_SUBREGION.equals(attributeValue))
pa.setSubregion(dataValue);
else if (XformBuilder.NODE_NAME_TOWNSHIP_DIVISION.equals(attributeValue))
pa.setTownshipDivision(dataValue);
else
throw new APIException("Cannot find person address with name = " + attributeValue);
if (addressIsNew) {
if (pa.getAddress1() == null || pa.getAddress1().trim().length() == 0)
return;
patient.addAddress(pa);
}
}
private static void updatePersonAttribute(Patient patient, String attributeValue, String dataValue, Element node) {
PersonAttributeType personAttributeType = Context.getPersonService().getPersonAttributeType(
Integer.parseInt(attributeValue));
if (personAttributeType == null)
throw new APIException("Cannot find person attribute type with id = " + attributeValue);
PersonAttribute personAttribute = patient.getAttribute(personAttributeType);
if (personAttribute == null) {
personAttribute = new PersonAttribute();
personAttribute.setDateCreated(new Date());
personAttribute.setCreator(Context.getAuthenticatedUser());
personAttribute.setAttributeType(personAttributeType);
//addAttribute will not add if value is not set.
setPersonAttributeValue(dataValue, personAttribute, personAttributeType);
patient.addAttribute(personAttribute);
}
setPersonAttributeValue(dataValue, personAttribute, personAttributeType);
if (StringUtils.isBlank(dataValue)) {
patient.removeAttribute(personAttribute);
}
}
private static void setPersonAttributeValue(String dataValue, PersonAttribute personAttribute, PersonAttributeType personAttributeType) {
if ("org.openmrs.Concept".equals(personAttributeType.getFormat())) {
if (!dataValue.contains("^")) {
return; //not edited
}
dataValue = XformBuilder.getConceptId(dataValue).toString();
}
personAttribute.setValue(dataValue);
}
}