Skip to content

Commit

Permalink
ATT-52: Attachment REST endpoint should send file name and comment (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibacher authored Jan 30, 2024
1 parent 6a80d58 commit 613f3b0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

/**
* Attachment represents all the parts of a complex obs that make an "attachment".
*
*
* @author Mekom Solutions
*/
public class Attachment extends BaseOpenmrsData implements java.io.Serializable {
Expand All @@ -24,6 +24,8 @@ public class Attachment extends BaseOpenmrsData implements java.io.Serializable

protected String comment = "";

protected String filename = "";

protected String bytesMimeType = null;

protected ContentFamily bytesContentFamily = null;
Expand Down Expand Up @@ -51,6 +53,22 @@ public Attachment(Obs obs) {

setDateTime(obs.getObsDatetime());
setComment(obs.getComment());

// Chomp the UUID off the end of the obs if any
String filename = new ValueComplex(obs.getValueComplex()).getFileName();
if (filename != null) {
int uuidIdx = filename.lastIndexOf("_" + obs.getUuid());
if (uuidIdx > 0) {
int extIdx = filename.lastIndexOf(".");
String extension = "";
if (extIdx > 0 && extIdx > uuidIdx) {
extension = filename.substring(extIdx);
}
filename = filename.substring(0, uuidIdx) + extension;
}
}

setFilename(filename);
setComplexData(obs.getComplexData());
}

Expand All @@ -62,7 +80,6 @@ public Attachment(Obs obs, ComplexDataHelper complexDataHelper) {

setBytesMimeType(complexDataHelper.getContentType(obs.getComplexData()));
setBytesContentFamily(AttachmentsContext.getContentFamily(complexDataHelper.getContentType(obs.getComplexData())));

}

public Obs getObs() {
Expand Down Expand Up @@ -111,6 +128,14 @@ public void setComment(String comment) {
this.comment = comment;
}

public String getFilename() {
return filename;
}

public void setFilename(String filename) {
this.filename = filename;
}

public ComplexData getComplexData() {
return complexData;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class ValueComplex {

public ValueComplex(String valueComplex) {

if (StringUtils.substringBefore(valueComplex, SEP).equals(UNIQUE_PREFIX) == false) {
if (!StringUtils.substringBefore(valueComplex, SEP).equals(UNIQUE_PREFIX)) {
this.instructions = INSTRUCTIONS_NONE;
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Obs;
import org.openmrs.annotation.OpenmrsProfile;
import org.openmrs.api.context.Context;
import org.openmrs.module.attachments.AttachmentsConstants;
import org.openmrs.module.attachments.AttachmentsContext;
Expand All @@ -29,17 +30,18 @@
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@OpenmrsProfile(openmrsPlatformVersion = "2.2.* - 9.*")
@RequestMapping(value = "/rest/" + RestConstants.VERSION_1 + "/" + AttachmentsConstants.ATTACHMENT_URI)
public class AttachmentBytesResource extends BaseRestController {

protected AttachmentsContext context = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT,
AttachmentsContext.class);

protected final Log log = LogFactory.getLog(getClass());

@RequestMapping(value = AttachmentsConstants.ATTACHMENT_BYTES_URI, method = RequestMethod.GET)
public void getFile(@PathVariable("uuid") String uuid, @RequestParam(required = false, value = "view") String view,
HttpServletResponse response) throws ResponseException {
AttachmentsContext context = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT,
AttachmentsContext.class);

// Getting the Core/Platform complex data object
Obs obs = context.getObsService().getObsByUuid(uuid);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,12 @@
import org.springframework.web.multipart.MultipartFile;

@Resource(name = RestConstants.VERSION_1 + "/"
+ AttachmentsConstants.ATTACHMENT_URI, supportedClass = Attachment.class, supportedOpenmrsVersions = { "2.2.*",
"2.3.*", "2.4.*", "2.5.*", "2.6.*" })
+ AttachmentsConstants.ATTACHMENT_URI, supportedClass = Attachment.class, supportedOpenmrsVersions = {
"2.2.* - 9.*" })
public class AttachmentResource extends DataDelegatingCrudResource<Attachment> implements Uploadable {

protected static final String REASON = "REST web service";

private ComplexObsSaver obsSaver = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_COMPLEXOBS_SAVER,
ComplexObsSaver.class);

private AttachmentsContext ctx = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT,
AttachmentsContext.class);

@Override
public Attachment newDelegate() {
return new Attachment();
Expand All @@ -68,7 +62,9 @@ public Attachment newDelegate() {
@Override
public Attachment save(Attachment delegate) {
Obs obs = Context.getObsService().saveObs(delegate.getObs(), REASON);
return new Attachment(obs, ctx.getComplexDataHelper());
return new Attachment(obs,
Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT, AttachmentsContext.class)
.getComplexDataHelper());
}

@Override
Expand All @@ -78,7 +74,9 @@ public Attachment getByUniqueId(String uniqueId) {
throw new GenericRestException(uniqueId + " does not identify a complex obs.", null);
else {
obs = Context.getObsService().getComplexObs(obs.getId(), AttachmentsConstants.ATT_VIEW_CRUD);
return new Attachment(obs, ctx.getComplexDataHelper());
return new Attachment(obs,
Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT, AttachmentsContext.class)
.getComplexDataHelper());
}
}

Expand All @@ -98,7 +96,6 @@ public void purge(Attachment delegate, RequestContext context) throws ResponseEx

@Override
public Object upload(MultipartFile file, RequestContext context) throws ResponseException, IOException {

// Prepare Parameters
Patient patient = Context.getPatientService().getPatientByUuid(context.getParameter("patient"));
Visit visit = Context.getVisitService().getVisitByUuid(context.getParameter("visit"));
Expand All @@ -108,6 +105,9 @@ public Object upload(MultipartFile file, RequestContext context) throws Response
String instructions = context.getParameter("instructions");
String base64Content = context.getParameter("base64Content");

AttachmentsContext ctx = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT,
AttachmentsContext.class);

if (base64Content != null) {
file = new Base64MultipartFile(base64Content);
}
Expand Down Expand Up @@ -159,12 +159,14 @@ public Object upload(MultipartFile file, RequestContext context) throws Response
Obs obs;
switch (getContentFamily(file.getContentType())) {
case IMAGE:
obs = obsSaver.saveImageAttachment(visit, patient, encounter, fileCaption, file, instructions);
obs = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_COMPLEXOBS_SAVER, ComplexObsSaver.class)
.saveImageAttachment(visit, patient, encounter, fileCaption, file, instructions);
break;

case OTHER:
default:
obs = obsSaver.saveOtherAttachment(visit, patient, encounter, fileCaption, file, instructions);
obs = Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_COMPLEXOBS_SAVER, ComplexObsSaver.class)
.saveOtherAttachment(visit, patient, encounter, fileCaption, file, instructions);
break;
}

Expand All @@ -184,6 +186,7 @@ public DelegatingResourceDescription getRepresentationDescription(Representation
DelegatingResourceDescription description = new DelegatingResourceDescription();
description.addProperty("uuid");
description.addProperty("dateTime");
description.addProperty("filename");
description.addProperty("comment");
description.addProperty("bytesMimeType");
description.addProperty("bytesContentFamily");
Expand All @@ -199,7 +202,7 @@ public DelegatingResourceDescription getRepresentationDescription(Representation
*/
public static void voidEncounterIfEmpty(EncounterService encounterService, String encounterUuid) {
Encounter encounter = encounterService.getEncounterByUuid(encounterUuid);
if (encounter != null && encounter.getAllObs().size() == 0) {
if (encounter != null && encounter.getAllObs().isEmpty()) {
encounterService.voidEncounter(encounter, "foo");
}
}
Expand Down Expand Up @@ -259,23 +262,21 @@ protected PageableResult doSearch(RequestContext context) {
Visit visit = Context.getVisitService().getVisitByUuid(context.getParameter("visit"));
Encounter encounter = Context.getEncounterService().getEncounterByUuid(context.getParameter("encounter"));
String includeEncounterless = context.getParameter("includeEncounterless");
Boolean includeVoided = BooleanUtils.toBoolean(context.getParameter("includeVoided"));
boolean includeVoided = BooleanUtils.toBoolean(context.getParameter("includeVoided"));

// Verify Parameters
if (patient == null) {
throw new IllegalRequestException("A patient parameter must be provided when searching the attachments.");
}

if (includeVoided == null) {
includeVoided = false;
}

// Search Attachments
List<Attachment> attachmentList = search(ctx.getAttachmentsService(), patient, visit, encounter,
includeEncounterless, includeVoided);
List<Attachment> attachmentList = search(
Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT, AttachmentsContext.class)
.getAttachmentsService(),
patient, visit, encounter, includeEncounterless, includeVoided);

if (attachmentList != null) {
return new NeedsPaging<Attachment>(attachmentList, context);
return new NeedsPaging<>(attachmentList, context);
}
return new EmptySearchResult();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.openmrs.module.attachments.rest;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand All @@ -10,14 +12,21 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openmrs.Concept;
import org.openmrs.ConceptComplex;
import org.openmrs.ConceptDatatype;
import org.openmrs.Encounter;
import org.openmrs.Obs;
import org.openmrs.Patient;
import org.openmrs.Visit;
import org.openmrs.api.ObsService;
import org.openmrs.api.context.Context;
import org.openmrs.module.attachments.AttachmentsConstants;
import org.openmrs.module.attachments.AttachmentsContext;
import org.openmrs.module.attachments.AttachmentsService;
import org.openmrs.module.attachments.obs.Attachment;
import org.openmrs.module.attachments.obs.ComplexDataHelperImpl;
import org.openmrs.obs.ComplexData;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
Expand All @@ -38,6 +47,31 @@ public void setup() {
.thenReturn(ctx);
}

@Test
public void get_shouldReturnFilenameProperty() {
// Arrange
AttachmentResource res = new AttachmentResource();
ObsService service = mock(ObsService.class);
PowerMockito.when(Context.getObsService()).thenReturn(service);
Obs attachmentObs = new Obs();
attachmentObs.setUuid("1234");
attachmentObs.setId(1);
Concept attachmentConcept = new ConceptComplex();
ConceptDatatype datatype = new ConceptDatatype();
datatype.setHl7Abbreviation("ED");
attachmentConcept.setDatatype(datatype);
attachmentObs.setConcept(attachmentConcept);
attachmentObs.setValueComplex("m3ks | instructions.default | text/plain | filename.png");
when(service.getObsByUuid("1234")).thenReturn(attachmentObs);
when(service.getComplexObs(1, AttachmentsConstants.ATT_VIEW_CRUD)).thenReturn(attachmentObs);

// Act
Attachment attachment = res.getByUniqueId("1234");

// Assert
assertThat(attachment.getFilename(), equalTo("filename.png"));
}

@Test
public void search_shouldInvokeApiForEncounterAttachments() {
// Setup
Expand Down

0 comments on commit 613f3b0

Please sign in to comment.