From c0701d0a2c23b14c46e6a646f52cbbcf53f73de0 Mon Sep 17 00:00:00 2001 From: Ian Date: Tue, 30 Jan 2024 14:22:19 -0500 Subject: [PATCH] ATT-52: Attachment REST endpoint should send file name and comment --- .../module/attachments/obs/Attachment.java | 14 +++++- .../module/attachments/obs/ValueComplex.java | 2 +- .../rest/AttachmentBytesResource.java | 8 ++-- .../attachments/rest/AttachmentResource.java | 45 ++++++++++--------- .../rest/AttachmentResourceTest.java | 34 ++++++++++++++ 5 files changed, 75 insertions(+), 28 deletions(-) diff --git a/api/src/main/java/org/openmrs/module/attachments/obs/Attachment.java b/api/src/main/java/org/openmrs/module/attachments/obs/Attachment.java index 1536186c..1797690e 100644 --- a/api/src/main/java/org/openmrs/module/attachments/obs/Attachment.java +++ b/api/src/main/java/org/openmrs/module/attachments/obs/Attachment.java @@ -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 { @@ -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; @@ -51,6 +53,7 @@ public Attachment(Obs obs) { setDateTime(obs.getObsDatetime()); setComment(obs.getComment()); + setFilename(new ValueComplex(obs.getValueComplex()).getFileName()); setComplexData(obs.getComplexData()); } @@ -62,7 +65,6 @@ public Attachment(Obs obs, ComplexDataHelper complexDataHelper) { setBytesMimeType(complexDataHelper.getContentType(obs.getComplexData())); setBytesContentFamily(AttachmentsContext.getContentFamily(complexDataHelper.getContentType(obs.getComplexData()))); - } public Obs getObs() { @@ -111,6 +113,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; } diff --git a/api/src/main/java/org/openmrs/module/attachments/obs/ValueComplex.java b/api/src/main/java/org/openmrs/module/attachments/obs/ValueComplex.java index 911df915..a5c505e2 100644 --- a/api/src/main/java/org/openmrs/module/attachments/obs/ValueComplex.java +++ b/api/src/main/java/org/openmrs/module/attachments/obs/ValueComplex.java @@ -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; } diff --git a/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentBytesResource.java b/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentBytesResource.java index 6e57558d..1398c02c 100644 --- a/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentBytesResource.java +++ b/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentBytesResource.java @@ -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; @@ -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); diff --git a/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentResource.java b/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentResource.java index d8401511..dba82b0e 100644 --- a/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentResource.java +++ b/omod/src/main/java/org/openmrs/module/attachments/rest/AttachmentResource.java @@ -46,18 +46,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 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(); @@ -66,7 +60,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 @@ -76,7 +72,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()); } } @@ -96,7 +94,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")); @@ -106,6 +103,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); } @@ -142,12 +142,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; } @@ -167,6 +169,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"); @@ -182,7 +185,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"); } } @@ -242,23 +245,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 attachmentList = search(ctx.getAttachmentsService(), patient, visit, encounter, - includeEncounterless, includeVoided); + List attachmentList = search( + Context.getRegisteredComponent(AttachmentsConstants.COMPONENT_ATT_CONTEXT, AttachmentsContext.class) + .getAttachmentsService(), + patient, visit, encounter, includeEncounterless, includeVoided); if (attachmentList != null) { - return new NeedsPaging(attachmentList, context); + return new NeedsPaging<>(attachmentList, context); } return new EmptySearchResult(); } diff --git a/omod/src/test/java/org/openmrs/module/attachments/rest/AttachmentResourceTest.java b/omod/src/test/java/org/openmrs/module/attachments/rest/AttachmentResourceTest.java index 4ff5346c..8c83727f 100644 --- a/omod/src/test/java/org/openmrs/module/attachments/rest/AttachmentResourceTest.java +++ b/omod/src/test/java/org/openmrs/module/attachments/rest/AttachmentResourceTest.java @@ -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; @@ -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; @@ -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