MIFOSX-97: repackage document management code.
This commit is contained in:
-281
@@ -1,281 +0,0 @@
|
||||
package org.mifosng.platform.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosng.platform.api.data.DocumentData;
|
||||
import org.mifosng.platform.documentmanagement.service.DocumentReadPlatformService;
|
||||
import org.mifosng.platform.documentmanagement.service.DocumentWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiConstants;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.sun.jersey.core.header.FormDataContentDisposition;
|
||||
import com.sun.jersey.multipart.FormDataBodyPart;
|
||||
import com.sun.jersey.multipart.FormDataParam;
|
||||
|
||||
@Path("{entityType}/{entityId}/documents")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class DocumentManagementApiResource {
|
||||
|
||||
@Autowired
|
||||
private DocumentReadPlatformService documentReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
private DocumentWritePlatformService documentWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
private PortfolioApiJsonSerializerService apiJsonSerializerService;
|
||||
|
||||
private static final Set<String> typicalResponseParameters = new HashSet<String>(
|
||||
Arrays.asList("id", "parentEntityType", "parentEntityId", "name",
|
||||
"fileName", "type", "size", "description"));
|
||||
|
||||
private final String SystemEntityType = "DOCUMENT";
|
||||
@Autowired
|
||||
private PlatformSecurityContext context;
|
||||
|
||||
/**
|
||||
* @param uriInfo
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retreiveAllDocuments(@Context final UriInfo uriInfo,
|
||||
@PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(SystemEntityType);
|
||||
|
||||
Set<String> responseParameters = ApiParameterHelper
|
||||
.extractFieldsForResponseIfProvided(uriInfo
|
||||
.getQueryParameters());
|
||||
if (responseParameters.isEmpty()) {
|
||||
responseParameters.addAll(typicalResponseParameters);
|
||||
}
|
||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
|
||||
.getQueryParameters());
|
||||
|
||||
Collection<DocumentData> documentDatas = this.documentReadPlatformService
|
||||
.retrieveAllDocuments(entityType, entityId);
|
||||
|
||||
return this.apiJsonSerializerService.serializeDocumentDataToJson(
|
||||
prettyPrint, responseParameters, documentDatas);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @param fileSize
|
||||
* @param inputStream
|
||||
* @param fileDetails
|
||||
* @param bodyPart
|
||||
* @param name
|
||||
* @param description
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response createDocument(@PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId,
|
||||
@HeaderParam("Content-Length") Long fileSize,
|
||||
@FormDataParam("file") InputStream inputStream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetails,
|
||||
@FormDataParam("file") FormDataBodyPart bodyPart,
|
||||
@FormDataParam("name") String name,
|
||||
@FormDataParam("description") String description) {
|
||||
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
/**
|
||||
* TODO: also need to have a backup and stop reading from stream after
|
||||
* max size is reached to protect against malicious clients
|
||||
**/
|
||||
|
||||
/**
|
||||
* TODO: need to extract the actual file type and determine if they are
|
||||
* permissable
|
||||
**/
|
||||
DocumentCommand documentCommand = new DocumentCommand(null, null,
|
||||
entityType, entityId, name, fileDetails.getFileName(),
|
||||
fileSize, bodyPart.getMediaType().toString(), description, null);
|
||||
|
||||
Long documentId = this.documentWritePlatformService.createDocument(
|
||||
documentCommand, inputStream);
|
||||
|
||||
return Response.ok().entity(new EntityIdentifier(documentId)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @param documentId
|
||||
* @param fileSize
|
||||
* @param inputStream
|
||||
* @param fileDetails
|
||||
* @param bodyPart
|
||||
* @param name
|
||||
* @param description
|
||||
* @return
|
||||
*/
|
||||
@PUT
|
||||
@Path("{documentId}")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response updateDocument(@PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId,
|
||||
@HeaderParam("Content-Length") Long fileSize,
|
||||
@FormDataParam("file") InputStream inputStream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetails,
|
||||
@FormDataParam("file") FormDataBodyPart bodyPart,
|
||||
@FormDataParam("name") String name,
|
||||
@FormDataParam("description") String description) {
|
||||
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
Set<String> modifiedParams = new HashSet<String>();
|
||||
modifiedParams.add("name");
|
||||
modifiedParams.add("description");
|
||||
|
||||
/***
|
||||
* Populate Document command based on whether a file has also been
|
||||
* passed in as a part of the update
|
||||
***/
|
||||
DocumentCommand documentCommand = null;
|
||||
if (inputStream != null && fileDetails.getFileName() != null) {
|
||||
modifiedParams.add("fileName");
|
||||
modifiedParams.add("size");
|
||||
modifiedParams.add("type");
|
||||
modifiedParams.add("location");
|
||||
documentCommand = new DocumentCommand(modifiedParams, documentId,
|
||||
entityType, entityId, name, fileDetails.getFileName(),
|
||||
fileSize, bodyPart.getMediaType().toString(), description,
|
||||
null);
|
||||
} else {
|
||||
documentCommand = new DocumentCommand(modifiedParams, documentId,
|
||||
entityType, entityId, name, null, null, null, description,
|
||||
null);
|
||||
}
|
||||
EntityIdentifier identifier = this.documentWritePlatformService
|
||||
.updateDocument(documentCommand, inputStream);
|
||||
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @param documentId
|
||||
* @param uriInfo
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("{documentId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String getDocument(@PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(SystemEntityType);
|
||||
|
||||
Set<String> responseParameters = ApiParameterHelper
|
||||
.extractFieldsForResponseIfProvided(uriInfo
|
||||
.getQueryParameters());
|
||||
if (responseParameters.isEmpty()) {
|
||||
responseParameters.addAll(typicalResponseParameters);
|
||||
}
|
||||
|
||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
|
||||
.getQueryParameters());
|
||||
|
||||
DocumentData documentData = this.documentReadPlatformService
|
||||
.retrieveDocument(entityType, entityId, documentId);
|
||||
|
||||
return this.apiJsonSerializerService.serializeDocumentDataToJson(
|
||||
prettyPrint, responseParameters, documentData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @param documentId
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("{documentId}/attachment")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response downloadFile(@PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(SystemEntityType);
|
||||
|
||||
DocumentData documentData = this.documentReadPlatformService
|
||||
.retrieveDocument(entityType, entityId, documentId);
|
||||
File file = new File(documentData.getLocation());
|
||||
ResponseBuilder response = Response.ok(file);
|
||||
response.header("Content-Disposition", "attachment; filename=\""
|
||||
+ documentData.getFileName() + "\"");
|
||||
response.header("Content-Type", documentData.getType());
|
||||
return response.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entityType
|
||||
* @param entityId
|
||||
* @param documentId
|
||||
* @return
|
||||
*/
|
||||
@DELETE
|
||||
@Path("{documentId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response deleteDocument(@PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId) {
|
||||
DocumentCommand documentCommand = new DocumentCommand(null, documentId,
|
||||
entityType, entityId, null, null, null, null, null, null);
|
||||
|
||||
EntityIdentifier documentIdentifier = this.documentWritePlatformService
|
||||
.deleteDocument(documentCommand);
|
||||
|
||||
return Response.ok(documentIdentifier).build();
|
||||
}
|
||||
|
||||
}
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
package org.mifosng.platform.api.commands;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Immutable command for creating or updating details of a client identifier.
|
||||
*/
|
||||
public class DocumentCommand {
|
||||
|
||||
private final Long id;
|
||||
private final String parentEntityType;
|
||||
private final Long parentEntityId;
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private String fileName;
|
||||
private Long size;
|
||||
private String type;
|
||||
private String location;
|
||||
|
||||
private final Set<String> modifiedParameters;
|
||||
|
||||
public DocumentCommand(final Set<String> modifiedParameters, final Long id,
|
||||
final String parentEntityType, final Long parentEntityId,
|
||||
final String name, final String fileName, Long size, String type,
|
||||
final String description, String location) {
|
||||
this.modifiedParameters = modifiedParameters;
|
||||
this.id = id;
|
||||
this.parentEntityType = parentEntityType;
|
||||
this.parentEntityId = parentEntityId;
|
||||
this.name = name;
|
||||
this.fileName = fileName;
|
||||
this.size = size;
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getParentEntityType() {
|
||||
return parentEntityType;
|
||||
}
|
||||
|
||||
public Long getParentEntityId() {
|
||||
return parentEntityId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public Set<String> getModifiedParameters() {
|
||||
return modifiedParameters;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public boolean isNameChanged() {
|
||||
return this.modifiedParameters.contains("name");
|
||||
}
|
||||
|
||||
public boolean isFileNameChanged() {
|
||||
return this.modifiedParameters.contains("fileName");
|
||||
}
|
||||
|
||||
public boolean isSizeChanged() {
|
||||
return this.modifiedParameters.contains("size");
|
||||
}
|
||||
|
||||
public boolean isFileTypeChanged() {
|
||||
return this.modifiedParameters.contains("type");
|
||||
}
|
||||
|
||||
public boolean isDescriptionChanged() {
|
||||
return this.modifiedParameters.contains("description");
|
||||
}
|
||||
|
||||
public boolean isLocationChanged() {
|
||||
return this.modifiedParameters.contains("location");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package org.mifosng.platform.api.data;
|
||||
|
||||
|
||||
public class DocumentData {
|
||||
|
||||
private final Long id;
|
||||
private final String parentEntityType;
|
||||
private final Long parentEntityId;
|
||||
private final String name;
|
||||
private final String fileName;
|
||||
private final Long size;
|
||||
private final String type;
|
||||
private final String description;
|
||||
private final String location;
|
||||
|
||||
public DocumentData(final Long id, final String parentEntityType,
|
||||
final Long parentEntityId, final String name,
|
||||
final String fileName, final Long size, final String type,
|
||||
final String description, final String location) {
|
||||
this.id = id;
|
||||
this.parentEntityType = parentEntityType;
|
||||
this.parentEntityId = parentEntityId;
|
||||
this.name = name;
|
||||
this.fileName = fileName;
|
||||
this.size = size;
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getParentEntityType() {
|
||||
return parentEntityType;
|
||||
}
|
||||
|
||||
public Long getParentEntityId() {
|
||||
return parentEntityId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
||||
-150
@@ -1,150 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.mifosplatform.infrastructure.user.domain.AppUser;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_document")
|
||||
public class Document extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
@Column(name = "parent_entity_type", length = 50)
|
||||
private String parentEntityType;
|
||||
|
||||
@Column(name = "parent_entity_id", length = 1000)
|
||||
private Long parentEntityId;
|
||||
|
||||
@Column(name = "name", length = 250)
|
||||
private String name;
|
||||
|
||||
@Column(name = "file_name", length = 250)
|
||||
private String fileName;
|
||||
|
||||
@Column(name = "size")
|
||||
private Long size;
|
||||
|
||||
@Column(name = "type", length = 50)
|
||||
private String type;
|
||||
|
||||
@Column(name = "description", length = 1000)
|
||||
private String description;
|
||||
|
||||
@Column(name = "location", length = 500)
|
||||
private String location;
|
||||
|
||||
public Document() {
|
||||
}
|
||||
|
||||
public static Document createNew(String parentEntityType,
|
||||
Long parentEntityId, String name, String fileName, Long size,
|
||||
String type, String description, String location) {
|
||||
return new Document(parentEntityType, parentEntityId, name, fileName,
|
||||
size, type, description, location);
|
||||
}
|
||||
|
||||
private Document(String parentEntityType, Long parentEntityId, String name,
|
||||
String fileName, Long size, String type, String description,
|
||||
String location) {
|
||||
this.parentEntityType = StringUtils.defaultIfEmpty(parentEntityType,
|
||||
null);
|
||||
this.parentEntityId = parentEntityId;
|
||||
this.name = StringUtils.defaultIfEmpty(name, null);
|
||||
this.fileName = StringUtils.defaultIfEmpty(fileName, null);
|
||||
this.size = size;
|
||||
this.type = StringUtils.defaultIfEmpty(type, null);
|
||||
this.description = StringUtils.defaultIfEmpty(description, null);
|
||||
this.location = StringUtils.defaultIfEmpty(location, null);
|
||||
}
|
||||
|
||||
public void update(final DocumentCommand command) {
|
||||
if (command.isDescriptionChanged()) {
|
||||
this.description = command.getDescription();
|
||||
}
|
||||
if (command.isFileNameChanged()) {
|
||||
this.fileName = command.getFileName();
|
||||
}
|
||||
if (command.isFileTypeChanged()) {
|
||||
this.type = command.getType();
|
||||
}
|
||||
if (command.isLocationChanged()) {
|
||||
this.location = command.getLocation();
|
||||
}
|
||||
if (command.isNameChanged()) {
|
||||
this.name = command.getName();
|
||||
}
|
||||
if (command.isSizeChanged()) {
|
||||
this.size = command.getSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getParentEntityType() {
|
||||
return parentEntityType;
|
||||
}
|
||||
|
||||
public void setParentEntityType(String parentEntityType) {
|
||||
this.parentEntityType = parentEntityType;
|
||||
}
|
||||
|
||||
public Long getParentEntityId() {
|
||||
return parentEntityId;
|
||||
}
|
||||
|
||||
public void setParentEntityId(Long parentEntityId) {
|
||||
this.parentEntityId = parentEntityId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface DocumentRepository extends
|
||||
JpaRepository<Document, Long>, JpaSpecificationExecutor<Document> {
|
||||
// no added behaviour
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
|
||||
public class DocumentCommandValidator {
|
||||
|
||||
private final DocumentCommand command;
|
||||
|
||||
public DocumentCommandValidator(DocumentCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void validateForUpdate() {
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
|
||||
dataValidationErrors).resource("document");
|
||||
|
||||
baseDataValidator.reset().parameter("name").value(command.getName())
|
||||
.ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("size").value(command.getSize())
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("fileName")
|
||||
.value(command.getFileName()).ignoreIfNull().notBlank()
|
||||
.notExceedingLengthOf(250);
|
||||
baseDataValidator.reset().parameter("location")
|
||||
.value(command.getLocation()).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("description")
|
||||
.value(command.getName()).ignoreIfNull()
|
||||
.notExceedingLengthOf(250);
|
||||
|
||||
baseDataValidator.reset().anyOfNotNull(command.getName(),
|
||||
command.getFileName(), command.getDescription(),
|
||||
command.getLocation(), command.getSize());
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(
|
||||
"validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public void validateForCreate() {
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
|
||||
dataValidationErrors).resource("document");
|
||||
baseDataValidator.reset().parameter("parentEntityType")
|
||||
.value(command.getParentEntityType()).notBlank()
|
||||
.notExceedingLengthOf(50);
|
||||
baseDataValidator.reset().parameter("parentEntityId")
|
||||
.value(command.getParentEntityId()).integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("name").value(command.getName())
|
||||
.notBlank().notExceedingLengthOf(250);
|
||||
baseDataValidator.reset().parameter("size").value(command.getSize())
|
||||
.integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("fileName")
|
||||
.value(command.getFileName()).notBlank()
|
||||
.notExceedingLengthOf(250);
|
||||
baseDataValidator.reset().parameter("description")
|
||||
.value(command.getName()).notExceedingLengthOf(250);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(
|
||||
"validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosng.platform.api.data.DocumentData;
|
||||
|
||||
public interface DocumentReadPlatformService {
|
||||
|
||||
Collection<DocumentData> retrieveAllDocuments(String entityType,
|
||||
Long entityId);
|
||||
|
||||
DocumentData retrieveDocument(String entityType, Long entityId,
|
||||
Long documentId);
|
||||
|
||||
}
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosng.platform.api.data.DocumentData;
|
||||
import org.mifosng.platform.exceptions.DocumentNotFoundException;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
// TODO: use these services to check if passed in entities for document
|
||||
// management exists (and ensure appropriate errors are thrown)
|
||||
private final PlatformSecurityContext context;
|
||||
// private final OfficeReadPlatformService officeReadPlatformService;
|
||||
// private final ClientReadPlatformService clientReadPlatformService;
|
||||
// private final LoanReadPlatformService loanReadPlatformService;
|
||||
// private final StaffReadPlatformService staffReadPlatformService;
|
||||
// private final AppUserReadPlatformService appUserReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public DocumentReadPlatformServiceImpl(
|
||||
final PlatformSecurityContext context,
|
||||
final TenantAwareRoutingDataSource dataSource
|
||||
// final OfficeReadPlatformService officeReadPlatformService,
|
||||
// final AppUserReadPlatformService appUserReadPlatformService,
|
||||
// final ClientReadPlatformService clientReadPlatformService,
|
||||
// final LoanReadPlatformService loanReadPlatformService,
|
||||
// final StaffReadPlatformService staffReadPlatformService
|
||||
) {
|
||||
this.context = context;
|
||||
// this.officeReadPlatformService = officeReadPlatformService;
|
||||
// this.appUserReadPlatformService = appUserReadPlatformService;
|
||||
// this.clientReadPlatformService = clientReadPlatformService;
|
||||
// this.loanReadPlatformService = loanReadPlatformService;
|
||||
// this.staffReadPlatformService = staffReadPlatformService;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DocumentData> retrieveAllDocuments(final String entityType, final Long entityId) {
|
||||
|
||||
context.authenticatedUser();
|
||||
|
||||
// TODO verify if the entities are valid and a user
|
||||
// has data
|
||||
// scope for the particular entities
|
||||
DocumentMapper mapper = new DocumentMapper();
|
||||
String sql = "select " + mapper.schema() + " order by d.id";
|
||||
return this.jdbcTemplate.query(sql, mapper, new Object[] {entityType, entityId});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentData retrieveDocument(final String entityType, final Long entityId, final Long documentId) {
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
// TODO verify if the entities are valid and a
|
||||
// user has data
|
||||
// scope for the particular entities
|
||||
DocumentMapper mapper = new DocumentMapper();
|
||||
String sql = "select " + mapper.schema() + " and d.id=? ";
|
||||
return this.jdbcTemplate.queryForObject(sql, mapper, new Object[] {entityType, entityId, documentId });
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
throw new DocumentNotFoundException(entityType, entityId, documentId);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DocumentMapper implements RowMapper<DocumentData> {
|
||||
|
||||
public String schema() {
|
||||
return "d.id as id, d.parent_entity_type as parentEntityType, d.parent_entity_id as parentEntityId, d.name as name, "
|
||||
+ " d.file_name as fileName, d.size as fileSize, d.type as fileType, "
|
||||
+ " d.description as description, d.location as location"
|
||||
+ " from m_document d where d.parent_entity_type=? and d.parent_entity_id=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final Long parentEntityId = JdbcSupport.getLong(rs, "parentEntityId");
|
||||
final Long fileSize = JdbcSupport.getLong(rs, "fileSize");
|
||||
final String parentEntityType = rs.getString("parentEntityType");
|
||||
final String name = rs.getString("name");
|
||||
final String fileName = rs.getString("fileName");
|
||||
final String fileType = rs.getString("fileType");
|
||||
final String description = rs.getString("description");
|
||||
final String location = rs.getString("location");
|
||||
|
||||
return new DocumentData(id, parentEntityType, parentEntityId, name,
|
||||
fileName, fileSize, fileType, description, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface DocumentWritePlatformService {
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'CREATE_m_guarantor_external')")
|
||||
Long createDocument(DocumentCommand documentCommand, InputStream inputStream);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'UPDATE_m_guarantor_external')")
|
||||
EntityIdentifier updateDocument(DocumentCommand documentCommand,
|
||||
InputStream inputStream);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'DELETE_m_guarantor_external')")
|
||||
EntityIdentifier deleteDocument(DocumentCommand documentCommand);
|
||||
|
||||
}
|
||||
-198
@@ -1,198 +0,0 @@
|
||||
package org.mifosng.platform.documentmanagement.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.mifosng.platform.api.commands.DocumentCommand;
|
||||
import org.mifosng.platform.documentmanagement.domain.Document;
|
||||
import org.mifosng.platform.documentmanagement.domain.DocumentRepository;
|
||||
import org.mifosng.platform.exceptions.DocumentManagementException;
|
||||
import org.mifosng.platform.exceptions.DocumentNotFoundException;
|
||||
import org.mifosng.platform.exceptions.InvalidEntityTypeForDocumentManagementException;
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class DocumentWritePlatformServiceJpaRepositoryImpl implements
|
||||
DocumentWritePlatformService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DocumentWritePlatformServiceJpaRepositoryImpl.class);
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DocumentRepository documentRepository;
|
||||
|
||||
@Autowired
|
||||
public DocumentWritePlatformServiceJpaRepositoryImpl(
|
||||
final PlatformSecurityContext context,
|
||||
final DocumentRepository documentRepository) {
|
||||
this.context = context;
|
||||
this.documentRepository = documentRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Long createDocument(final DocumentCommand documentCommand, final InputStream inputStream) {
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
DocumentCommandValidator validator = new DocumentCommandValidator(documentCommand);
|
||||
|
||||
validateParentEntityType(documentCommand);
|
||||
|
||||
validator.validateForCreate();
|
||||
|
||||
String fileUploadLocation = FileUtils.generateFileParentDirectory(
|
||||
documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId());
|
||||
|
||||
/** Recursively create the directory if it does not exist **/
|
||||
if (!new File(fileUploadLocation).isDirectory()) {
|
||||
new File(fileUploadLocation).mkdirs();
|
||||
}
|
||||
|
||||
String fileLocation = FileUtils.saveToFileSystem(inputStream,
|
||||
fileUploadLocation, documentCommand.getFileName());
|
||||
|
||||
Document document = Document.createNew(
|
||||
documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId(),
|
||||
documentCommand.getName(), documentCommand.getFileName(),
|
||||
documentCommand.getSize(), documentCommand.getType(),
|
||||
documentCommand.getDescription(), fileLocation);
|
||||
|
||||
this.documentRepository.save(document);
|
||||
|
||||
return document.getId();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.document.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
} catch (IOException ioe) {
|
||||
logger.error(ioe.getMessage(), ioe);
|
||||
throw new DocumentManagementException(documentCommand.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier updateDocument(final DocumentCommand documentCommand, final InputStream inputStream) {
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
String oldLocation = null;
|
||||
DocumentCommandValidator validator = new DocumentCommandValidator(documentCommand);
|
||||
validator.validateForUpdate();
|
||||
// TODO check if entity id is valid and within data scope for the
|
||||
// user
|
||||
Document documentForUpdate = this.documentRepository
|
||||
.findOne(documentCommand.getId());
|
||||
if (documentForUpdate == null) {
|
||||
throw new DocumentNotFoundException(
|
||||
documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId(),
|
||||
documentCommand.getId());
|
||||
}
|
||||
oldLocation = documentForUpdate.getLocation();
|
||||
// if a new file is also passed in
|
||||
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
||||
String fileUploadLocation = FileUtils
|
||||
.generateFileParentDirectory(
|
||||
documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId());
|
||||
|
||||
/** Recursively create the directory if it does not exist **/
|
||||
if (!new File(fileUploadLocation).isDirectory()) {
|
||||
new File(fileUploadLocation).mkdirs();
|
||||
}
|
||||
|
||||
// TODO replace file system appender with an Amazon S3 appender
|
||||
String fileLocation = FileUtils.saveToFileSystem(inputStream,
|
||||
fileUploadLocation, documentCommand.getFileName());
|
||||
documentCommand.setLocation(fileLocation);
|
||||
}
|
||||
|
||||
documentForUpdate.update(documentCommand);
|
||||
|
||||
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
||||
// delete previous file
|
||||
deleteFile(documentCommand.getName(), oldLocation);
|
||||
}
|
||||
|
||||
this.documentRepository.saveAndFlush(documentForUpdate);
|
||||
|
||||
return new EntityIdentifier(documentForUpdate.getId());
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.document.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
} catch (IOException ioe) {
|
||||
logger.error(ioe.getMessage(), ioe);
|
||||
throw new DocumentManagementException(documentCommand.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier deleteDocument(final DocumentCommand documentCommand) {
|
||||
context.authenticatedUser();
|
||||
|
||||
validateParentEntityType(documentCommand);
|
||||
// TODO: Check document is present under this entity Id
|
||||
Document document = this.documentRepository.findOne(documentCommand.getId());
|
||||
if (document == null) {
|
||||
throw new DocumentNotFoundException(
|
||||
documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId(),
|
||||
documentCommand.getId());
|
||||
}
|
||||
|
||||
this.documentRepository.delete(document);
|
||||
deleteFile(document.getName(), document.getLocation());
|
||||
return new EntityIdentifier(document.getId());
|
||||
}
|
||||
|
||||
private void deleteFile(String documentName, String location) {
|
||||
File fileToBeDeleted = new File(location);
|
||||
boolean fileDeleted = fileToBeDeleted.delete();
|
||||
if (!fileDeleted) {
|
||||
throw new DocumentManagementException(documentName);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateParentEntityType(DocumentCommand documentCommand) {
|
||||
if (!checkValidEntityType(documentCommand.getParentEntityType())) {
|
||||
throw new InvalidEntityTypeForDocumentManagementException(
|
||||
documentCommand.getParentEntityType());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkValidEntityType(final String entityType) {
|
||||
|
||||
for (DOCUMENT_MANAGEMENT_ENTITY entities : DOCUMENT_MANAGEMENT_ENTITY.values()) {
|
||||
if (entities.name().equalsIgnoreCase(entityType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*** Entities for document Management **/
|
||||
public static enum DOCUMENT_MANAGEMENT_ENTITY {
|
||||
CLIENTS, CLIENT_IDENTIFIERS, STAFF, LOANS, SAVINGS;
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package org.mifosng.platform.exceptions;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
|
||||
public class DocumentManagementException extends
|
||||
AbstractPlatformDomainRuleException {
|
||||
|
||||
public DocumentManagementException(final String name) {
|
||||
super("error.msg.document.save", "Error while manipulating file "
|
||||
+ name + " due to a File system / Amazon S3 issue", name);
|
||||
}
|
||||
|
||||
public DocumentManagementException(final String name, final Long fileSize,
|
||||
final int maxFileSize) {
|
||||
super("error.msg.document.file.too.big",
|
||||
"Unable to save the document with name" + name
|
||||
+ " since its file Size of " + fileSize / (1024 * 1024)
|
||||
+ " MB exceeds the max permissable file size of "
|
||||
+ maxFileSize
|
||||
+ " MB", name, fileSize);
|
||||
}
|
||||
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package org.mifosng.platform.exceptions;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class DocumentNotFoundException extends
|
||||
AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public DocumentNotFoundException(final String entityType,
|
||||
final Long entityId, final Long id) {
|
||||
super("error.msg.document.id.invalid", "Document with identifier " + id
|
||||
+ " does not exist for the " + entityType + " with Identifier "
|
||||
+ entityId, id);
|
||||
}
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package org.mifosng.platform.exceptions;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when document management functionality is
|
||||
* invoked for invalid Entity Types
|
||||
*/
|
||||
public class InvalidEntityTypeForDocumentManagementException extends
|
||||
AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public InvalidEntityTypeForDocumentManagementException(
|
||||
final String entityType) {
|
||||
super("error.documentmanagement.entitytype.invalid",
|
||||
"Document Management is not support for the Entity Type: "
|
||||
+ entityType, entityType);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,7 +7,6 @@ import java.util.Set;
|
||||
|
||||
import org.mifosng.platform.api.data.DepositAccountData;
|
||||
import org.mifosng.platform.api.data.DepositProductData;
|
||||
import org.mifosng.platform.api.data.DocumentData;
|
||||
import org.mifosng.platform.api.data.GroupAccountSummaryCollectionData;
|
||||
import org.mifosng.platform.api.data.GroupData;
|
||||
import org.mifosng.platform.api.data.GuarantorData;
|
||||
@@ -19,6 +18,7 @@ import org.mifosplatform.infrastructure.configuration.data.ConfigurationData;
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.dataqueries.data.DatatableData;
|
||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||
import org.mifosplatform.infrastructure.office.data.OfficeData;
|
||||
import org.mifosplatform.infrastructure.office.data.OfficeTransactionData;
|
||||
import org.mifosplatform.infrastructure.staff.data.BulkTransferLoanOfficerData;
|
||||
|
||||
+1
-1
@@ -5,7 +5,6 @@ import java.util.Set;
|
||||
|
||||
import org.mifosng.platform.api.data.DepositAccountData;
|
||||
import org.mifosng.platform.api.data.DepositProductData;
|
||||
import org.mifosng.platform.api.data.DocumentData;
|
||||
import org.mifosng.platform.api.data.GroupAccountSummaryCollectionData;
|
||||
import org.mifosng.platform.api.data.GroupData;
|
||||
import org.mifosng.platform.api.data.GuarantorData;
|
||||
@@ -17,6 +16,7 @@ import org.mifosplatform.infrastructure.configuration.data.ConfigurationData;
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.dataqueries.data.DatatableData;
|
||||
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||
import org.mifosplatform.infrastructure.office.data.OfficeData;
|
||||
import org.mifosplatform.infrastructure.office.data.OfficeTransactionData;
|
||||
import org.mifosplatform.infrastructure.staff.data.BulkTransferLoanOfficerData;
|
||||
|
||||
+1
-1
@@ -9,12 +9,12 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.mifosng.platform.exceptions.DocumentManagementException;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||
import org.mifosplatform.infrastructure.core.exception.ImageDataURLNotValidException;
|
||||
import org.mifosplatform.infrastructure.core.exception.ImageUploadException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.ApiConstants;
|
||||
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
|
||||
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.service.DocumentReadPlatformService;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.service.DocumentWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.sun.jersey.core.header.FormDataContentDisposition;
|
||||
import com.sun.jersey.multipart.FormDataBodyPart;
|
||||
import com.sun.jersey.multipart.FormDataParam;
|
||||
|
||||
@Path("{entityType}/{entityId}/documents")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class DocumentManagementApiResource {
|
||||
|
||||
private final String SystemEntityType = "DOCUMENT";
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DocumentReadPlatformService documentReadPlatformService;
|
||||
private final DocumentWritePlatformService documentWritePlatformService;
|
||||
private final PortfolioApiJsonSerializerService apiJsonSerializerService;
|
||||
|
||||
@Autowired
|
||||
public DocumentManagementApiResource(final PlatformSecurityContext context,
|
||||
final DocumentReadPlatformService documentReadPlatformService, final DocumentWritePlatformService documentWritePlatformService,
|
||||
final PortfolioApiJsonSerializerService apiJsonSerializerService) {
|
||||
this.context = context;
|
||||
this.documentReadPlatformService = documentReadPlatformService;
|
||||
this.documentWritePlatformService = documentWritePlatformService;
|
||||
this.apiJsonSerializerService = apiJsonSerializerService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retreiveAllDocuments(@Context final UriInfo uriInfo, @PathParam("entityType") String entityType,
|
||||
@PathParam("entityId") Long entityId) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(SystemEntityType);
|
||||
|
||||
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
|
||||
final Collection<DocumentData> documentDatas = this.documentReadPlatformService.retrieveAllDocuments(entityType, entityId);
|
||||
|
||||
return this.apiJsonSerializerService.serializeDocumentDataToJson(prettyPrint, responseParameters, documentDatas);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response createDocument(@PathParam("entityType") String entityType, @PathParam("entityId") Long entityId,
|
||||
@HeaderParam("Content-Length") Long fileSize, @FormDataParam("file") InputStream inputStream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetails, @FormDataParam("file") FormDataBodyPart bodyPart,
|
||||
@FormDataParam("name") String name, @FormDataParam("description") String description) {
|
||||
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
/**
|
||||
* TODO: also need to have a backup and stop reading from stream after
|
||||
* max size is reached to protect against malicious clients
|
||||
**/
|
||||
|
||||
/**
|
||||
* TODO: need to extract the actual file type and determine if they are
|
||||
* permissable
|
||||
**/
|
||||
DocumentCommand documentCommand = new DocumentCommand(null, null, entityType, entityId, name, fileDetails.getFileName(), fileSize,
|
||||
bodyPart.getMediaType().toString(), description, null);
|
||||
|
||||
Long documentId = this.documentWritePlatformService.createDocument(documentCommand, inputStream);
|
||||
|
||||
return Response.ok().entity(new EntityIdentifier(documentId)).build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{documentId}")
|
||||
@Consumes({ MediaType.MULTIPART_FORM_DATA })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response updateDocument(@PathParam("entityType") String entityType, @PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId, @HeaderParam("Content-Length") Long fileSize,
|
||||
@FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails,
|
||||
@FormDataParam("file") FormDataBodyPart bodyPart, @FormDataParam("name") String name,
|
||||
@FormDataParam("description") String description) {
|
||||
|
||||
FileUtils.validateFileSizeWithinPermissibleRange(fileSize, name, ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB);
|
||||
|
||||
Set<String> modifiedParams = new HashSet<String>();
|
||||
modifiedParams.add("name");
|
||||
modifiedParams.add("description");
|
||||
|
||||
/***
|
||||
* Populate Document command based on whether a file has also been
|
||||
* passed in as a part of the update
|
||||
***/
|
||||
DocumentCommand documentCommand = null;
|
||||
if (inputStream != null && fileDetails.getFileName() != null) {
|
||||
modifiedParams.add("fileName");
|
||||
modifiedParams.add("size");
|
||||
modifiedParams.add("type");
|
||||
modifiedParams.add("location");
|
||||
documentCommand = new DocumentCommand(modifiedParams, documentId, entityType, entityId, name, fileDetails.getFileName(),
|
||||
fileSize, bodyPart.getMediaType().toString(), description, null);
|
||||
} else {
|
||||
documentCommand = new DocumentCommand(modifiedParams, documentId, entityType, entityId, name, null, null, null, description,
|
||||
null);
|
||||
}
|
||||
EntityIdentifier identifier = this.documentWritePlatformService.updateDocument(documentCommand, inputStream);
|
||||
|
||||
return Response.ok().entity(identifier).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{documentId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String getDocument(@PathParam("entityType") String entityType, @PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId, @Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(SystemEntityType);
|
||||
|
||||
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
|
||||
final DocumentData documentData = this.documentReadPlatformService.retrieveDocument(entityType, entityId, documentId);
|
||||
|
||||
return this.apiJsonSerializerService.serializeDocumentDataToJson(prettyPrint, responseParameters, documentData);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{documentId}/attachment")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response downloadFile(@PathParam("entityType") String entityType, @PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(SystemEntityType);
|
||||
|
||||
DocumentData documentData = this.documentReadPlatformService.retrieveDocument(entityType, entityId, documentId);
|
||||
File file = new File(documentData.fileLocation());
|
||||
ResponseBuilder response = Response.ok(file);
|
||||
response.header("Content-Disposition", "attachment; filename=\"" + documentData.fileName() + "\"");
|
||||
response.header("Content-Type", documentData.contentType());
|
||||
return response.build();
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{documentId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response deleteDocument(@PathParam("entityType") String entityType, @PathParam("entityId") Long entityId,
|
||||
@PathParam("documentId") Long documentId) {
|
||||
|
||||
DocumentCommand documentCommand = new DocumentCommand(null, documentId, entityType, entityId, null, null, null, null, null, null);
|
||||
|
||||
EntityIdentifier documentIdentifier = this.documentWritePlatformService.deleteDocument(documentCommand);
|
||||
|
||||
return Response.ok(documentIdentifier).build();
|
||||
}
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.command;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Immutable command for creating or updating details of a client identifier.
|
||||
*/
|
||||
public class DocumentCommand {
|
||||
|
||||
private final Long id;
|
||||
private final String parentEntityType;
|
||||
private final Long parentEntityId;
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private String fileName;
|
||||
private Long size;
|
||||
private String type;
|
||||
private String location;
|
||||
|
||||
private final Set<String> modifiedParameters;
|
||||
|
||||
public DocumentCommand(final Set<String> modifiedParameters, final Long id, final String parentEntityType, final Long parentEntityId,
|
||||
final String name, final String fileName, Long size, String type, final String description, String location) {
|
||||
this.modifiedParameters = modifiedParameters;
|
||||
this.id = id;
|
||||
this.parentEntityType = parentEntityType;
|
||||
this.parentEntityId = parentEntityId;
|
||||
this.name = name;
|
||||
this.fileName = fileName;
|
||||
this.size = size;
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getParentEntityType() {
|
||||
return parentEntityType;
|
||||
}
|
||||
|
||||
public Long getParentEntityId() {
|
||||
return parentEntityId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public Set<String> getModifiedParameters() {
|
||||
return modifiedParameters;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public boolean isNameChanged() {
|
||||
return this.modifiedParameters.contains("name");
|
||||
}
|
||||
|
||||
public boolean isFileNameChanged() {
|
||||
return this.modifiedParameters.contains("fileName");
|
||||
}
|
||||
|
||||
public boolean isSizeChanged() {
|
||||
return this.modifiedParameters.contains("size");
|
||||
}
|
||||
|
||||
public boolean isFileTypeChanged() {
|
||||
return this.modifiedParameters.contains("type");
|
||||
}
|
||||
|
||||
public boolean isDescriptionChanged() {
|
||||
return this.modifiedParameters.contains("description");
|
||||
}
|
||||
|
||||
public boolean isLocationChanged() {
|
||||
return this.modifiedParameters.contains("location");
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
|
||||
public class DocumentCommandValidator {
|
||||
|
||||
private final DocumentCommand command;
|
||||
|
||||
public DocumentCommandValidator(DocumentCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void validateForUpdate() {
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("document");
|
||||
|
||||
baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("size").value(command.getSize()).ignoreIfNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("fileName").value(command.getFileName()).ignoreIfNull().notBlank().notExceedingLengthOf(250);
|
||||
baseDataValidator.reset().parameter("location").value(command.getLocation()).ignoreIfNull().notBlank();
|
||||
baseDataValidator.reset().parameter("description").value(command.getName()).ignoreIfNull().notExceedingLengthOf(250);
|
||||
|
||||
baseDataValidator.reset().anyOfNotNull(command.getName(), command.getFileName(), command.getDescription(), command.getLocation(),
|
||||
command.getSize());
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
public void validateForCreate() {
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("document");
|
||||
baseDataValidator.reset().parameter("parentEntityType").value(command.getParentEntityType()).notBlank().notExceedingLengthOf(50);
|
||||
baseDataValidator.reset().parameter("parentEntityId").value(command.getParentEntityId()).integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("name").value(command.getName()).notBlank().notExceedingLengthOf(250);
|
||||
baseDataValidator.reset().parameter("size").value(command.getSize()).integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("fileName").value(command.getFileName()).notBlank().notExceedingLengthOf(250);
|
||||
baseDataValidator.reset().parameter("description").value(command.getName()).notExceedingLengthOf(250);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.data;
|
||||
|
||||
/**
|
||||
* Immutable data object represent document being managed on platform.
|
||||
*/
|
||||
public class DocumentData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String parentEntityType;
|
||||
@SuppressWarnings("unused")
|
||||
private final Long parentEntityId;
|
||||
@SuppressWarnings("unused")
|
||||
private final String name;
|
||||
private final String fileName;
|
||||
@SuppressWarnings("unused")
|
||||
private final Long size;
|
||||
private final String type;
|
||||
@SuppressWarnings("unused")
|
||||
private final String description;
|
||||
private final String location;
|
||||
|
||||
public DocumentData(final Long id, final String parentEntityType, final Long parentEntityId, final String name, final String fileName,
|
||||
final Long size, final String type, final String description, final String location) {
|
||||
this.id = id;
|
||||
this.parentEntityType = parentEntityType;
|
||||
this.parentEntityId = parentEntityId;
|
||||
this.name = name;
|
||||
this.fileName = fileName;
|
||||
this.size = size;
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public String contentType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String fileName() {
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
public String fileLocation() {
|
||||
return this.location;
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||
import org.mifosplatform.infrastructure.user.domain.AppUser;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_document")
|
||||
public class Document extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
@Column(name = "parent_entity_type", length = 50)
|
||||
private String parentEntityType;
|
||||
|
||||
@Column(name = "parent_entity_id", length = 1000)
|
||||
private Long parentEntityId;
|
||||
|
||||
@Column(name = "name", length = 250)
|
||||
private String name;
|
||||
|
||||
@Column(name = "file_name", length = 250)
|
||||
private String fileName;
|
||||
|
||||
@Column(name = "size")
|
||||
private Long size;
|
||||
|
||||
@Column(name = "type", length = 50)
|
||||
private String type;
|
||||
|
||||
@Column(name = "description", length = 1000)
|
||||
private String description;
|
||||
|
||||
@Column(name = "location", length = 500)
|
||||
private String location;
|
||||
|
||||
public Document() {}
|
||||
|
||||
public static Document createNew(String parentEntityType, Long parentEntityId, String name, String fileName, Long size, String type,
|
||||
String description, String location) {
|
||||
return new Document(parentEntityType, parentEntityId, name, fileName, size, type, description, location);
|
||||
}
|
||||
|
||||
private Document(String parentEntityType, Long parentEntityId, String name, String fileName, Long size, String type,
|
||||
String description, String location) {
|
||||
this.parentEntityType = StringUtils.defaultIfEmpty(parentEntityType, null);
|
||||
this.parentEntityId = parentEntityId;
|
||||
this.name = StringUtils.defaultIfEmpty(name, null);
|
||||
this.fileName = StringUtils.defaultIfEmpty(fileName, null);
|
||||
this.size = size;
|
||||
this.type = StringUtils.defaultIfEmpty(type, null);
|
||||
this.description = StringUtils.defaultIfEmpty(description, null);
|
||||
this.location = StringUtils.defaultIfEmpty(location, null);
|
||||
}
|
||||
|
||||
public void update(final DocumentCommand command) {
|
||||
if (command.isDescriptionChanged()) {
|
||||
this.description = command.getDescription();
|
||||
}
|
||||
if (command.isFileNameChanged()) {
|
||||
this.fileName = command.getFileName();
|
||||
}
|
||||
if (command.isFileTypeChanged()) {
|
||||
this.type = command.getType();
|
||||
}
|
||||
if (command.isLocationChanged()) {
|
||||
this.location = command.getLocation();
|
||||
}
|
||||
if (command.isNameChanged()) {
|
||||
this.name = command.getName();
|
||||
}
|
||||
if (command.isSizeChanged()) {
|
||||
this.size = command.getSize();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getParentEntityType() {
|
||||
return parentEntityType;
|
||||
}
|
||||
|
||||
public void setParentEntityType(String parentEntityType) {
|
||||
this.parentEntityType = parentEntityType;
|
||||
}
|
||||
|
||||
public Long getParentEntityId() {
|
||||
return parentEntityId;
|
||||
}
|
||||
|
||||
public void setParentEntityId(Long parentEntityId) {
|
||||
this.parentEntityId = parentEntityId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(String location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface DocumentRepository extends JpaRepository<Document, Long>, JpaSpecificationExecutor<Document> {
|
||||
// no added behaviour
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class DocumentManagementException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public DocumentManagementException(final String name) {
|
||||
super("error.msg.document.save", "Error while manipulating file " + name + " due to a File system / Amazon S3 issue", name);
|
||||
}
|
||||
|
||||
public DocumentManagementException(final String name, final Long fileSize, final int maxFileSize) {
|
||||
super("error.msg.document.file.too.big", "Unable to save the document with name" + name + " since its file Size of " + fileSize
|
||||
/ (1024 * 1024) + " MB exceeds the max permissable file size of " + maxFileSize + " MB", name, fileSize);
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class DocumentNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public DocumentNotFoundException(final String entityType, final Long entityId, final Long id) {
|
||||
super("error.msg.document.id.invalid", "Document with identifier " + id + " does not exist for the " + entityType
|
||||
+ " with Identifier " + entityId, id);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when document management functionality is
|
||||
* invoked for invalid Entity Types
|
||||
*/
|
||||
public class InvalidEntityTypeForDocumentManagementException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public InvalidEntityTypeForDocumentManagementException(final String entityType) {
|
||||
super("error.documentmanagement.entitytype.invalid", "Document Management is not support for the Entity Type: " + entityType,
|
||||
entityType);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||
|
||||
public interface DocumentReadPlatformService {
|
||||
|
||||
Collection<DocumentData> retrieveAllDocuments(String entityType, Long entityId);
|
||||
|
||||
DocumentData retrieveDocument(String entityType, Long entityId, Long documentId);
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DocumentReadPlatformServiceImpl implements DocumentReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public DocumentReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DocumentData> retrieveAllDocuments(final String entityType, final Long entityId) {
|
||||
|
||||
context.authenticatedUser();
|
||||
|
||||
// TODO verify if the entities are valid and a user
|
||||
// has data
|
||||
// scope for the particular entities
|
||||
DocumentMapper mapper = new DocumentMapper();
|
||||
String sql = "select " + mapper.schema() + " order by d.id";
|
||||
return this.jdbcTemplate.query(sql, mapper, new Object[] { entityType, entityId });
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentData retrieveDocument(final String entityType, final Long entityId, final Long documentId) {
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
// TODO verify if the entities are valid and a
|
||||
// user has data
|
||||
// scope for the particular entities
|
||||
DocumentMapper mapper = new DocumentMapper();
|
||||
String sql = "select " + mapper.schema() + " and d.id=? ";
|
||||
return this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { entityType, entityId, documentId });
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
throw new DocumentNotFoundException(entityType, entityId, documentId);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DocumentMapper implements RowMapper<DocumentData> {
|
||||
|
||||
public String schema() {
|
||||
return "d.id as id, d.parent_entity_type as parentEntityType, d.parent_entity_id as parentEntityId, d.name as name, "
|
||||
+ " d.file_name as fileName, d.size as fileSize, d.type as fileType, "
|
||||
+ " d.description as description, d.location as location"
|
||||
+ " from m_document d where d.parent_entity_type=? and d.parent_entity_id=?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = JdbcSupport.getLong(rs, "id");
|
||||
final Long parentEntityId = JdbcSupport.getLong(rs, "parentEntityId");
|
||||
final Long fileSize = JdbcSupport.getLong(rs, "fileSize");
|
||||
final String parentEntityType = rs.getString("parentEntityType");
|
||||
final String name = rs.getString("name");
|
||||
final String fileName = rs.getString("fileName");
|
||||
final String fileType = rs.getString("fileType");
|
||||
final String description = rs.getString("description");
|
||||
final String location = rs.getString("location");
|
||||
|
||||
return new DocumentData(id, parentEntityType, parentEntityId, name, fileName, fileSize, fileType, description, location);
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface DocumentWritePlatformService {
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'CREATE_m_guarantor_external')")
|
||||
Long createDocument(DocumentCommand documentCommand, InputStream inputStream);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'UPDATE_m_guarantor_external')")
|
||||
EntityIdentifier updateDocument(DocumentCommand documentCommand, InputStream inputStream);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'DELETE_m_guarantor_external')")
|
||||
EntityIdentifier deleteDocument(DocumentCommand documentCommand);
|
||||
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
package org.mifosplatform.infrastructure.documentmanagement.service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommand;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.command.DocumentCommandValidator;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.domain.Document;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.domain.DocumentRepository;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentNotFoundException;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.exception.InvalidEntityTypeForDocumentManagementException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWritePlatformService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DocumentWritePlatformServiceJpaRepositoryImpl.class);
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DocumentRepository documentRepository;
|
||||
|
||||
@Autowired
|
||||
public DocumentWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final DocumentRepository documentRepository) {
|
||||
this.context = context;
|
||||
this.documentRepository = documentRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Long createDocument(final DocumentCommand documentCommand, final InputStream inputStream) {
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
DocumentCommandValidator validator = new DocumentCommandValidator(documentCommand);
|
||||
|
||||
validateParentEntityType(documentCommand);
|
||||
|
||||
validator.validateForCreate();
|
||||
|
||||
String fileUploadLocation = FileUtils.generateFileParentDirectory(documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId());
|
||||
|
||||
/** Recursively create the directory if it does not exist **/
|
||||
if (!new File(fileUploadLocation).isDirectory()) {
|
||||
new File(fileUploadLocation).mkdirs();
|
||||
}
|
||||
|
||||
String fileLocation = FileUtils.saveToFileSystem(inputStream, fileUploadLocation, documentCommand.getFileName());
|
||||
|
||||
Document document = Document.createNew(documentCommand.getParentEntityType(), documentCommand.getParentEntityId(),
|
||||
documentCommand.getName(), documentCommand.getFileName(), documentCommand.getSize(), documentCommand.getType(),
|
||||
documentCommand.getDescription(), fileLocation);
|
||||
|
||||
this.documentRepository.save(document);
|
||||
|
||||
return document.getId();
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException("error.msg.document.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
} catch (IOException ioe) {
|
||||
logger.error(ioe.getMessage(), ioe);
|
||||
throw new DocumentManagementException(documentCommand.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier updateDocument(final DocumentCommand documentCommand, final InputStream inputStream) {
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
|
||||
String oldLocation = null;
|
||||
DocumentCommandValidator validator = new DocumentCommandValidator(documentCommand);
|
||||
validator.validateForUpdate();
|
||||
// TODO check if entity id is valid and within data scope for the
|
||||
// user
|
||||
Document documentForUpdate = this.documentRepository.findOne(documentCommand.getId());
|
||||
if (documentForUpdate == null) { throw new DocumentNotFoundException(documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId(), documentCommand.getId()); }
|
||||
oldLocation = documentForUpdate.getLocation();
|
||||
// if a new file is also passed in
|
||||
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
||||
String fileUploadLocation = FileUtils.generateFileParentDirectory(documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId());
|
||||
|
||||
/** Recursively create the directory if it does not exist **/
|
||||
if (!new File(fileUploadLocation).isDirectory()) {
|
||||
new File(fileUploadLocation).mkdirs();
|
||||
}
|
||||
|
||||
// TODO replace file system appender with an Amazon S3 appender
|
||||
String fileLocation = FileUtils.saveToFileSystem(inputStream, fileUploadLocation, documentCommand.getFileName());
|
||||
documentCommand.setLocation(fileLocation);
|
||||
}
|
||||
|
||||
documentForUpdate.update(documentCommand);
|
||||
|
||||
if (inputStream != null && documentCommand.isFileNameChanged()) {
|
||||
// delete previous file
|
||||
deleteFile(documentCommand.getName(), oldLocation);
|
||||
}
|
||||
|
||||
this.documentRepository.saveAndFlush(documentForUpdate);
|
||||
|
||||
return new EntityIdentifier(documentForUpdate.getId());
|
||||
} catch (DataIntegrityViolationException dve) {
|
||||
logger.error(dve.getMessage(), dve);
|
||||
throw new PlatformDataIntegrityException("error.msg.document.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
} catch (IOException ioe) {
|
||||
logger.error(ioe.getMessage(), ioe);
|
||||
throw new DocumentManagementException(documentCommand.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public EntityIdentifier deleteDocument(final DocumentCommand documentCommand) {
|
||||
context.authenticatedUser();
|
||||
|
||||
validateParentEntityType(documentCommand);
|
||||
// TODO: Check document is present under this entity Id
|
||||
Document document = this.documentRepository.findOne(documentCommand.getId());
|
||||
if (document == null) { throw new DocumentNotFoundException(documentCommand.getParentEntityType(),
|
||||
documentCommand.getParentEntityId(), documentCommand.getId()); }
|
||||
|
||||
this.documentRepository.delete(document);
|
||||
deleteFile(document.getName(), document.getLocation());
|
||||
return new EntityIdentifier(document.getId());
|
||||
}
|
||||
|
||||
private void deleteFile(String documentName, String location) {
|
||||
File fileToBeDeleted = new File(location);
|
||||
boolean fileDeleted = fileToBeDeleted.delete();
|
||||
if (!fileDeleted) { throw new DocumentManagementException(documentName); }
|
||||
}
|
||||
|
||||
private void validateParentEntityType(DocumentCommand documentCommand) {
|
||||
if (!checkValidEntityType(documentCommand.getParentEntityType())) { throw new InvalidEntityTypeForDocumentManagementException(
|
||||
documentCommand.getParentEntityType()); }
|
||||
}
|
||||
|
||||
private static boolean checkValidEntityType(final String entityType) {
|
||||
|
||||
for (DOCUMENT_MANAGEMENT_ENTITY entities : DOCUMENT_MANAGEMENT_ENTITY.values()) {
|
||||
if (entities.name().equalsIgnoreCase(entityType)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*** Entities for document Management **/
|
||||
public static enum DOCUMENT_MANAGEMENT_ENTITY {
|
||||
CLIENTS, CLIENT_IDENTIFIERS, STAFF, LOANS, SAVINGS;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.mifosng.platform.exceptions.DocumentManagementException;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepository;
|
||||
import org.mifosplatform.infrastructure.codes.exception.CodeValueNotFoundException;
|
||||
@@ -14,6 +13,7 @@ import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
|
||||
import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.core.service.FileUtils;
|
||||
import org.mifosplatform.infrastructure.documentmanagement.exception.DocumentManagementException;
|
||||
import org.mifosplatform.infrastructure.office.domain.Office;
|
||||
import org.mifosplatform.infrastructure.office.domain.OfficeRepository;
|
||||
import org.mifosplatform.infrastructure.office.exception.OfficeNotFoundException;
|
||||
|
||||
Reference in New Issue
Block a user