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-130:Adding support for the FHIR Media resource #328

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d785e97
FM2-130:Adding support for the FHIR Media resource
tendomart Feb 15, 2021
68e5bd4
Refining Media Complex Obs Handler
tendomart Feb 16, 2021
d508846
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Feb 16, 2021
39be2b1
Adding Search params , Service and Translator Layers
tendomart Feb 16, 2021
0aca54d
Doing more refining
tendomart Feb 18, 2021
b28be07
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Feb 18, 2021
53d8ff7
Implementing fhir media translator
tendomart Mar 30, 2021
ba5c351
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Mar 30, 2021
027f483
Doing cleaning
tendomart Mar 30, 2021
9fda48d
Removing duplicate code
tendomart Mar 30, 2021
5041fa2
Doing more refactorings and adding unit tests for Tranlator , service…
tendomart Mar 31, 2021
f4a4bed
Fine tuning Media search params doing other changes
tendomart Apr 1, 2021
1ba904b
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Apr 1, 2021
dd4b80e
Doing more refactoring
tendomart Apr 6, 2021
da7d841
Removing commented out lines
tendomart Apr 6, 2021
aea79f8
Doing more rectifications
tendomart Apr 7, 2021
b26adb3
Adding search params and FhirMediaDaoImplTest
tendomart Apr 12, 2021
d2625e6
Adding Media element translators
tendomart Apr 14, 2021
74103bc
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Apr 14, 2021
119fb76
Deleting unnecessary Media Translators
tendomart Apr 15, 2021
619d08b
Refining Translators
tendomart Apr 28, 2021
ee13f88
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Apr 28, 2021
86e2ca9
Refining MediaContentTranslator and Accompanying tests
tendomart Apr 30, 2021
a8c2605
Refactoring translators
tendomart May 5, 2021
3933575
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart May 5, 2021
93f2f45
Rectifying project build failure
tendomart May 7, 2021
9c843e8
Doing more fixes
tendomart May 27, 2021
bb9dbdf
Dealing with FhirMediaDaoImplTest failing tests
tendomart Jun 4, 2021
b6888be
Making FhirMediaDaoImpl CRUD methods work
tendomart Jun 7, 2021
6d2e407
Merge branch 'master' of https://github.com/openmrs/openmrs-module-fh…
tendomart Jun 7, 2021
5c79a15
Removing redundant code
tendomart Jun 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions api/src/main/java/org/openmrs/module/fhir2/FhirConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public class FhirConstants {

public static final String ENCOUNTER_CLASS_VALUE_SET_URI = HL7_FHIR_CODE_SYSTEM_PREFIX + "/v3-ActCode";

public static final String MEDIA_CREATED_DATE_TIME = "media.created.date.time";

@Value("${project.version}")
public static String OPENMRS_FHIR_SERVER_VERSION;

Expand Down Expand Up @@ -296,4 +298,25 @@ public class FhirConstants {
public static final String REVERSE_INCLUDE_SEARCH_HANDLER = "_revinclude.search.handler";

public static final String CONDITION_OBSERVATION_CONCEPT_UUID = "1284AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

public static final String FHIR_MEDIA = "media";

public static final String MEDIA_STATUS = "media.status";

public static final String MEDIA_TYPE = "media.type";

public static final String MEDIA_SUBJECT = "media.subject";

public static final String MEDIA_ENCOUNTER_REFERENCE = "media.encounter.reference";

public static final String MEDIA_CREATED_ON = "media.created.on";

public static final String MEDIA_CONTENT_TYPE = "media.content.type";

public static final String CONTENT_DATA = "content.data";

public static final String CONTENT_TITLE = "content.title";

public static final String CONTENT_DATE_OF_CREATION = "content.creation";

tendomart marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 javax.annotation.Nonnull;

import java.util.HashSet;

import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.ReferenceAndListParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.TokenAndListParam;
import org.hl7.fhir.r4.model.Observation;

public interface FhirMediaService extends FhirService<Observation> {

Observation get(@Nonnull String uuid);
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be unnecessary as it's already defined by the parent interface.


IBundleProvider searchForMedia(TokenAndListParam status, TokenAndListParam type, ReferenceAndListParam subject,
ReferenceAndListParam encounterReference, DateRangeParam createdDateTime, TokenAndListParam contentType,
StringAndListParam contentDataType, StringAndListParam contentTitle, DateRangeParam contentCreated,
DateRangeParam lastUpdated, HashSet<Include> includes, HashSet<Include> revIncludes, SortSpec sort);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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 javax.annotation.Nonnull;

import java.util.List;

import org.openmrs.Obs;
import org.openmrs.annotation.Authorized;
import org.openmrs.module.fhir2.api.search.param.SearchParameterMap;
import org.openmrs.util.PrivilegeConstants;

public interface FhirMediaDao extends FhirDao<Obs> {

@Override
@Authorized(PrivilegeConstants.GET_OBS)
Obs get(@Nonnull String uuid);

@Override
@Authorized(PrivilegeConstants.ADD_OBS)
Obs createOrUpdate(@Nonnull Obs newEntry);

@Override
@Authorized(PrivilegeConstants.DELETE_OBS)
Obs delete(@Nonnull String uuid);

@Override
@Authorized(PrivilegeConstants.GET_OBS)
List<String> getSearchResultUuids(@Nonnull SearchParameterMap theParams);

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

import lombok.AccessLevel;
import lombok.Setter;
import org.hibernate.Criteria;
import org.openmrs.Obs;
import org.openmrs.api.APIException;
import org.openmrs.module.fhir2.FhirConstants;
import org.openmrs.module.fhir2.api.dao.FhirMediaDao;
import org.openmrs.module.fhir2.api.search.param.SearchParameterMap;
import org.openmrs.obs.ComplexObsHandler;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PACKAGE)
public class FhirMediaDaoImpl extends BaseFhirDao<Obs> implements FhirMediaDao, ComplexObsHandler {
Copy link
Member

Choose a reason for hiding this comment

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

This class definitely shouldn't be a ComplexObsHandler. That interface is only for classes which implement a specific type of ComplexObs, e.g., ImageHandler or PdfHandler or something like that.


@Override
protected void setupSearchParams(Criteria criteria, SearchParameterMap theParams) {
theParams.getParameters().forEach(entry -> {
Copy link
Member

Choose a reason for hiding this comment

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

Here, we'll want to ensure that we're only searching ComplexObs and not just any Obs. This looks like it could be done as something like:

if (lacksAlias(criteria, "c")) {
	criteria.createAlias("concept", "c");
}

if (lacksAlias(criteria, "cdt")) {
    criteria.createAlias("c.datatype", "cdt");
}

criteria.add(eq("cdt.hl7_abbreviation", "ED"));

switch (entry.getKey()) {
case FhirConstants.MEDIA_STATUS:
entry.getValue().forEach(param -> handleStatus(criteria, entry.getValue()));
break;
case FhirConstants.MEDIA_TYPE:
entry.getValue().forEach(param -> handleMediaType(criteria, entry.getValue()));
break;
case FhirConstants.MEDIA_SUBJECT:
entry.getValue().forEach(param -> handleMediaSubject(criteria, entry.getValue()));
break;
case FhirConstants.MEDIA_ENCOUNTER_REFERENCE:
entry.getValue().forEach(param -> handleMediaEncounterReference(criteria, entry.getValue()));
break;
case FhirConstants.MEDIA_CREATED_DATE_TIME:
entry.getValue().forEach(param -> handleMediaCreatedDate(criteria, entry.getValue()));
break;
case FhirConstants.MEDIA_CONTENT_TYPE:
entry.getValue().forEach(param -> handleMediaContentType(criteria, entry.getValue()));
break;
case FhirConstants.CONTENT_DATA:
entry.getValue().forEach(param -> handleContentData(criteria, entry.getValue()));
break;
case FhirConstants.CONTENT_TITLE:
entry.getValue().forEach(param -> handleContentTitle(criteria, entry.getValue()));
break;
case FhirConstants.CONTENT_DATE_OF_CREATION:
entry.getValue().forEach(param -> handleContentDateOfCreation(criteria, entry.getValue()));
break;

}
});

}

@Override
public Obs saveObs(Obs obs) throws APIException {
return null;
}

@Override
public Obs getObs(Obs obs, String s) {
return null;
}

@Override
public boolean purgeComplexData(Obs obs) {
return false;
}

@Override
public String[] getSupportedViews() {
return new String[0];
}

@Override
public boolean supportsView(String s) {
return false;
}

@Override
public Obs createOrUpdate(@Nonnull Obs newEntry) {
return super.createOrUpdate(newEntry);
}

@Override
public Obs delete(@Nonnull String uuid) {
return super.delete(uuid);
}

@Override
public List<String> getSearchResultUuids(@Nonnull SearchParameterMap theParams) {
return super.getSearchResultUuids(theParams);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* 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.handler;

import lombok.AccessLevel;
import lombok.Setter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Obs;
import org.openmrs.Patient;
import org.openmrs.api.APIException;
import org.openmrs.api.PatientService;
import org.openmrs.api.context.Context;
import org.openmrs.customdatatype.CustomDatatypeHandler;
import org.openmrs.obs.ComplexData;
import org.openmrs.obs.ComplexObsHandler;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Setter(AccessLevel.PUBLIC)
@Order(Ordered.LOWEST_PRECEDENCE)
public class FhirMediaComplexObsHandler implements ComplexObsHandler, CustomDatatypeHandler {
Copy link
Member

Choose a reason for hiding this comment

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

We really, really don't need a FHIR-specific ComplexObsHandler we can rely on the ObsService to populate the ComplexObs data (if any)


public static final Log log = LogFactory.getLog(Obs.class);

public static final String HANDLER_TYPE = "MediaHandler";

public FhirMediaComplexObsHandler() {
super();
}

@Override
public Obs saveObs(Obs obs) throws APIException {
PatientService patientService = Context.getPatientService();
Patient patient = patientService.getPatient(Integer.parseInt(obs.getValueComplex()));
if (patient == null) {
throw new APIException("Cannot save complex obs where obsId=" + obs.getObsId() + "Desired Patient id :"
+ Integer.parseInt(obs.getValueComplex()) + "cannot be found");
}

obs.setValueComplex(obs.getComplexData().getTitle());
obs.setComplexData(null);
return obs;
}

@Override
public Obs getObs(Obs obs, String s) {
Patient patient = null;
PatientService ps = Context.getPatientService();
String contentType = obs.getComplexData().getTitle();
String key = obs.getUuid();

if (key != null && !StringUtils.isEmpty(key)) {
patient = ps.getPatient(Integer.parseInt(key));
}

if (patient != null) {
ComplexData complexData = new ComplexData(contentType, key);
obs.setComplexData(complexData);
} else {
log.info("Warning : specified patient cannot be found - returning no ComplexData for " + obs.getObsId());
}

return obs;
}

@Override
public boolean purgeComplexData(Obs obs) {
String contentType = obs.getComplexData().getTitle();
String key = obs.getUuid();

if (key != null) {
ComplexData complexData = new ComplexData(contentType, key);
obs.setComplexData(complexData);
Context.getObsService().getHandler(obs).purgeComplexData(obs);
} else {
log.info("Sorry There is no such an observation with " + key);
}
return true;
}

@Override
public String[] getSupportedViews() {
return new String[0];
}

@Override
public boolean supportsView(String s) {
return false;
}

@Override
public void setHandlerConfiguration(String s) {

}

/**
* Gets the handler type for each registered handler.
*
* @return the handler type
*/
public String getHandlerType() {
return FhirMediaComplexObsHandler.HANDLER_TYPE;
}
}
Loading