Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FM2-606: Mapping ContactPoints to OpenMRS #517

Merged
merged 5 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.fhir2.api;

import java.util.Optional;

import org.openmrs.PersonAttributeType;
import org.openmrs.attribute.BaseAttributeType;
import org.openmrs.module.fhir2.model.FhirContactPointMap;

public interface FhirContactPointMapService {

Optional<FhirContactPointMap> getFhirContactPointMapForPersonAttributeType(PersonAttributeType attributeType);

Optional<FhirContactPointMap> getFhirContactPointMapForAttributeType(BaseAttributeType<?> attributeType);

FhirContactPointMap saveFhirContactPointMap(FhirContactPointMap contactPointMap);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.fhir2.api.dao;

import java.util.Optional;

import org.openmrs.PersonAttributeType;
import org.openmrs.attribute.BaseAttributeType;
import org.openmrs.module.fhir2.model.FhirContactPointMap;

public interface FhirContactPointMapDao {

Optional<FhirContactPointMap> getFhirContactPointMapForPersonAttributeType(PersonAttributeType attributeType);

Optional<FhirContactPointMap> getFhirContactPointMapForAttributeType(BaseAttributeType<?> attributeType);

FhirContactPointMap saveFhirContactPointMap(FhirContactPointMap contactPointMap);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* 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.fhir2.api.dao.impl;

import javax.annotation.Nonnull;

import java.util.Optional;

import lombok.AccessLevel;
import lombok.Setter;
import org.apache.commons.lang.StringUtils;
import org.hibernate.SessionFactory;
import org.openmrs.LocationAttributeType;
import org.openmrs.PersonAttributeType;
import org.openmrs.ProviderAttributeType;
import org.openmrs.attribute.BaseAttributeType;
import org.openmrs.module.fhir2.api.dao.FhirContactPointMapDao;
import org.openmrs.module.fhir2.model.FhirContactPointMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PACKAGE)
public class FhirContactPointMapDaoImpl implements FhirContactPointMapDao {

@Autowired
@Qualifier("sessionFactory")
private SessionFactory sessionFactory;

@Override
public Optional<FhirContactPointMap> getFhirContactPointMapForPersonAttributeType(
@Nonnull PersonAttributeType attributeType) {
if (attributeType == null) {
return Optional.empty();

Check warning on line 42 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L42

Added line #L42 was not covered by tests
}

return Optional.ofNullable((FhirContactPointMap) sessionFactory.getCurrentSession().createQuery(
"from FhirContactPointMap fcp where fcp.attributeTypeDomain = 'person' and fcp.attributeTypeId = :attribute_type_id")
.setParameter("attribute_type_id", attributeType.getId()).uniqueResult());
}

@Override
public Optional<FhirContactPointMap> getFhirContactPointMapForAttributeType(
@Nonnull BaseAttributeType<?> attributeType) {
if (attributeType == null) {
return Optional.empty();

Check warning on line 54 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L54

Added line #L54 was not covered by tests
}

String attributeTypeClassName = attributeType.getClass().getSimpleName();
if (attributeTypeClassName == null || "".equals(attributeTypeClassName)
|| !attributeTypeClassName.endsWith("AttributeType")) {
return Optional.empty();

Check warning on line 60 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L60

Added line #L60 was not covered by tests
}

String attributeTypeDomain = StringUtils.removeEnd(attributeTypeClassName.toLowerCase(), "attributetype");
if (attributeType instanceof LocationAttributeType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a better implementation here (because we can support more than just hard-coded values):

String attributeTypeClassName = attributeType.getClass().getSimpleName();
if (attributeTypeClassName == null || "".equals(attributeTypeClassName) || !attributeTypeClassName.endsWith("AttributeType")) {
	return Optional.empty();
}

String attributeTypeDomain = StringUtils.removeEnd(attributeTypeClassName.toLowerCase(), "attributetype");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

attributeTypeDomain = "location";
} else if (attributeType instanceof ProviderAttributeType) {
attributeTypeDomain = "provider";
}

if (attributeTypeDomain == null) {
return Optional.empty();

Check warning on line 71 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L71

Added line #L71 was not covered by tests
}

return Optional.ofNullable((FhirContactPointMap) sessionFactory.getCurrentSession().createQuery(
"from FhirContactPointMap fcp where fcp.attributeTypeDomain = :attribute_type_domain and fcp.attributeTypeId = :attribute_type_id")
.setParameter("attribute_type_domain", attributeTypeDomain)
.setParameter("attribute_type_id", attributeType.getId()).uniqueResult());
}

@Override
public FhirContactPointMap saveFhirContactPointMap(@Nonnull FhirContactPointMap contactPointMap) {
FhirContactPointMap existingContactPointMap = (FhirContactPointMap) sessionFactory.getCurrentSession().createQuery(

Check warning on line 82 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L82

Added line #L82 was not covered by tests
"from FhirContactPointMap fcp where fcp.attributeTypeDomain = :attribute_type_domain and fcp.attributeTypeId = :attribute_type_id")
.setParameter("attribute_type_domain", contactPointMap.getAttributeTypeDomain())
.setParameter("attribute_type_id", contactPointMap.getAttributeTypeId()).uniqueResult();

Check warning on line 85 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L84-L85

Added lines #L84 - L85 were not covered by tests

if (existingContactPointMap != null) {
existingContactPointMap.setSystem(contactPointMap.getSystem());
existingContactPointMap.setUse(contactPointMap.getUse());
existingContactPointMap.setRank(contactPointMap.getRank());
sessionFactory.getCurrentSession().merge(existingContactPointMap);
return existingContactPointMap;

Check warning on line 92 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L88-L92

Added lines #L88 - L92 were not covered by tests
} else {
sessionFactory.getCurrentSession().saveOrUpdate(contactPointMap);
return contactPointMap;

Check warning on line 95 in api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/dao/impl/FhirContactPointMapDaoImpl.java#L94-L95

Added lines #L94 - L95 were not covered by tests
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.fhir2.api.impl;

import java.util.Optional;

import lombok.AccessLevel;
import lombok.Setter;
import org.openmrs.PersonAttributeType;
import org.openmrs.attribute.BaseAttributeType;
import org.openmrs.module.fhir2.api.FhirContactPointMapService;
import org.openmrs.module.fhir2.api.dao.FhirContactPointMapDao;
import org.openmrs.module.fhir2.model.FhirContactPointMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@Transactional
@Setter(AccessLevel.PACKAGE)
public class FhirContactPointMapServiceImpl implements FhirContactPointMapService {

@Autowired
private FhirContactPointMapDao dao;

@Transactional(readOnly = true)
@Override
public Optional<FhirContactPointMap> getFhirContactPointMapForPersonAttributeType(PersonAttributeType attributeType) {
return dao.getFhirContactPointMapForPersonAttributeType(attributeType);
}

@Transactional(readOnly = true)
@Override
public Optional<FhirContactPointMap> getFhirContactPointMapForAttributeType(BaseAttributeType<?> attributeType) {
return dao.getFhirContactPointMapForAttributeType(attributeType);
}

@Override
public FhirContactPointMap saveFhirContactPointMap(FhirContactPointMap contactPointMap) {
return dao.saveFhirContactPointMap(contactPointMap);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@

import javax.annotation.Nonnull;

import ca.uhn.fhir.rest.api.PatchTypeEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenParam;
Expand All @@ -41,8 +39,6 @@
import org.openmrs.module.fhir2.api.translators.OpenmrsFhirUpdatableTranslator;
import org.openmrs.module.fhir2.api.translators.UpdatableOpenmrsTranslator;
import org.openmrs.module.fhir2.api.util.ImmunizationObsGroupHelper;
import org.openmrs.module.fhir2.api.util.JsonPatchUtils;
import org.openmrs.module.fhir2.api.util.XmlPatchUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package org.openmrs.module.fhir2.api.translators.impl;

import static org.openmrs.module.fhir2.api.util.GeneralUtils.isVoidedOrRetired;

import javax.annotation.Nonnull;

import lombok.AccessLevel;
Expand All @@ -21,9 +23,13 @@
import org.openmrs.api.LocationService;
import org.openmrs.api.PersonService;
import org.openmrs.api.ProviderService;
import org.openmrs.attribute.BaseAttribute;
import org.openmrs.attribute.BaseAttributeType;
import org.openmrs.module.fhir2.FhirConstants;
import org.openmrs.module.fhir2.api.FhirContactPointMapService;
import org.openmrs.module.fhir2.api.FhirGlobalPropertyService;
import org.openmrs.module.fhir2.api.translators.TelecomTranslator;
import org.openmrs.module.fhir2.model.FhirContactPointMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand All @@ -40,6 +46,9 @@ public class TelecomTranslatorImpl implements TelecomTranslator<BaseOpenmrsData>
@Autowired
private ProviderService providerService;

@Autowired
private FhirContactPointMapService fhirContactPointMapService;

@Autowired
private FhirGlobalPropertyService globalPropertyService;

Expand All @@ -54,6 +63,7 @@ public BaseOpenmrsData toOpenmrsType(@Nonnull BaseOpenmrsData attribute, @Nonnul
if (contactPoint.hasId()) {
personAttribute.setUuid(contactPoint.getId());
}

personAttribute.setValue(contactPoint.getValue());
personAttribute.setAttributeType(personService.getPersonAttributeTypeByUuid(
globalPropertyService.getGlobalProperty(FhirConstants.PERSON_CONTACT_POINT_ATTRIBUTE_TYPE)));
Expand All @@ -80,7 +90,7 @@ public BaseOpenmrsData toOpenmrsType(@Nonnull BaseOpenmrsData attribute, @Nonnul

@Override
public ContactPoint toFhirResource(@Nonnull BaseOpenmrsData attribute) {
if (attribute == null || attribute.getVoided()) {
if (attribute == null || isVoidedOrRetired(attribute)) {
return null;
}

Expand All @@ -90,6 +100,10 @@ public ContactPoint toFhirResource(@Nonnull BaseOpenmrsData attribute) {
PersonAttribute personAttribute = (PersonAttribute) attribute;
contactPoint.setId(personAttribute.getUuid());
contactPoint.setValue(personAttribute.getValue());

fhirContactPointMapService
.getFhirContactPointMapForPersonAttributeType(((PersonAttribute) attribute).getAttributeType())
.ifPresent(contactPointMap -> mapContactPoint(contactPoint, contactPointMap));
} else if (attribute instanceof LocationAttribute) {
LocationAttribute locationAttribute = (LocationAttribute) attribute;
contactPoint.setId(locationAttribute.getUuid());
Expand All @@ -100,6 +114,21 @@ public ContactPoint toFhirResource(@Nonnull BaseOpenmrsData attribute) {
contactPoint.setValue(providerAttribute.getValue().toString());
}

if (attribute instanceof BaseAttribute) {
fhirContactPointMapService
.getFhirContactPointMapForAttributeType(
(BaseAttributeType<?>) ((BaseAttribute<?, ?>) attribute).getAttributeType())
.ifPresent(contactPointMap -> mapContactPoint(contactPoint, contactPointMap));
}

return contactPoint;
}

private static void mapContactPoint(ContactPoint contactPoint, FhirContactPointMap contactPointMap) {
contactPoint.setSystem(contactPointMap.getSystem());
contactPoint.setUse(contactPointMap.getUse());
if (contactPointMap.getRank() != null) {
contactPoint.setRank(contactPointMap.getRank());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
import java.util.Objects;

import lombok.extern.slf4j.Slf4j;
import org.openmrs.OpenmrsObject;
import org.openmrs.Retireable;
import org.openmrs.Voidable;

@Slf4j
public final class GeneralUtils {
Expand All @@ -37,4 +40,14 @@
throws IOException {
return inputStreamToString(Objects.requireNonNull(cl.getResourceAsStream(resource)), charset);
}

public static boolean isVoidedOrRetired(OpenmrsObject object) {
if (object instanceof Retireable) {
return ((Retireable) object).getRetired();

Check warning on line 46 in api/src/main/java/org/openmrs/module/fhir2/api/util/GeneralUtils.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/util/GeneralUtils.java#L46

Added line #L46 was not covered by tests
} else if (object instanceof Voidable) {
return ((Voidable) object).getVoided();
}

return false;

Check warning on line 51 in api/src/main/java/org/openmrs/module/fhir2/api/util/GeneralUtils.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/openmrs/module/fhir2/api/util/GeneralUtils.java#L51

Added line #L51 was not covered by tests
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.fhir2.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.r4.model.ContactPoint.ContactPointUse;
import org.openmrs.BaseOpenmrsData;

@Data
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
@Entity
@Table(name = "fhir_contact_point_map")
@NoArgsConstructor
public class FhirContactPointMap extends BaseOpenmrsData {

private static final long serialVersionUID = 1742113L;

@EqualsAndHashCode.Include
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "fhir_contact_point_map_id")
private Integer id;

@Column(name = "attribute_type_domain", nullable = false)
private String attributeTypeDomain;

@Column(name = "attribute_type_id", nullable = false)
private Integer attributeTypeId;

@Enumerated(EnumType.STRING)
@Column(length = 50)
private ContactPointSystem system;

@Enumerated(EnumType.STRING)
@Column(length = 50)
private ContactPointUse use;

private Integer rank;
}