Add pagination support to audit API

This commit is contained in:
ashok-conflux
2013-12-12 19:09:50 +05:30
parent a9f01477e0
commit 5373263f6c
6 changed files with 316 additions and 8 deletions
@@ -26,8 +26,10 @@ import org.mifosplatform.commands.data.AuditSearchData;
import org.mifosplatform.commands.service.AuditReadPlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.PaginationParameters;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
@@ -72,15 +74,22 @@ public class AuditsApiResource {
@QueryParam("checkerDateTimeTo") final String checkerDateTimeTo,
@QueryParam("processingResult") final Integer processingResult, @QueryParam("officeId") final Integer officeId,
@QueryParam("groupId") final Integer groupId, @QueryParam("clientId") final Integer clientId,
@QueryParam("loanid") final Integer loanId, @QueryParam("savingsAccountId") final Integer savingsAccountId) {
@QueryParam("loanid") final Integer loanId, @QueryParam("savingsAccountId") final Integer savingsAccountId,
@QueryParam("paged") final Boolean paged, @QueryParam("offset") final Integer offset, @QueryParam("limit") final Integer limit,
@QueryParam("orderBy") final String orderBy, @QueryParam("sortOrder") final String sortOrder) {
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
final PaginationParameters parameters = PaginationParameters.instance(paged, offset, limit, orderBy, sortOrder);
final String extraCriteria = getExtraCriteria(actionName, entityName, resourceId, makerId, makerDateTimeFrom, makerDateTimeTo,
checkerId, checkerDateTimeFrom, checkerDateTimeTo, processingResult, officeId, groupId, clientId, loanId, savingsAccountId);
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (parameters.isPaged()){
final Page<AuditData> auditEntries = this.auditReadPlatformService.retrievePaginatedAuditEntries(extraCriteria, settings.isIncludeJson(), parameters);
return this.toApiJsonSerializer.serialize(settings, auditEntries, this.RESPONSE_DATA_PARAMETERS);
}
final Collection<AuditData> auditEntries = this.auditReadPlatformService.retrieveAuditEntries(extraCriteria,
settings.isIncludeJson());
@@ -9,10 +9,14 @@ import java.util.Collection;
import org.mifosplatform.commands.data.AuditData;
import org.mifosplatform.commands.data.AuditSearchData;
import org.mifosplatform.infrastructure.core.data.PaginationParameters;
import org.mifosplatform.infrastructure.core.service.Page;
public interface AuditReadPlatformService {
Collection<AuditData> retrieveAuditEntries(String extraCriteria, boolean includeJson);
Page<AuditData> retrievePaginatedAuditEntries(String extraCriteria, boolean includeJson, PaginationParameters parameters);
Collection<AuditData> retrieveAllEntriesToBeChecked(String extraCriteria, boolean includeJson);
@@ -8,18 +8,25 @@ package org.mifosplatform.commands.service;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.mifosplatform.commands.data.AuditData;
import org.mifosplatform.commands.data.AuditSearchData;
import org.mifosplatform.commands.data.ProcessingResultLookup;
import org.mifosplatform.infrastructure.core.data.PaginationParameters;
import org.mifosplatform.infrastructure.core.data.PaginationParametersDataValidator;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.core.service.PaginationHelper;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.office.data.OfficeData;
@@ -49,6 +56,9 @@ import com.google.gson.JsonObject;
public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
private final static Logger logger = LoggerFactory.getLogger(AuditReadPlatformServiceImpl.class);
private final static Set<String> supportedOrderByValues = new HashSet<String>(Arrays.asList("id", "actionName", "entityName",
"resourceId", "subresourceId", "madeOnDate", "checkedOnDate", "officeName", "groupName", "clientName", "loanAccountNo",
"savingsAccountNo"));
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
@@ -58,12 +68,15 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
private final ClientReadPlatformService clientReadPlatformService;
private final LoanProductReadPlatformService loanProductReadPlatformService;
private final StaffReadPlatformService staffReadPlatformService;
private final PaginationHelper<AuditData> paginationHelper = new PaginationHelper<AuditData>();
private final PaginationParametersDataValidator paginationParametersDataValidator;
@Autowired
public AuditReadPlatformServiceImpl(final PlatformSecurityContext context, final RoutingDataSource dataSource,
final FromJsonHelper fromApiJsonHelper, final AppUserReadPlatformService appUserReadPlatformService,
final OfficeReadPlatformService officeReadPlatformService, final ClientReadPlatformService clientReadPlatformService,
final LoanProductReadPlatformService loanProductReadPlatformService, final StaffReadPlatformService staffReadPlatformService) {
final LoanProductReadPlatformService loanProductReadPlatformService, final StaffReadPlatformService staffReadPlatformService,
final PaginationParametersDataValidator paginationParametersDataValidator) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.fromApiJsonHelper = fromApiJsonHelper;
@@ -72,6 +85,7 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
this.clientReadPlatformService = clientReadPlatformService;
this.loanProductReadPlatformService = loanProductReadPlatformService;
this.staffReadPlatformService = staffReadPlatformService;
this.paginationParametersDataValidator = paginationParametersDataValidator;
}
private static final class AuditMapper implements RowMapper<AuditData> {
@@ -145,10 +159,44 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
if (StringUtils.isNotBlank(extraCriteria)) {
updatedExtraCriteria = " where (" + extraCriteria + ")";
}
updatedExtraCriteria += " order by aud.id DESC";
updatedExtraCriteria += " order by aud.id DESC limit " + PaginationParameters.getCheckedLimit(null);
return retrieveEntries("audit", updatedExtraCriteria, includeJson);
}
@Override
public Page<AuditData> retrievePaginatedAuditEntries(final String extraCriteria, final boolean includeJson, final PaginationParameters parameters) {
this.paginationParametersDataValidator.validateParameterValues(parameters, supportedOrderByValues, "audits");
final AppUser currentUser = this.context.authenticatedUser();
final String hierarchy = currentUser.getOffice().getHierarchy();
String updatedExtraCriteria = "";
if (StringUtils.isNotBlank(extraCriteria)) {
updatedExtraCriteria = " where (" + extraCriteria + ")";
}
final AuditMapper rm = new AuditMapper();
final StringBuilder sqlBuilder = new StringBuilder(200);
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
sqlBuilder.append(rm.schema(includeJson, hierarchy));
sqlBuilder.append(' ').append(updatedExtraCriteria);
if (parameters.isOrderByRequested()) {
sqlBuilder.append(' ').append(parameters.orderBySql());
}else {
sqlBuilder.append(' ').append(' ').append(" order by aud.id DESC");
}
if (parameters.isLimited()) {
sqlBuilder.append(' ').append(parameters.limitSql());
}
logger.info("sql: " + sqlBuilder.toString());
final String sqlCountRows = "SELECT FOUND_ROWS()";
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), new Object[] {}, rm);
}
@Override
public Collection<AuditData> retrieveAllEntriesToBeChecked(final String extraCriteria, final boolean includeJson) {
@@ -195,7 +243,7 @@ public class AuditReadPlatformServiceImpl implements AuditReadPlatformService {
return this.jdbcTemplate.query(sql, rm, new Object[] {});
}
@Override
public AuditData retrieveAuditEntry(final Long auditId) {
@@ -0,0 +1,115 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.core.data;
import org.apache.commons.lang.StringUtils;
/**
* <p>
* Immutable data object representing pagination parameter values.
* </p>
*/
public class PaginationParameters {
private final boolean paged;
private final Integer offset;
private final Integer limit;
private final String orderBy;
private final String sortOrder;
public static PaginationParameters instance (Boolean paged, Integer offset, Integer limit, String orderBy, String sortOrder){
if( null == paged) {
paged = false;
}
final Integer maxLimitAllowed = getCheckedLimit(limit);
return new PaginationParameters(paged, offset, maxLimitAllowed, orderBy, sortOrder);
}
private PaginationParameters(boolean paged, Integer offset, Integer limit, String orderBy, String sortOrder) {
this.paged = paged;
this.offset = offset;
this.limit = limit;
this.orderBy = orderBy;
this.sortOrder = sortOrder;
}
public static Integer getCheckedLimit(final Integer limit) {
final Integer maxLimitAllowed = 200;
// default to max limit first off
Integer checkedLimit = maxLimitAllowed;
if (limit != null && limit > 0) {
checkedLimit = limit;
} else if (limit != null) {
// unlimited case: limit provided and 0 or less
checkedLimit = null;
}
return checkedLimit;
}
public boolean isPaged() {
return this.paged;
}
public Integer getOffset() {
return this.offset;
}
public Integer getLimit() {
return this.limit;
}
public String getOrderBy() {
return this.orderBy;
}
public String getSortOrder() {
return this.sortOrder;
}
public boolean isOrderByRequested() {
return StringUtils.isNotBlank(this.orderBy);
}
public boolean isSortOrderProvided() {
return StringUtils.isNotBlank(this.sortOrder);
}
public boolean isLimited() {
return this.limit != null && this.limit.intValue() > 0;
}
public boolean isOffset() {
return this.offset != null;
}
public String orderBySql(){
final StringBuffer sql = new StringBuffer();
if (this.isOrderByRequested()) {
sql.append(" order by ").append(this.getOrderBy());
if (this.isSortOrderProvided()) {
sql.append(' ').append(this.getSortOrder());
}
}
return sql.toString();
}
public String limitSql(){
final StringBuffer sql = new StringBuffer();
if (this.isLimited()) {
sql.append(" limit ").append(this.getLimit());
if (this.isOffset()) {
sql.append(" offset ").append(this.getOffset());
}
}
return sql.toString();
}
}
@@ -0,0 +1,44 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.infrastructure.core.data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.springframework.stereotype.Component;
@Component
public class PaginationParametersDataValidator {
public static Set<String> sortOrderValues = new HashSet<String>(Arrays.asList("ASC", "DESC"));
public void validateParameterValues(PaginationParameters parameters, final Set<String> supportedOrdeByValues, final String resourceName) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (parameters.isOrderByRequested() && !supportedOrdeByValues.contains(parameters.getOrderBy())){
final String defaultUserMessage = "The orderBy value '" + parameters.getOrderBy() + "' is not supported. The supported orderBy values are " + supportedOrdeByValues.toString();
final ApiParameterError error = ApiParameterError.parameterError("validation.msg."+resourceName+".orderBy.value.is.not.supported",
defaultUserMessage, "orderBy", parameters.getOrderBy(), supportedOrdeByValues.toString());
dataValidationErrors.add(error);
}
if (parameters.isSortOrderProvided() && !sortOrderValues.contains(parameters.getSortOrder().toUpperCase())){
final String defaultUserMessage = "The sortOrder value '" + parameters.getSortOrder() + "' is not supported. The supported sortOrder values are " + sortOrderValues.toString();
final ApiParameterError error = ApiParameterError.parameterError("validation.msg."+resourceName+".sortOrder.value.is.not.supported",
defaultUserMessage, "sortOrder", parameters.getSortOrder(), sortOrderValues.toString());
dataValidationErrors.add(error);
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}