Merge remote-tracking branch 'ashok/MIFOSX-36'

This commit is contained in:
Keith Woodlock
2013-02-06 16:39:28 +00:00
14 changed files with 395 additions and 9 deletions
@@ -16,6 +16,7 @@ public class CommandWrapper {
private final String json;
private final Long apptableId;
private final Long datatableId;
private final Long codeId;
public static CommandWrapper wrap(final String actionName, final String enityName, final Long resourceId) {
return new CommandWrapper(null, actionName, enityName, resourceId);
@@ -38,12 +39,13 @@ public class CommandWrapper {
this.entityId = resourceId;
this.apptableId = null;
this.datatableId = null;
this.codeId = null;
this.href = null;
this.json = null;
}
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final String actionName,
final String entityName, final Long entityId, final Long apptableId, final Long datatableId, final String href,
final String entityName, final Long entityId, final Long apptableId, final Long datatableId, final Long codeId, final String href,
final String json) {
this.commandId = null;
this.officeId = officeId;
@@ -56,6 +58,7 @@ public class CommandWrapper {
this.entityId = entityId;
this.apptableId = apptableId;
this.datatableId = datatableId;
this.codeId = codeId;
this.href = href;
this.json = json;
}
@@ -87,7 +90,11 @@ public class CommandWrapper {
public String getTaskPermissionName() {
return this.taskPermissionName;
}
public Long getCodeId(){
return this.codeId;
}
public String getHref() {
return this.href;
}
@@ -170,6 +177,10 @@ public class CommandWrapper {
return this.entityName.equalsIgnoreCase("CODE");
}
public boolean isCodeValueResource() {
return this.entityName.equalsIgnoreCase("CODEVALUE");
}
public boolean isStaffResource() {
return this.entityName.equalsIgnoreCase("STAFF");
}
@@ -15,10 +15,11 @@ public class CommandWrapperBuilder {
private String json = "{}";
private Long apptableId;
private Long datatableId;
private Long codeId;
public CommandWrapper build() {
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.actionName, this.entityName, this.entityId,
this.apptableId, this.datatableId, this.href, this.json);
this.apptableId, this.datatableId, this.codeId, this.href, this.json);
}
// public CommandWrapperBuilder withEntityId(final Long withId) {
@@ -555,4 +556,13 @@ public class CommandWrapperBuilder {
this.href = "/loans/loanreassignment";
return this;
}
public CommandWrapperBuilder createCodeValue(final Long codeId) {
this.actionName = "CREATE";
this.entityName = "CODEVALUE";
this.codeId = codeId;
this.href = "/codes/" + codeId + "/codevalues/template";
return this;
}
}
@@ -53,7 +53,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(json);
final JsonCommand command = JsonCommand.from(json, parsedCommand, this.fromApiJsonHelper, wrapper.getEntityName(),
wrapper.getEntityId(), wrapper.getGroupId(), wrapper.getClientId(), wrapper.getLoanId(), wrapper.getApptableId(),
wrapper.getDatatableId());
wrapper.getDatatableId(), wrapper.getCodeId());
result = this.processAndLogCommandService.processAndLogCommand(wrapper, command, isApprovedByChecker);
} catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) {
@@ -63,7 +63,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(jsonToUse);
final JsonCommand command = JsonCommand.from(jsonToUse, parsedCommand, this.fromApiJsonHelper, wrapper.getEntityName(),
wrapper.getEntityId(), wrapper.getGroupId(), wrapper.getClientId(), wrapper.getLoanId(), wrapper.getApptableId(),
wrapper.getDatatableId());
wrapper.getDatatableId(), wrapper.getCodeId());
result = this.processAndLogCommandService.logCommand(wrapper, command);
}
@@ -200,6 +200,16 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isCodeValueResource()) {
if (wrapper.isCreate()) {
handler = applicationContext.getBean("createCodeValueCommandHandler", NewCommandSourceHandler.class);
//} else if (wrapper.isUpdate()) {
// handler = applicationContext.getBean("updateCodeCommandHandler", NewCommandSourceHandler.class);
//} else if (wrapper.isDelete()) {
// handler = applicationContext.getBean("deleteCodeCommandHandler", NewCommandSourceHandler.class);
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isCurrencyResource()) {
handler = applicationContext.getBean("updateCurrencyCommandHandler", NewCommandSourceHandler.class);
} else if (wrapper.isFundResource()) {
@@ -0,0 +1,40 @@
package org.mifosplatform.infrastructure.codes;
import java.util.HashSet;
import java.util.Set;
public class CodeConstants {
/***
* Enum of all parameters passed in while creating/updating a code and code value
***/
public static enum CODEVALUE_JSON_INPUT_PARAMS {
CODEVALUE_ID("id"), NAME("name"), POSITION("position");
private final String value;
private CODEVALUE_JSON_INPUT_PARAMS(final String value) {
this.value = value;
}
private static final Set<String> values = new HashSet<String>();
static {
for (CODEVALUE_JSON_INPUT_PARAMS type : CODEVALUE_JSON_INPUT_PARAMS.values()) {
values.add(type.value);
}
}
public static Set<String> getAllValues() {
return values;
}
@Override
public String toString() {
return name().toString().replaceAll("_", " ");
}
public String getValue() {
return this.value;
}
}
}
@@ -0,0 +1,87 @@
package org.mifosplatform.infrastructure.codes.api;
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.GET;
import javax.ws.rs.POST;
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.UriInfo;
import org.mifosplatform.commands.domain.CommandWrapper;
import org.mifosplatform.commands.service.CommandWrapperBuilder;
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
import org.mifosplatform.infrastructure.codes.data.CodeData;
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
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;
@Path("/codes/{codeId}/codevalues")
@Component
@Scope("singleton")
public class CodeValuesApiResource {
/**
* The set of parameters that are supported in response for {@link CodeData}
*/
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "position"));
private final String resourceNameForPermissions = "CODEVALUE";
private final PlatformSecurityContext context;
private final CodeValueReadPlatformService readPlatformService;
private final DefaultToApiJsonSerializer<CodeValueData> toApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@Autowired
public CodeValuesApiResource(final PlatformSecurityContext context, final CodeValueReadPlatformService readPlatformService,
final DefaultToApiJsonSerializer<CodeValueData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
this.context = context;
this.readPlatformService = readPlatformService;
this.toApiJsonSerializer = toApiJsonSerializer;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllCodeValues(@Context final UriInfo uriInfo, @PathParam("codeId") final Long codeId) {
context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions);
final Collection<CodeValueData> codeValues = this.readPlatformService.retrieveAllCodeValues(codeId);
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
return this.toApiJsonSerializer.serialize(settings, codeValues, RESPONSE_DATA_PARAMETERS);
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String createCodeValue(@PathParam("codeId") final Long codeId, final String apiRequestBodyAsJson) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().createCodeValue(codeId).withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
}
}
@@ -8,6 +8,8 @@ import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.codes.CodeConstants.CODEVALUE_JSON_INPUT_PARAMS;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity
@@ -46,4 +48,11 @@ public class CodeValue extends AbstractPersistable<Long> {
public int position() {
return position;
}
public static CodeValue fromJson(Code code, final JsonCommand command) {
final String label = command.stringValueOfParameterNamed(CODEVALUE_JSON_INPUT_PARAMS.NAME.getValue());
final Integer position = command.integerValueSansLocaleOfParameterNamed(CODEVALUE_JSON_INPUT_PARAMS.POSITION.getValue());
return new CodeValue(code, label, position.intValue());
}
}
@@ -0,0 +1,27 @@
package org.mifosplatform.infrastructure.codes.handler;
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
import org.mifosplatform.infrastructure.codes.service.CodeValueWritePlatformService;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class CreateCodeValueCommandHandler implements NewCommandSourceHandler {
private final CodeValueWritePlatformService writePlatformService;
@Autowired
public CreateCodeValueCommandHandler(final CodeValueWritePlatformService writePlatformService) {
this.writePlatformService = writePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.createCodeValue(command);
}
}
@@ -0,0 +1,81 @@
package org.mifosplatform.infrastructure.codes.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.codes.CodeConstants.CODEVALUE_JSON_INPUT_PARAMS;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Deserializer for code JSON to validate API request.
*/
@Component
public final class CodeValueCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = CODEVALUE_JSON_INPUT_PARAMS.getAllValues();
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public CodeValueCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateForCreate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("codevalue");
final JsonElement element = fromApiJsonHelper.parse(json);
final String name = fromApiJsonHelper.extractStringNamed(CODEVALUE_JSON_INPUT_PARAMS.NAME.getValue(), element);
baseDataValidator.reset().parameter(CODEVALUE_JSON_INPUT_PARAMS.NAME.getValue()).value(name).notBlank().notExceedingLengthOf(100);
final Integer position = fromApiJsonHelper.extractIntegerSansLocaleNamed(CODEVALUE_JSON_INPUT_PARAMS.POSITION.getValue(), element);
baseDataValidator.reset().parameter(CODEVALUE_JSON_INPUT_PARAMS.POSITION.getValue()).value(position).notBlank().integerGreaterThanZero();
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForUpdate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code");
final JsonElement element = fromApiJsonHelper.parse(json);
if (fromApiJsonHelper.parameterExists("name", element)) {
final String name = fromApiJsonHelper.extractStringNamed("name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank().notExceedingLengthOf(100);
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -21,4 +21,6 @@ public interface CodeValueReadPlatformService {
// system defined code value data
Collection<CodeValueData> retrieveCustomIdentifierCodeValues();
Collection<CodeValueData> retrieveAllCodeValues(final Long codeId);
}
@@ -52,4 +52,17 @@ public class CodeValueReadPlatformServiceImpl implements CodeValueReadPlatformSe
return this.jdbcTemplate.query(sql, rm, new Object[] { "Customer Identifier" });
}
@Override
public Collection<CodeValueData> retrieveAllCodeValues(Long codeId) {
context.authenticatedUser();
final CodeValueDataMapper rm = new CodeValueDataMapper();
final String sql = "select " + rm.schema() + "where cv.code_id = ? order by position";
return this.jdbcTemplate.query(sql, rm, new Object[] { codeId });
}
}
@@ -0,0 +1,13 @@
package org.mifosplatform.infrastructure.codes.service;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
public interface CodeValueWritePlatformService {
CommandProcessingResult createCodeValue(JsonCommand command);
//CommandProcessingResult updateCode(Long codeId, JsonCommand command);
//CommandProcessingResult deleteCode(Long codeId);
}
@@ -0,0 +1,77 @@
package org.mifosplatform.infrastructure.codes.service;
import org.mifosplatform.infrastructure.codes.domain.Code;
import org.mifosplatform.infrastructure.codes.domain.CodeRepository;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.codes.domain.CodeValueRepository;
import org.mifosplatform.infrastructure.codes.serialization.CodeValueCommandFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
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 CodeValueWritePlatformServiceJpaRepositoryImpl implements CodeValueWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(CodeValueWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final CodeValueRepository codeValueRepository;
private final CodeRepository codeRepository;
private final CodeValueCommandFromApiJsonDeserializer fromApiJsonDeserializer;
@Autowired
public CodeValueWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final CodeRepository codeRepository, final CodeValueRepository codeValueRepository,
final CodeValueCommandFromApiJsonDeserializer fromApiJsonDeserializer) {
this.context = context;
this.codeRepository = codeRepository;
this.codeValueRepository = codeValueRepository;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
}
@Transactional
@Override
public CommandProcessingResult createCodeValue(final JsonCommand command) {
try {
context.authenticatedUser();
this.fromApiJsonDeserializer.validateForCreate(command.json());
final Long codeId = command.getCodeId();
final Code code = this.codeRepository.findOne(codeId);
final CodeValue codeValue = CodeValue.fromJson(code, command);
this.codeValueRepository.save(codeValue);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(codeValue.getId()).build();
} catch (DataIntegrityViolationException dve) {
handleCodeValueDataIntegrityIssues(command, dve);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.build();
}
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue
* is.
*/
private void handleCodeValueDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("code_value_duplicate")) {
final String name = command.stringValueOfParameterNamed("name");
throw new PlatformDataIntegrityException("error.msg.code.value.duplicate.label", "A code value with lable '" + name + "' already exists");
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.cund.unknown.data.integrity.issue",
"Unknown data integrity issue with resource: " + realCause.getMessage());
}
}
@@ -33,22 +33,23 @@ public final class JsonCommand {
private final String entityName;
private final Long apptableId;
private final Long datatableId;
private final Long codeId;
public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper,
final String entityName, final Long resourceId, final Long groupId, final Long clientId, final Long loanId,
final Long apptableId, final Long datatableId) {
final Long apptableId, final Long datatableId, final Long codeId) {
return new JsonCommand(null, jsonCommand, parsedCommand, fromApiJsonHelper, entityName, resourceId, groupId, clientId, loanId,
apptableId, datatableId);
apptableId, datatableId, codeId);
}
public static JsonCommand fromExistingCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
final FromJsonHelper fromApiJsonHelper, final Long resourceId) {
return new JsonCommand(commandId, jsonCommand, parsedCommand, fromApiJsonHelper, null, resourceId, null, null, null, null, null);
return new JsonCommand(commandId, jsonCommand, parsedCommand, fromApiJsonHelper, null, resourceId, null, null, null, null, null, null);
}
public JsonCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long groupId,
final Long clientId, final Long loanId, final Long apptableId, final Long datatableId) {
final Long clientId, final Long loanId, final Long apptableId, final Long datatableId, final Long codeId) {
this.commandId = commandId;
this.jsonCommand = jsonCommand;
this.parsedCommand = parsedCommand;
@@ -60,6 +61,7 @@ public final class JsonCommand {
this.loanId = loanId;
this.apptableId = apptableId;
this.datatableId = datatableId;
this.codeId = codeId;
}
public String json() {
@@ -102,6 +104,10 @@ public final class JsonCommand {
return this.datatableId;
}
public Long getCodeId(){
return this.codeId;
}
private boolean differenceExists(final LocalDate baseValue, final LocalDate workingCopyValue) {
boolean differenceExists = false;