address review comments for client search and minor updates to document search api

This commit is contained in:
Vishwas Babu AJ
2012-10-12 01:56:45 +05:30
parent ab9497c985
commit 3ce1ee7ded
16 changed files with 477 additions and 103 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ apply plugin: 'project-report'
project.ext.springVersion = '3.1.1.RELEASE'
project.ext.springSecurityVersion = '3.1.0.RELEASE'
project.ext.hibernateValidatorVersion = '4.3.0.Final'
project.ext.hibernateCoreVersion = '4.1.3.Final'
project.ext.hibernateCoreVersion = '3.6.10.Final'
project.ext.jerseyVersion = '1.13'
project.ext.springDataJpaVersion = '1.0.3.RELEASE'
@@ -27,8 +27,10 @@ import org.mifosng.platform.api.data.DocumentData;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService;
import org.mifosng.platform.api.infrastructure.ApiParameterHelper;
import org.mifosng.platform.common.ApplicationConstants;
import org.mifosng.platform.documentmanagement.service.DocumentReadPlatformService;
import org.mifosng.platform.documentmanagement.service.DocumentWritePlatformService;
import org.mifosng.platform.exceptions.DocumentManagementException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -55,6 +57,12 @@ public class DocumentManagementApiResource {
Arrays.asList("id", "parentEntityType", "parentEntityId", "name",
"fileName", "type", "size", "description"));
/**
* @param uriInfo
* @param entityType
* @param entityId
* @return
*/
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@@ -78,29 +86,43 @@ public class DocumentManagementApiResource {
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,
@HeaderParam("Content-Length") Long fileSize) {
@FormDataParam("name") String name,
@FormDataParam("description") String description) {
// TODO: Using Content-Length gives me size of the entire request, need
// to filter out only the size of the file
initialFileCheckerFastFail(fileSize, name);
// TODO: Need to add a Fast fail for checking size of file depending on
// the size sent by client, also need to have a backup and stop reading
// from stream after size is reached to protect against malicious
// clients
/**
* 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 fi they are
* permissable
**/
DocumentCommand documentCommand = new DocumentCommand(null, null,
entityType, entityId, "test", fileDetails.getFileName(),
fileSize, bodyPart.getMediaType().toString(), "description",
null);
bodyPart.getMediaType();
entityType, entityId, name, fileDetails.getFileName(),
fileSize, bodyPart.getMediaType().toString(), description, null);
Long documentId = this.documentWritePlatformService.createDocument(
documentCommand, inputStream);
@@ -108,6 +130,87 @@ public class DocumentManagementApiResource {
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) {
initialFileCheckerFastFail(fileSize, name);
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) {
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 fileSize
* @param name
*/
private void initialFileCheckerFastFail(Long fileSize, String name) {
/**
* Using Content-Length gives me size of the entire request, which is
* good enough for now for a fast fail as the length of the rest of the
* content i.e name and description while compared to the uploaded file
* size is negligible
**/
if (fileSize != null
&& ((fileSize / (1024 * 1024)) > ApplicationConstants.MAX_FILE_UPLOAD_SIZE_IN_MB)) {
throw new DocumentManagementException(name, fileSize);
}
}
/**
* @param entityType
* @param entityId
* @param documentId
* @param uriInfo
* @return
*/
@GET
@Path("{documentId}")
@Consumes({ MediaType.APPLICATION_JSON })
@@ -134,6 +237,12 @@ public class DocumentManagementApiResource {
prettyPrint, responseParameters, documentData);
}
/**
* @param entityType
* @param entityId
* @param documentId
* @return
*/
@GET
@Path("{documentId}/attachment")
@Consumes({ MediaType.APPLICATION_JSON })
@@ -152,22 +261,12 @@ public class DocumentManagementApiResource {
return response.build();
}
@PUT
@Path("{documentId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateDocument(@PathParam("entityType") String entityType,
@PathParam("entityId") Long entityId,
@PathParam("documentId") Long documentId) {
// TODO
// EntityIdentifier identifier =
// this.documentWritePlatformService.updateDocument(documentCommand,
// inputStream, fileDetails)
return Response.ok().entity(null).build();
}
/**
* @param entityType
* @param entityId
* @param documentId
* @return
*/
@DELETE
@Path("{documentId}")
@Consumes({ MediaType.APPLICATION_JSON })
@@ -5,11 +5,8 @@ import org.apache.commons.lang.StringUtils;
public class ClientLookup {
private final Long id;
@SuppressWarnings("unused")
private final String displayName;
@SuppressWarnings("unused")
private final Long officeId;
@SuppressWarnings("unused")
private final String officeName;
public ClientLookup(final Long id, final String firstname, final String lastname, final Long officeId, final String officeName) {
@@ -52,4 +49,22 @@ public class ClientLookup {
public int hashCode() {
return this.id.hashCode();
}
public Long getId() {
return id;
}
public String getDisplayName() {
return displayName;
}
public Long getOfficeId() {
return officeId;
}
public String getOfficeName() {
return officeName;
}
}
@@ -16,21 +16,17 @@ import org.mifosng.platform.user.domain.AppUser;
@Table(name = "m_client_identifier")
public class ClientIdentifier extends AbstractAuditableCustom<AppUser, Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "document_type_id", nullable = false)
private CodeValue documentType;
@SuppressWarnings("unused")
@Column(name = "document_key", length = 1000)
private String documentKey;
@SuppressWarnings("unused")
@Column(name = "description", length = 1000)
private String description;
@@ -41,12 +37,11 @@ public class ClientIdentifier extends AbstractAuditableCustom<AppUser, Long> {
this.description = null;
}
public static ClientIdentifier createNew(
final Client client,
final CodeValue documentType,
final String documentKey,
public static ClientIdentifier createNew(final Client client,
final CodeValue documentType, final String documentKey,
final String description) {
return new ClientIdentifier(client, documentType, documentKey, description);
return new ClientIdentifier(client, documentType, documentKey,
description);
}
private ClientIdentifier(final Client client, final CodeValue documentType,
@@ -73,4 +68,21 @@ public class ClientIdentifier extends AbstractAuditableCustom<AppUser, Long> {
command.getDescription(), null);
}
}
public Client getClient() {
return client;
}
public CodeValue getDocumentType() {
return documentType;
}
public String getDocumentKey() {
return documentKey;
}
public String getDescription() {
return description;
}
}
@@ -37,4 +37,6 @@ public interface ClientReadPlatformService {
* @return
*/
ClientIdentifierData retrieveNewClientIdentifierDetails();
Boolean existsClientIdentifier(Long clientId,Long identifierTypeId);
ClientLookup getClientByIdentifier(Long identifierTypeId, String identifierKey);
}
@@ -9,9 +9,19 @@ import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.*;
import org.mifosng.platform.api.data.AppUserData;
import org.mifosng.platform.api.data.ClientAccountSummaryCollectionData;
import org.mifosng.platform.api.data.ClientAccountSummaryData;
import org.mifosng.platform.api.data.ClientData;
import org.mifosng.platform.api.data.ClientIdentifierData;
import org.mifosng.platform.api.data.ClientLookup;
import org.mifosng.platform.api.data.CodeValueData;
import org.mifosng.platform.api.data.EnumOptionData;
import org.mifosng.platform.api.data.NoteData;
import org.mifosng.platform.api.data.OfficeLookup;
import org.mifosng.platform.client.domain.NoteEnumerations;
import org.mifosng.platform.common.ApplicationConstants;
import org.mifosng.platform.exceptions.ClientIdentifierNotFoundException;
import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.NoteNotFoundException;
import org.mifosng.platform.infrastructure.JdbcSupport;
@@ -156,9 +166,17 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
"c.office_id as officeId, o.name as officeName " +
"from m_client c join m_office o on o.id = c.office_id where c.is_deleted=0 ";
}
public String clientLookupByIdentifierSchema() {
return "c.id as id, c.firstname as firstname, c.lastname as lastname, " +
"c.office_id as officeId, o.name as officeName " +
"from m_client c, m_office o, m_client_identifier ci " +
"where o.id = c.office_id and c.id=ci.client_id " +
"and ci.document_type_id= ? and ci.document_key like ?";
}
@Override
public ClientLookup mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
public ClientLookup mapRow(ResultSet rs, int rowNum) throws SQLException {
Long id = rs.getLong("id");
String firstname = rs.getString("firstname");
String lastname = rs.getString("lastname");
@@ -428,27 +446,30 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
@Override
public ClientIdentifierData retrieveClientIdentifier(Long clientId,
Long clientIdentifierId) {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
try {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
ClientIdentityMapper rm = new ClientIdentityMapper();
ClientIdentityMapper rm = new ClientIdentityMapper();
String sql = "select " + rm.schema();
String sql = "select " + rm.schema();
sql += " and ci.id = ?";
sql += " and ci.id = ?";
ClientIdentifierData clientIdentifierData = this.jdbcTemplate
.queryForObject(sql, rm, new Object[] { clientId,
hierarchySearchString, clientIdentifierId });
ClientIdentifierData clientIdentifierData = this.jdbcTemplate
.queryForObject(sql, rm, new Object[] { clientId,
hierarchySearchString, clientIdentifierId });
if(clientIdentifierData!=null){
clientIdentifierData.setAllowedDocumentTypes(new ArrayList<CodeValueData>(
codeValuePlatformService
.retrieveAllCodeValues(ApplicationConstants.CLIENT_IDENTITY_CODE_ID)));
clientIdentifierData
.setAllowedDocumentTypes(new ArrayList<CodeValueData>(
codeValuePlatformService
.retrieveAllCodeValues(ApplicationConstants.CLIENT_IDENTITY_CODE_ID)));
return clientIdentifierData;
} catch (EmptyResultDataAccessException e) {
throw new ClientIdentifierNotFoundException(clientIdentifierId);
}
return clientIdentifierData;
}
@Override
@@ -495,7 +516,43 @@ public class ClientReadPlatformServiceImpl implements ClientReadPlatformService
}
@Override
public Boolean existsClientIdentifier(Long clientId, Long identifierTypeId) {
try {
AppUser currentUser = context.authenticatedUser();
String hierarchy = currentUser.getOffice().getHierarchy();
String hierarchySearchString = hierarchy + "%";
ClientIdentityMapper rm = new ClientIdentityMapper();
String sql = "select " + rm.schema() + " and ci.document_type_id=?";
/****query for Object throws an exception if exactly one row is not returned***/
this.jdbcTemplate.queryForObject(sql, rm, new Object[] { clientId,
hierarchySearchString, identifierTypeId });
return true;
} catch (EmptyResultDataAccessException e) {
return false;
}
}
@Override
public ClientLookup getClientByIdentifier(Long identifierTypeId,
String identifierKey) {
try {
ClientLookupMapper mapper = new ClientLookupMapper();
String sql = "select " + mapper.clientLookupByIdentifierSchema();
/****
* query for Object throws an exception if exactly one row is not
* returned
***/
ClientLookup clientLookup = jdbcTemplate.queryForObject(sql,
mapper, new Object[] { identifierTypeId, identifierKey });
return clientLookup;
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
@@ -4,6 +4,7 @@ import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.commands.ClientIdentifierCommand;
import org.mifosng.platform.api.commands.NoteCommand;
import org.mifosng.platform.api.data.ClientLookup;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientIdentifier;
@@ -14,6 +15,7 @@ import org.mifosng.platform.client.domain.NoteRepository;
import org.mifosng.platform.exceptions.ClientIdentifierNotFoundException;
import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.CodeValueNotFoundException;
import org.mifosng.platform.exceptions.DuplicateClientIdentifierException;
import org.mifosng.platform.exceptions.NoteNotFoundException;
import org.mifosng.platform.exceptions.OfficeNotFoundException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
@@ -42,6 +44,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
private final OfficeRepository officeRepository;
private final NoteRepository noteRepository;
private final CodeValueRepository codeValueRepository;
private final ClientReadPlatformService clientReadPlatformService;
@Autowired
public ClientWritePlatformServiceJpaRepositoryImpl(
@@ -50,13 +53,15 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
final ClientIdentifierRepository clientIdentifierRepository,
final OfficeRepository officeRepository,
NoteRepository noteRepository,
final CodeValueRepository codeValueRepository) {
final CodeValueRepository codeValueRepository,
final ClientReadPlatformService clientReadPlatformService) {
this.context = context;
this.clientRepository = clientRepository;
this.clientIdentifierRepository = clientIdentifierRepository;
this.officeRepository = officeRepository;
this.noteRepository = noteRepository;
this.codeValueRepository = codeValueRepository;
this.clientReadPlatformService = clientReadPlatformService;
}
@Transactional
@@ -209,7 +214,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
@Transactional
@Override
public Long addClientIdentifier(ClientIdentifierCommand clientIdentifierCommand) {
public Long addClientIdentifier(
ClientIdentifierCommand clientIdentifierCommand) {
try {
context.authenticatedUser();
@@ -234,6 +240,22 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
String documentKey = clientIdentifierCommand.getDocumentKey();
String description = clientIdentifierCommand.getDescription();
/**
* check if a client identifier of the given type already exists for
* the client
**/
if (clientReadPlatformService.existsClientIdentifier(
clientIdentifierCommand.getClientId(),
clientIdentifierCommand.getDocumentTypeId())) {
throw new DuplicateClientIdentifierException(
documentType.getLabel());
}
/*** Check if any Client has the same identifier ***/
checkIdentifierUniqueness(documentType.getId(),
documentType.getLabel(), documentKey,
clientIdentifierCommand.getClientId());
ClientIdentifier clientIdentifier = ClientIdentifier.createNew(
client, documentType, documentKey, description);
@@ -248,6 +270,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
}
}
@Transactional
@Override
public EntityIdentifier updateClientIdentifier(
ClientIdentifierCommand clientIdentifierCommand) {
@@ -276,6 +300,45 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
throw new ClientIdentifierNotFoundException(
clientIdentifierCommand.getId());
}
/**
* check if a client identifier of the given type already exists for
* the client
**/
if (clientIdentifierForUpdate.getDocumentType().getId() != clientIdentifierCommand
.getDocumentTypeId()) {
if (clientReadPlatformService.existsClientIdentifier(
clientIdentifierCommand.getClientId(),
clientIdentifierCommand.getDocumentTypeId())) {
throw new DuplicateClientIdentifierException(
documentType.getLabel());
}
}
/*** Check if any Client has the same identifier ***/
if (clientIdentifierCommand.isDocumentTypeChanged()
&& clientIdentifierCommand.isDocumentKeyChanged()) {
checkIdentifierUniqueness(
clientIdentifierCommand.getDocumentTypeId(),
documentType.getLabel(),
clientIdentifierCommand.getDocumentKey(),
clientIdentifierForUpdate.getClient().getId());
} else if (clientIdentifierCommand.isDocumentTypeChanged()
&& !clientIdentifierCommand.isDocumentKeyChanged()) {
checkIdentifierUniqueness(
clientIdentifierCommand.getDocumentTypeId(),
documentType.getLabel(),
clientIdentifierForUpdate.getDocumentKey(),
clientIdentifierForUpdate.getClient().getId());
} else if (!clientIdentifierCommand.isDocumentTypeChanged()
&& clientIdentifierCommand.isDocumentKeyChanged()) {
checkIdentifierUniqueness(clientIdentifierForUpdate
.getDocumentType().getId(), documentType.getLabel(),
clientIdentifierCommand.getDocumentKey(),
clientIdentifierForUpdate.getClient().getId());
}
clientIdentifierForUpdate.update(clientIdentifierCommand,
documentType);
@@ -303,4 +366,19 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements
return new EntityIdentifier(clientIdentifierId);
}
/**
* @param documentTypeId
* @param documentTypeLabel
* @param documentKey
*/
private void checkIdentifierUniqueness(Long documentTypeId,
String documentTypeLabel, String documentKey, Long callingClientId) {
ClientLookup clientLookup = clientReadPlatformService
.getClientByIdentifier(documentTypeId, documentKey);
if (clientLookup != null && clientLookup.getId()!=callingClientId) {
throw new DuplicateClientIdentifierException(clientLookup.getDisplayName(),
clientLookup.getOfficeName(), documentTypeLabel, documentKey);
}
}
}
@@ -4,6 +4,9 @@ public class ApplicationConstants {
public static final Long CLIENT_IDENTITY_CODE_ID = 9L;
// TODO:Vishwas Need to move these settings to a database flag
public static final Integer MAX_FILE_UPLOAD_SIZE_IN_MB = 5;
/*** Entities for document Management **/
public static enum DOCUMENT_MANAGEMENT_ENTITIES {
CLIENTs, STAFF, LOANS;
@@ -13,35 +13,27 @@ import org.mifosng.platform.user.domain.AppUser;
@Table(name = "m_document")
public class Document extends AbstractAuditableCustom<AppUser, Long> {
@SuppressWarnings("unused")
@Column(name = "parent_entity_type", length = 50)
private String parentEntityType;
@SuppressWarnings("unused")
@Column(name = "parent_entity_id", length = 1000)
private Long parentEntityId;
@SuppressWarnings("unused")
@Column(name = "name", length = 250)
private String name;
@SuppressWarnings("unused")
@Column(name = "file_name", length = 250)
private String fileName;
@SuppressWarnings("unused")
@Column(name = "size")
private Long size;
@SuppressWarnings("unused")
@Column(name = "type", length = 50)
private String type;
@SuppressWarnings("unused")
@Column(name = "description", length = 1000)
private String description;
@SuppressWarnings("unused")
@Column(name = "location", length = 500)
private String location;
@@ -91,4 +83,68 @@ public class Document extends AbstractAuditableCustom<AppUser, Long> {
}
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;
}
}
@@ -24,16 +24,13 @@ public class DocumentCommandValidator {
baseDataValidator.reset().parameter("name").value(command.getName())
.ignoreIfNull().notBlank();
/*** TODO:Validate for max length of File to be stored **/
baseDataValidator.reset().parameter("size").value(command.getSize())
.ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("fileName")
.value(command.getFileName()).ignoreIfNull().notBlank()
.integerGreaterThanZero();
.notExceedingLengthOf(250);
baseDataValidator.reset().parameter("location")
.value(command.getLocation()).ignoreIfNull().notBlank()
.integerGreaterThanZero();
/*** TODO: Validate for permissable types ***/
.value(command.getLocation()).ignoreIfNull().notBlank();
baseDataValidator.reset().parameter("type").value(command.getName())
.ignoreIfNull().notBlank().notExceedingLengthOf(250);
baseDataValidator.reset().parameter("description")
@@ -63,18 +60,16 @@ public class DocumentCommandValidator {
.value(command.getParentEntityId()).integerGreaterThanZero();
baseDataValidator.reset().parameter("name").value(command.getName())
.notBlank().notExceedingLengthOf(250);
/*** TODO:Validate for max length of File to be stored **/
baseDataValidator.reset().parameter("size").value(command.getSize())
.integerGreaterThanZero();
baseDataValidator.reset().parameter("fileName")
.value(command.getFileName()).notBlank()
.notExceedingLengthOf(250);
/*** TODO: Validate for permissable types ***/
baseDataValidator.reset().parameter("type").value(command.getName())
.notBlank().notExceedingLengthOf(250);
baseDataValidator.reset().parameter("description")
.value(command.getName()).notExceedingLengthOf(250);
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
@@ -26,7 +26,7 @@ public class DocumentReadPlatformServiceImpl implements
private final JdbcTemplate jdbcTemplate;
// TODO: use these services to check if passed n entities for document
// 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;
@@ -12,7 +12,7 @@ import org.mifosng.platform.common.FileUtils;
import org.mifosng.platform.documentmanagement.domain.Document;
import org.mifosng.platform.documentmanagement.domain.DocumentRepository;
import org.mifosng.platform.exceptions.DocumentNotFoundException;
import org.mifosng.platform.exceptions.DocumentSaveException;
import org.mifosng.platform.exceptions.DocumentManagementException;
import org.mifosng.platform.exceptions.InvalidEntityTypeForDocumentManagementException;
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
import org.mifosng.platform.loan.domain.LoanRepository;
@@ -79,9 +79,6 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
new File(fileUploadLocation).mkdirs();
}
// TODO check if entity id is valid and within data scope for the
// user
// TODO replace file system appender with an Amazon S3 appender
String fileLocation = FileUtils.saveToFileSystem(inputStream,
fileUploadLocation, documentCommand.getFileName());
@@ -102,7 +99,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
"Unknown data integrity issue with resource.");
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new DocumentSaveException(documentCommand.getName());
throw new DocumentManagementException(documentCommand.getName());
}
}
@@ -111,7 +108,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
public EntityIdentifier updateDocument(DocumentCommand documentCommand,
InputStream inputStream) {
try {
String oldLocation = null;
DocumentCommandValidator validator = new DocumentCommandValidator(
documentCommand);
validator.validateForUpdate();
@@ -125,7 +122,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
documentCommand.getParentEntityId(),
documentCommand.getId());
}
oldLocation = documentForUpdate.getLocation();
// if a new file is also passed in
if (inputStream != null) {
String fileUploadLocation = FileUtils
@@ -142,11 +139,16 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
// TODO delete the file at the previous location
String fileLocation = FileUtils.saveToFileSystem(inputStream,
fileUploadLocation, documentCommand.getFileName());
documentCommand.setSize(documentCommand.getSize());
documentCommand.setLocation(fileLocation);
}
documentForUpdate.update(documentCommand);
if (inputStream != null) {
// delete previous file
deleteFile(documentCommand.getName(), oldLocation);
}
this.documentRepository.saveAndFlush(documentForUpdate);
return new EntityIdentifier(documentForUpdate.getId());
@@ -157,7 +159,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
"Unknown data integrity issue with resource.");
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new DocumentSaveException(documentCommand.getName());
throw new DocumentManagementException(documentCommand.getName());
}
}
@@ -176,11 +178,18 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements
}
this.documentRepository.delete(document);
// TODO: delete the actual file from File system/ Amazon S3
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(
@@ -0,0 +1,22 @@
package org.mifosng.platform.exceptions;
import org.mifosng.platform.common.ApplicationConstants;
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) {
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 "
+ ApplicationConstants.MAX_FILE_UPLOAD_SIZE_IN_MB
+ " MB", name, fileSize);
}
}
@@ -1,11 +0,0 @@
package org.mifosng.platform.exceptions;
public class DocumentSaveException extends
AbstractPlatformResourceNotFoundException {
public DocumentSaveException(final String name) {
super("error.msg.document.id.save",
"Unable to save the document with name" + name
+ " due to a File system / Amazon S3 issue", name);
}
}
@@ -0,0 +1,23 @@
package org.mifosng.platform.exceptions;
/**
* A {@link RuntimeException} thrown when a client Identifer of the particular
* type is already present
*/
public class DuplicateClientIdentifierException extends
AbstractPlatformDomainRuleException {
public DuplicateClientIdentifierException(String identifierType) {
super("error.msg.clientIdentifier.type.duplicate",
"Client Identifier of type " + identifierType
+ " is already present for this client", identifierType);
}
public DuplicateClientIdentifierException(String clientName,
String officeName, String identifierType, String identifierKey) {
super("error.msg.clientIdentifier.identityKey.duplicate", "Client "
+ clientName + "under " + officeName + " Branch already has a "
+ identifierType + " with unique key " + identifierKey,
clientName, officeName, identifierType, identifierKey);
}
}
@@ -15,11 +15,9 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
"code_id", "code_value" }, name = "code_value_duplicate") })
public class CodeValue extends AbstractPersistable<Long> {
@SuppressWarnings("unused")
@Column(name = "code_value", length = 100)
private String label;
@SuppressWarnings("unused")
@Column(name = "order_position")
private int position;
@@ -44,4 +42,20 @@ public class CodeValue extends AbstractPersistable<Long> {
this.position = position;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}