diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java index 443032bbb..5c5d85a6b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandSource.java @@ -92,6 +92,10 @@ public class CommandSource extends AbstractPersistable { public Long resourceId() { return this.resourceId; } + + public boolean hasJson() { + return StringUtils.isNotBlank(this.commandAsJson); + } public String json() { return this.commandAsJson; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/ClientCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/ClientCommandHandler.java index 22371aba2..c8bd30987 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/ClientCommandHandler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/ClientCommandHandler.java @@ -46,11 +46,9 @@ public class ClientCommandHandler implements CommandSourceHandler { final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); CommandSource commandSourceResult = commandSource.copy(); - Long newResourceId = null; - if (commandSource.isCreate()) { try { - newResourceId = this.clientWritePlatformService.createClient(command); + Long newResourceId = this.clientWritePlatformService.createClient(command); commandSourceResult.markAsChecked(maker, asToday); commandSourceResult.updateResourceId(newResourceId); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { @@ -59,8 +57,6 @@ public class ClientCommandHandler implements CommandSourceHandler { } else if (commandSource.isUpdate()) { try { EntityIdentifier result = this.clientWritePlatformService.updateClientDetails(commandSource.resourceId(), command); - newResourceId = result.getEntityId(); - final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); commandSourceResult.updateJsonTo(jsonOfChangesOnly); @@ -70,8 +66,7 @@ public class ClientCommandHandler implements CommandSourceHandler { } } else if (commandSource.isDelete()) { try { - EntityIdentifier result = this.clientWritePlatformService.deleteClient(commandSource.resourceId(), command); - newResourceId = result.getEntityId(); + this.clientWritePlatformService.deleteClient(commandSource.resourceId(), command); commandSourceResult.markAsChecked(maker, asToday); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { // swallow this rollback transaction by design @@ -102,7 +97,11 @@ public class ClientCommandHandler implements CommandSourceHandler { "UPDATE_CLIENT_CHECKER"); context.authenticatedUser().validateHasPermissionTo("UPDATE_CLIENT_CHECKER", allowedPermissions); - this.clientWritePlatformService.updateClientDetails(commandSourceResult.resourceId(), command); + EntityIdentifier result = this.clientWritePlatformService.updateClientDetails(commandSourceResult.resourceId(), command); + + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); + commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isDelete()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "PORTFOLIO_MANAGEMENT_SUPER_USER", diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/CodeCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/CodeCommandHandler.java index df7a6e15e..0decf5145 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/CodeCommandHandler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/CodeCommandHandler.java @@ -5,27 +5,35 @@ import java.util.List; import org.joda.time.LocalDate; import org.mifosplatform.commands.domain.CommandSource; -import org.mifosplatform.infrastructure.codes.command.CodeCommand; -import org.mifosplatform.infrastructure.codes.serialization.CodeCommandFromCommandJsonDeserializer; import org.mifosplatform.infrastructure.codes.service.CodeWritePlatformService; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.infrastructure.core.serialization.ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.portfolio.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException; import org.mifosplatform.useradministration.domain.AppUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.google.gson.JsonElement; + @Service public class CodeCommandHandler implements CommandSourceHandler { private final PlatformSecurityContext context; - private final CodeCommandFromCommandJsonDeserializer fromCommandJsonDeserializer; + private final FromJsonHelper fromApiJsonHelper; + private final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer; private final CodeWritePlatformService writePlatformService; @Autowired public CodeCommandHandler(final PlatformSecurityContext context, - final CodeCommandFromCommandJsonDeserializer fromCommandJsonDeserializer, final CodeWritePlatformService writePlatformService) { + final FromJsonHelper fromApiJsonHelper, + final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer, + final CodeWritePlatformService writePlatformService) { this.context = context; - this.fromCommandJsonDeserializer = fromCommandJsonDeserializer; + this.fromApiJsonHelper = fromApiJsonHelper; + this.toApiJsonSerializer = toApiJsonSerializer; this.writePlatformService = writePlatformService; } @@ -36,8 +44,9 @@ public class CodeCommandHandler implements CommandSourceHandler { final LocalDate asToday = new LocalDate(); final Long resourceId = commandSource.resourceId(); - final CodeCommand command = this.fromCommandJsonDeserializer.commandFromCommandJson(resourceId, commandSource.json()); - + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); + final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); + CommandSource commandSourceResult = commandSource.copy(); if (commandSource.isCreate()) { @@ -50,7 +59,10 @@ public class CodeCommandHandler implements CommandSourceHandler { } } else if (commandSource.isUpdate()) { try { - this.writePlatformService.updateCode(command); + EntityIdentifier result = this.writePlatformService.updateCode(resourceId, command); + + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); commandSourceResult.markAsChecked(maker, asToday); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { @@ -58,7 +70,7 @@ public class CodeCommandHandler implements CommandSourceHandler { } } else if (commandSource.isDelete()) { try { - this.writePlatformService.deleteCode(command); + this.writePlatformService.deleteCode(resourceId, command); commandSourceResult.markAsChecked(maker, asToday); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { // swallow this rollback transaction by design @@ -74,7 +86,8 @@ public class CodeCommandHandler implements CommandSourceHandler { final AppUser checker = context.authenticatedUser(); Long resourceId = commandSourceResult.resourceId(); - final CodeCommand command = this.fromCommandJsonDeserializer.commandFromCommandJson(resourceId, commandSourceResult.json(), true); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceResult.json()); + final JsonCommand command = JsonCommand.withMakerCheckerApproval(commandSourceResult.json(), parsedCommand, this.fromApiJsonHelper); if (commandSourceResult.isCreate()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "CREATE_CODE_MAKER"); @@ -87,13 +100,17 @@ public class CodeCommandHandler implements CommandSourceHandler { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "UPDATE_CODE_MAKER"); context.authenticatedUser().validateHasPermissionTo("UPDATE_CODE_MAKER", allowedPermissions); - this.writePlatformService.updateCode(command); + EntityIdentifier result = this.writePlatformService.updateCode(resourceId, command); + + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); + commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isDelete()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "DELETE_CODE_MAKER"); context.authenticatedUser().validateHasPermissionTo("DELETE_CODE_MAKER", allowedPermissions); - this.writePlatformService.deleteCode(command); + this.writePlatformService.deleteCode(resourceId, command); commandSourceResult.markAsChecked(checker, new LocalDate()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java index 712587459..79d8b86db 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java @@ -36,7 +36,10 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio final CommandSource commandSourceInput = CommandSource.createdBy(apiOperation, resource, resourceId, commandSerializedAsJson, maker, asToday); final CommandSource commandSourceResult = this.commandSourceHandlerDelegator.handleCommandWithSupportForRollback(commandSourceInput); - commandSourceRepository.save(commandSourceResult); + + if (commandSourceResult.hasJson()) { + commandSourceRepository.save(commandSourceResult); + } return EntityIdentifier.makerChecker(commandSourceResult.resourceId(), commandSourceResult.getId()); } @@ -49,7 +52,9 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio final CommandSource commandSourceInput = this.commandSourceRepository.findOne(id); final CommandSource commandSourceResult = this.commandSourceHandlerDelegator.handleCommandForCheckerApproval(commandSourceInput); - commandSourceRepository.save(commandSourceResult); + if (commandSourceResult.hasJson()) { + commandSourceRepository.save(commandSourceResult); + } return EntityIdentifier.makerChecker(commandSourceResult.resourceId(), commandSourceResult.getId()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/api/CodesApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/api/CodesApiResource.java index d920be929..79eb42034 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/api/CodesApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/api/CodesApiResource.java @@ -20,7 +20,6 @@ import javax.ws.rs.core.UriInfo; import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.infrastructure.codes.data.CodeData; -import org.mifosplatform.infrastructure.codes.serialization.CodeCommandFromApiJsonDeserializer; import org.mifosplatform.infrastructure.codes.service.CodeReadPlatformService; import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; @@ -44,19 +43,16 @@ public class CodesApiResource { private final PlatformSecurityContext context; private final CodeReadPlatformService readPlatformService; - private final CodeCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final DefaultToApiJsonSerializer toApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @Autowired public CodesApiResource(final PlatformSecurityContext context, final CodeReadPlatformService readPlatformService, - final CodeCommandFromApiJsonDeserializer fromApiJsonDeserializer, final DefaultToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; this.readPlatformService = readPlatformService; - this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.toApiJsonSerializer = toApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; @@ -83,10 +79,8 @@ public class CodesApiResource { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "CREATE_CODE"); context.authenticatedUser().validateHasPermissionTo("CREATE_CODE", allowedPermissions); - final String commandSerializedAsJson = this.fromApiJsonDeserializer.serializedCommandJsonFromApiJson(apiRequestBodyAsJson); - final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "codes", null, - commandSerializedAsJson); + apiRequestBodyAsJson); return this.toApiJsonSerializer.serialize(result); } @@ -112,10 +106,8 @@ public class CodesApiResource { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "UPDATE_CODE"); context.authenticatedUser().validateHasPermissionTo("UPDATE_CODE", allowedPermissions); - final String commandSerializedAsJson = this.fromApiJsonDeserializer.serializedCommandJsonFromApiJson(codeId, apiRequestBodyAsJson); - final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "codes", codeId, - commandSerializedAsJson); + apiRequestBodyAsJson); return this.toApiJsonSerializer.serialize(result); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/command/CodeCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/command/CodeCommand.java index b78120c2e..ee29bec52 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/command/CodeCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/command/CodeCommand.java @@ -2,7 +2,6 @@ package org.mifosplatform.infrastructure.codes.command; import java.util.ArrayList; import java.util.List; -import java.util.Set; import org.mifosplatform.infrastructure.core.data.ApiParameterError; import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; @@ -10,21 +9,12 @@ import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidation /** *

Immutable command for creating or updating details of a code.

- * - *

Transient fields are not intended for serialization.

*/ public class CodeCommand { private final String name; - private final transient Set parametersPassedInRequest; - private final transient boolean makerCheckerApproval; - private final transient Long id; - - public CodeCommand(final Set modifiedParameters, final boolean makerCheckerApproval, final Long id, final String name) { - this.parametersPassedInRequest = modifiedParameters; - this.makerCheckerApproval = makerCheckerApproval; - this.id = id; + public CodeCommand(final String name) { this.name = name; } @@ -42,26 +32,11 @@ public class CodeCommand { List dataValidationErrors = new ArrayList(); DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code"); - baseDataValidator.reset().parameter("id").value(this.id).notNull(); - baseDataValidator.reset().parameter("name").value(this.name).ignoreIfNull().notBlank(); + baseDataValidator.reset().parameter("name").value(this.name).notBlank(); + baseDataValidator.reset().anyOfNotNull(this.name); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } } - - public String getName() { - return this.name; - } - - public Long getId() { - return this.id; - } - - public boolean isNameChanged() { - return this.parametersPassedInRequest.contains("name"); - } - - public boolean isApprovedByChecker() { - return this.makerCheckerApproval; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java index 7a95f9664..4c9b7b185 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/domain/Code.java @@ -1,5 +1,7 @@ package org.mifosplatform.infrastructure.codes.domain; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Set; import javax.persistence.CascadeType; @@ -12,8 +14,8 @@ import javax.persistence.UniqueConstraint; import org.apache.commons.lang.StringUtils; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollectionOption; -import org.mifosplatform.infrastructure.codes.command.CodeCommand; import org.mifosplatform.infrastructure.codes.exception.SystemDefinedCodeCannotBeChangedException; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.springframework.data.jpa.domain.AbstractPersistable; @Entity @@ -25,14 +27,15 @@ public class Code extends AbstractPersistable { @Column(name = "is_system_defined") private final boolean systemDefined; - + @SuppressWarnings("unused") @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL, mappedBy = "code", orphanRemoval = true) private Set values; - public static Code createNew(final String codeName) { - return new Code(codeName); + public static Code fromJson(final JsonCommand command) { + final String name = command.stringValueOfParameterNamed("name"); + return new Code(name); } protected Code() { @@ -43,23 +46,28 @@ public class Code extends AbstractPersistable { this.name = name; this.systemDefined = false; } - + public String name() { return this.name; } - + public boolean isSystemDefined() { return this.systemDefined; } - public void update(final CodeCommand command) { - - if (systemDefined) { - throw new SystemDefinedCodeCannotBeChangedException(); + public Map update(final JsonCommand command) { + + if (systemDefined) { throw new SystemDefinedCodeCannotBeChangedException(); } + + final Map actualChanges = new LinkedHashMap(1); + + final String firstnameParamName = "name"; + if (command.isChangeInStringParameterNamed(firstnameParamName, this.name)) { + final String newValue = command.stringValueOfParameterNamed(firstnameParamName); + actualChanges.put(firstnameParamName, newValue); + this.name = StringUtils.defaultIfEmpty(newValue, null); } - if (command.isNameChanged()) { - this.name = StringUtils.defaultIfEmpty(command.getName(), null); - } + return actualChanges; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromApiJsonDeserializer.java index e24f8d78b..cb9b15d5a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromApiJsonDeserializer.java @@ -14,6 +14,7 @@ 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; /** @@ -26,25 +27,24 @@ public final class CodeCommandFromApiJsonDeserializer extends AbstractFromApiJso * The parameters supported for this command. */ private final Set supportedParameters = new HashSet(Arrays.asList("name")); - private final FromJsonHelper fromApiJsonHelper; - private final CodeCommandFromCommandJsonDeserializer fromCommandJsonDeserializer; @Autowired - public CodeCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, - final CodeCommandFromCommandJsonDeserializer fromCommandJsonDeserializer, final CommandSerializer commandSerializerService) { + public CodeCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, final CommandSerializer commandSerializerService) { super(commandSerializerService); this.fromApiJsonHelper = fromApiJsonHelper; - this.fromCommandJsonDeserializer = fromCommandJsonDeserializer; } @Override - public CodeCommand commandFromApiJson(final Long codeId, final String json) { + public CodeCommand commandFromApiJson(@SuppressWarnings("unused") final Long codeId, final String json) { final Type typeOfMap = new TypeToken>() {}.getType(); fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); - return this.fromCommandJsonDeserializer.commandFromCommandJson(codeId, json); + final JsonElement element = fromApiJsonHelper.parse(json); + final String name = fromApiJsonHelper.extractStringNamed("name", element); + + return new CodeCommand(name); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromCommandJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromCommandJsonDeserializer.java deleted file mode 100644 index 3a0f1d9c1..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/serialization/CodeCommandFromCommandJsonDeserializer.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.mifosplatform.infrastructure.codes.serialization; - -import java.util.HashSet; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -import org.mifosplatform.infrastructure.codes.command.CodeCommand; -import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; -import org.mifosplatform.infrastructure.core.serialization.AbstractFromCommandJsonDeserializer; -import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.google.gson.JsonElement; - -/** - * - */ -@Component -public final class CodeCommandFromCommandJsonDeserializer extends AbstractFromCommandJsonDeserializer { - - private final FromJsonHelper fromJsonHelper; - - @Autowired - public CodeCommandFromCommandJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { - this.fromJsonHelper = fromApiJsonHelper; - } - - @Override - public CodeCommand commandFromCommandJson(Long codeId, String commandAsJson, boolean makerCheckerApproval) { - if (StringUtils.isBlank(commandAsJson)) { throw new InvalidJsonException(); } - - final Set parametersPassedInRequest = new HashSet(); - - final JsonElement element = fromJsonHelper.parse(commandAsJson); - final String name = fromJsonHelper.extractStringNamed("name", element, parametersPassedInRequest); - - return new CodeCommand(parametersPassedInRequest, makerCheckerApproval, codeId, name); - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformService.java index 02f09715c..42623cf62 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformService.java @@ -1,13 +1,13 @@ package org.mifosplatform.infrastructure.codes.service; -import org.mifosplatform.infrastructure.codes.command.CodeCommand; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; public interface CodeWritePlatformService { - Long createCode(CodeCommand command); + Long createCode(JsonCommand command); - Long updateCode(CodeCommand command); + EntityIdentifier updateCode(Long codeId, JsonCommand command); - EntityIdentifier deleteCode(CodeCommand command); + EntityIdentifier deleteCode(Long codeId, JsonCommand command); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java index ab65184d0..2455fa581 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/codes/service/CodeWritePlatformServiceJpaRepositoryImpl.java @@ -1,10 +1,14 @@ package org.mifosplatform.infrastructure.codes.service; +import java.util.Map; + import org.mifosplatform.infrastructure.codes.command.CodeCommand; import org.mifosplatform.infrastructure.codes.domain.Code; import org.mifosplatform.infrastructure.codes.domain.CodeRepository; import org.mifosplatform.infrastructure.codes.exception.CodeNotFoundException; import org.mifosplatform.infrastructure.codes.exception.SystemDefinedCodeCannotBeChangedException; +import org.mifosplatform.infrastructure.codes.serialization.CodeCommandFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; @@ -24,27 +28,30 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf private final PlatformSecurityContext context; private final CodeRepository codeRepository; - private final ConfigurationDomainService configurationDomainService; + private final CodeCommandFromApiJsonDeserializer fromApiJsonDeserializer; @Autowired public CodeWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final CodeRepository codeRepository, - final ConfigurationDomainService configurationDomainService) { + final ConfigurationDomainService configurationDomainService, + final CodeCommandFromApiJsonDeserializer fromApiJsonDeserializer) { this.context = context; this.codeRepository = codeRepository; this.configurationDomainService = configurationDomainService; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; } @Transactional @Override - public Long createCode(final CodeCommand command) { + public Long createCode(final JsonCommand command) { try { context.authenticatedUser(); - command.validateForCreate(); - - final Code code = Code.createNew(command.getName()); + + final CodeCommand codeCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); + codeCommand.validateForCreate(); + final Code code = Code.fromJson(command); this.codeRepository.save(code); if (this.configurationDomainService.isMakerCheckerEnabledForTask("CREATE_CODE") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); } @@ -57,47 +64,36 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf @Transactional @Override - public Long updateCode(final CodeCommand command) { + public EntityIdentifier updateCode(final Long codeId, final JsonCommand command) { try { context.authenticatedUser(); - command.validateForUpdate(); + final CodeCommand codeCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); + codeCommand.validateForUpdate(); - final Code code = retrieveCodeBy(command.getId()); - code.update(command); + final Code code = retrieveCodeBy(codeId); + Map changes = code.update(command); - this.codeRepository.save(code); + if (!changes.isEmpty()) { + this.codeRepository.save(code); + } if (this.configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_CODE") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); } - return code.getId(); + return EntityIdentifier.withChanges(codeId, changes); } catch (DataIntegrityViolationException dve) { handleCodeDataIntegrityIssues(command, dve); - return Long.valueOf(-1); + return null; } } - /* - * Guaranteed to throw an exception no matter what the data integrity issue - * is. - */ - private void handleCodeDataIntegrityIssues(final CodeCommand command, final DataIntegrityViolationException dve) { - Throwable realCause = dve.getMostSpecificCause(); - if (realCause.getMessage().contains("code_name_org")) { throw new PlatformDataIntegrityException("error.msg.code.duplicate.name", - "A code with name '" + command.getName() + "' 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()); - } - @Transactional @Override - public EntityIdentifier deleteCode(final CodeCommand command) { + public EntityIdentifier deleteCode(final Long codeId, final JsonCommand command) { context.authenticatedUser(); - final Code code = retrieveCodeBy(command.getId()); + final Code code = retrieveCodeBy(codeId); if (code.isSystemDefined()) { throw new SystemDefinedCodeCannotBeChangedException(); } @@ -114,4 +110,20 @@ public class CodeWritePlatformServiceJpaRepositoryImpl implements CodeWritePlatf if (code == null) { throw new CodeNotFoundException(codeId.toString()); } return code; } + + /* + * Guaranteed to throw an exception no matter what the data integrity issue + * is. + */ + private void handleCodeDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { + Throwable realCause = dve.getMostSpecificCause(); + if (realCause.getMessage().contains("code_name_org")) { + final String name = command.stringValueOfParameterNamed("name"); + throw new PlatformDataIntegrityException("error.msg.code.duplicate.name", + "A code with name '" + 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()); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java index d062115d1..509940996 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java @@ -7,7 +7,10 @@ import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import com.google.gson.JsonElement; /** - * Represents JSON based command. + * Immutable representation of a command. + * + * Wraps the provided JSON with convenience functions for extracting parameter + * values and checking for changes against an existing value. */ public final class JsonCommand { @@ -19,12 +22,14 @@ public final class JsonCommand { public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper) { return new JsonCommand(jsonCommand, parsedCommand, fromApiJsonHelper, false); } - - public static JsonCommand withMakerCheckerApproval(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper) { + + public static JsonCommand withMakerCheckerApproval(final String jsonCommand, final JsonElement parsedCommand, + final FromJsonHelper fromApiJsonHelper) { return new JsonCommand(jsonCommand, parsedCommand, fromApiJsonHelper, true); } - public JsonCommand(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper, final boolean approvedByChecker) { + public JsonCommand(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper, + final boolean approvedByChecker) { this.jsonCommand = jsonCommand; this.parsedCommand = parsedCommand; this.fromApiJsonHelper = fromApiJsonHelper; @@ -38,7 +43,7 @@ public final class JsonCommand { public boolean isApprovedByChecker() { return this.approvedByChecker; } - + private boolean differenceExists(LocalDate baseValue, LocalDate workingCopyValue) { boolean differenceExists = false; @@ -62,7 +67,7 @@ public final class JsonCommand { return differenceExists; } - + private boolean differenceExists(final Long baseValue, final Long workingCopyValue) { boolean differenceExists = false; @@ -74,11 +79,11 @@ public final class JsonCommand { return differenceExists; } - + private boolean parameterExists(final String parameterName) { return this.fromApiJsonHelper.parameterExists(parameterName, parsedCommand); } - + public String dateFormat() { return stringValueOfParameterNamed("dateFormat"); } @@ -97,7 +102,7 @@ public final class JsonCommand { } public Long longValueOfParameterNamed(final String parameterName) { - return this.fromApiJsonHelper.extractLongNamed(parameterName, parsedCommand); + return this.fromApiJsonHelper.extractLongNamed(parameterName, parsedCommand); } public boolean isChangeInLocalDateParameterNamed(final String parameterName, final LocalDate existingValue) { @@ -108,7 +113,7 @@ public final class JsonCommand { } return isChanged; } - + public LocalDate localDateValueOfParameterNamed(final String parameterName) { return this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand); } @@ -121,7 +126,7 @@ public final class JsonCommand { } return isChanged; } - + public String stringValueOfParameterNamed(final String parameterName) { final String value = this.fromApiJsonHelper.extractStringNamed(parameterName, parsedCommand); return StringUtils.defaultIfEmpty(value, ""); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java index a397a96d7..a2da8a0e6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java @@ -23,7 +23,7 @@ public class EntityIdentifier { public static EntityIdentifier makerChecker(final Long resourceId, final Long makerCheckerId) { return new EntityIdentifier(resourceId, makerCheckerId, null); } - + public static EntityIdentifier withChanges(final Long resourceId, final Map changesOnly) { return new EntityIdentifier(resourceId, null, changesOnly); } @@ -51,6 +51,10 @@ public class EntityIdentifier { } public Map getChanges() { - return this.changes; + Map checkIfEmpty = null; + if (!this.changes.isEmpty()) { + checkIfEmpty = this.changes; + } + return checkIfEmpty; } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson.java index 81132c109..acf2a6676 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson.java @@ -28,6 +28,11 @@ public final class ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson { } public String serialize(final Object result) { - return this.gson.toJson(result); + String returnedResult = null; + final String serializedResult = this.gson.toJson(result); + if (!"null".equalsIgnoreCase(serializedResult)) { + returnedResult = serializedResult; + } + return returnedResult; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/serialization/ClientCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/serialization/ClientCommandFromApiJsonDeserializer.java index 89b3b4af7..a2130f381 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/serialization/ClientCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/serialization/ClientCommandFromApiJsonDeserializer.java @@ -46,16 +46,13 @@ public final class ClientCommandFromApiJsonDeserializer extends AbstractFromApiJ fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); - final Set parametersPassedInRequest = new HashSet(); - final JsonElement element = fromApiJsonHelper.parse(json); - final Long officeId = fromApiJsonHelper.extractLongNamed("officeId", element, parametersPassedInRequest); - final String externalId = fromApiJsonHelper.extractStringNamed("externalId", element, parametersPassedInRequest); - final String firstname = fromApiJsonHelper.extractStringNamed("firstname", element, parametersPassedInRequest); - final String lastname = fromApiJsonHelper.extractStringNamed("lastname", element, parametersPassedInRequest); - final String clientOrBusinessName = fromApiJsonHelper - .extractStringNamed("clientOrBusinessName", element, parametersPassedInRequest); - final LocalDate joiningDate = fromApiJsonHelper.extractLocalDateNamed("joiningDate", element, parametersPassedInRequest); + final Long officeId = fromApiJsonHelper.extractLongNamed("officeId", element); + final String externalId = fromApiJsonHelper.extractStringNamed("externalId", element); + final String firstname = fromApiJsonHelper.extractStringNamed("firstname", element); + final String lastname = fromApiJsonHelper.extractStringNamed("lastname", element); + final String clientOrBusinessName = fromApiJsonHelper.extractStringNamed("clientOrBusinessName", element); + final LocalDate joiningDate = fromApiJsonHelper.extractLocalDateNamed("joiningDate", element); return new ClientCommand(externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 37edb8ca5..72daed081 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -155,7 +155,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP clientForUpdate.changeOffice(newOffice); } - this.clientRepository.save(clientForUpdate); + if (!changesOnly.isEmpty()) { + this.clientRepository.save(clientForUpdate); + } if (this.configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_CLIENT") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); }