diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java index 7de327eee..fde9c2cb4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/FundsApiResource.java @@ -1,8 +1,6 @@ package org.mifosng.platform.api; -import java.lang.reflect.Type; import java.util.Collection; -import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -19,6 +17,7 @@ import javax.ws.rs.core.UriInfo; import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.FundData; +import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService; import org.mifosng.platform.fund.service.FundReadPlatformService; import org.mifosng.platform.fund.service.FundWritePlatformService; @@ -26,9 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - @Path("/funds") @Component @Scope("singleton") @@ -43,12 +39,15 @@ public class FundsApiResource { @Autowired private FundWritePlatformService writePlatformService; + @Autowired + private ApiDataConversionService apiDataConversionService; + @Autowired private ApiJSONFormattingService jsonFormattingService; @GET - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public String retrieveFunds(@Context UriInfo uriInfo) { Collection funds = this.readPlatformService.retrieveAllFunds(); @@ -62,22 +61,8 @@ public class FundsApiResource { @Produces({MediaType.APPLICATION_JSON}) public Response createFund(final String jsonRequestBody) { - Gson gson = new Gson(); - Type typeOfMap = new TypeToken>(){}.getType(); - Map requestMap = gson.fromJson(jsonRequestBody, typeOfMap); - - String name = null; - if (requestMap.containsKey("name")) { - name = requestMap.get("name"); - } + FundCommand command = this.apiDataConversionService.convertJsonToFundCommand(null, jsonRequestBody); - String externalId = null; - if (requestMap.containsKey("externalId")) { - externalId = requestMap.get("externalId"); - } - - FundCommand command = new FundCommand(name, externalId); - Long fundId = this.writePlatformService.createFund(command); return Response.ok().entity(new EntityIdentifier(fundId)).build(); @@ -85,8 +70,8 @@ public class FundsApiResource { @GET @Path("{fundId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public String retreiveOffice(@PathParam("fundId") final Long fundId, @Context UriInfo uriInfo) { FundData fund = this.readPlatformService.retrieveFund(fundId); @@ -102,23 +87,8 @@ public class FundsApiResource { @Produces({MediaType.APPLICATION_JSON}) public Response updateFund(@PathParam("fundId") final Long fundId, final String jsonRequestBody) { - Gson gson = new Gson(); - Type typeOfMap = new TypeToken>(){}.getType(); - Map requestMap = gson.fromJson(jsonRequestBody, typeOfMap); - - String name = null; - if (requestMap.containsKey("name")) { - name = requestMap.get("name"); - } + FundCommand command = this.apiDataConversionService.convertJsonToFundCommand(fundId, jsonRequestBody); - String externalId = null; - if (requestMap.containsKey("externalId")) { - externalId = requestMap.get("externalId"); - } - - FundCommand command = new FundCommand(name, externalId); - command.setId(fundId); - Long entityId = this.writePlatformService.updateFund(command); return Response.ok().entity(new EntityIdentifier(entityId)).build(); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductsApiResource.java similarity index 95% rename from mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java rename to mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductsApiResource.java index eec824274..38dd0005e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductsApiResource.java @@ -28,7 +28,7 @@ import org.springframework.stereotype.Component; @Path("/loanproducts") @Component @Scope("singleton") -public class LoanProductApiResource { +public class LoanProductsApiResource { private String defaultFieldList = "principal,inArrearsTolerance,interestRatePerPeriod,annualInterestRate,repaymentFrequencyType,interestRateFrequencyType,amortizationType,interestType,interestCalculationPeriodType,fundId"; private String allowedFieldList = "currencyOptions,amortizationTypeOptions,interestTypeOptions,interestCalculationPeriodTypeOptions,repaymentFrequencyTypeOptions,interestRateFrequencyTypeOptions,fundOptions"; @@ -51,7 +51,7 @@ public class LoanProductApiResource { @Produces({MediaType.APPLICATION_JSON}) public Response createLoanProduct(final String jsonRequestBody) { - final LoanProductCommand command = this.apiDataConversionService.convertJsonToCommand(null, jsonRequestBody); + final LoanProductCommand command = this.apiDataConversionService.convertJsonToLoanProductCommand(null, jsonRequestBody); EntityIdentifier entityIdentifier = this.loanProductWritePlatformService.createLoanProduct(command); @@ -93,7 +93,7 @@ public class LoanProductApiResource { @Path("{productId}") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public String retrieveLoanProductDetails(@PathParam("productId") final Long productId, final UriInfo uriInfo) { + public String retrieveLoanProductDetails(@PathParam("productId") final Long productId, @Context final UriInfo uriInfo) { LoanProductData loanProduct = this.loanProductReadPlatformService.retrieveLoanProduct(productId); @@ -109,7 +109,7 @@ public class LoanProductApiResource { @Produces({MediaType.APPLICATION_JSON}) public Response updateLoanProduct(@PathParam("productId") final Long productId, final String jsonRequestBody) { - LoanProductCommand command = this.apiDataConversionService.convertJsonToCommand(productId, jsonRequestBody); + LoanProductCommand command = this.apiDataConversionService.convertJsonToLoanProductCommand(productId, jsonRequestBody); EntityIdentifier entityIdentifier = this.loanProductWritePlatformService.updateLoanProduct(command); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/OfficeApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/OfficesApiResource.java similarity index 53% rename from mifosng-provider/src/main/java/org/mifosng/platform/api/OfficeApiResource.java rename to mifosng-provider/src/main/java/org/mifosng/platform/api/OfficesApiResource.java index ea132c76f..b7c9fa0fa 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/OfficeApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/OfficesApiResource.java @@ -1,8 +1,6 @@ package org.mifosng.platform.api; -import java.lang.reflect.Type; import java.util.Collection; -import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -17,7 +15,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import org.joda.time.LocalDate; import org.mifosng.platform.api.commands.OfficeCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.OfficeData; @@ -29,13 +26,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - @Path("/offices") @Component @Scope("singleton") -public class OfficeApiResource { +public class OfficesApiResource { private String defaultFieldList = "openingDate"; private String allowedFieldList = "allowedParents"; @@ -54,12 +48,11 @@ public class OfficeApiResource { private ApiJSONFormattingService jsonFormattingService; @GET - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public String retrieveOffices(@Context UriInfo uriInfo) { - Collection offices = this.readPlatformService - .retrieveAllOffices(); + Collection offices = this.readPlatformService.retrieveAllOffices(); String selectedFields = ""; return this.jsonFormattingService.convertRequest(offices, filterName, allowedFieldList, selectedFields, uriInfo.getQueryParameters()); @@ -67,8 +60,8 @@ public class OfficeApiResource { @GET @Path("template") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public String retrieveOfficeTemplate(@Context UriInfo uriInfo) { OfficeData officeData = this.readPlatformService @@ -85,39 +78,8 @@ public class OfficeApiResource { @Produces({MediaType.APPLICATION_JSON}) public Response createOffice(final String jsonRequestBody) { - Gson gson = new Gson(); - Type typeOfMap = new TypeToken>(){}.getType(); - Map requestMap = gson.fromJson(jsonRequestBody, typeOfMap); + OfficeCommand command = this.apiDataConversionService.convertJsonToOfficeCommand(null, jsonRequestBody); - String name = null; - if (requestMap.containsKey("name")) { - name = requestMap.get("name"); - } - - String externalId = null; - if (requestMap.containsKey("externalId")) { - externalId = requestMap.get("externalId"); - } - - Long parentId = null; - if (requestMap.containsKey("parentId")) { - parentId = Long.valueOf(requestMap.get("parentId")); - } - - String openingDate = null; - if (requestMap.containsKey("openingDate")) { - openingDate = requestMap.get("openingDate"); - } - - String dateFormat = null; - if (requestMap.containsKey("dateFormat")) { - dateFormat = requestMap.get("dateFormat"); - } - - LocalDate openingLocalDate = apiDataConversionService.convertFrom(openingDate, "openingDate", dateFormat); - - OfficeCommand command = new OfficeCommand(name, externalId, parentId, openingLocalDate); - Long officeId = this.writePlatformService.createOffice(command); return Response.ok().entity(new EntityIdentifier(officeId)).build(); @@ -125,8 +87,8 @@ public class OfficeApiResource { @GET @Path("{officeId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public String retreiveOffice(@PathParam("officeId") final Long officeId, @QueryParam("template") String template, @Context UriInfo uriInfo) { @@ -143,42 +105,11 @@ public class OfficeApiResource { @PUT @Path("{officeId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public Response updateOffice(@PathParam("officeId") final Long officeId, final String jsonRequestBody) { - Gson gson = new Gson(); - Type typeOfMap = new TypeToken>(){}.getType(); - Map requestMap = gson.fromJson(jsonRequestBody, typeOfMap); - - String name = null; - if (requestMap.containsKey("name")) { - name = requestMap.get("name"); - } - - String externalId = null; - if (requestMap.containsKey("externalId")) { - externalId = requestMap.get("externalId"); - } - - Long parentId = null; - if (requestMap.containsKey("parentId")) { - parentId = Long.valueOf(requestMap.get("parentId")); - } - - String openingDate = null; - if (requestMap.containsKey("openingDate")) { - openingDate = requestMap.get("openingDate"); - } - - String dateFormat = null; - if (requestMap.containsKey("dateFormat")) { - dateFormat = requestMap.get("dateFormat"); - } - - LocalDate openingLocalDate = apiDataConversionService.convertFrom(openingDate, "openingDate", dateFormat); - - OfficeCommand command = new OfficeCommand(officeId, name, externalId, parentId, openingLocalDate); + OfficeCommand command = this.apiDataConversionService.convertJsonToOfficeCommand(officeId, jsonRequestBody); Long entityId = this.writePlatformService.updateOffice(command); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/PermissionApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/PermissionsApiResource.java similarity index 81% rename from mifosng-provider/src/main/java/org/mifosng/platform/api/PermissionApiResource.java rename to mifosng-provider/src/main/java/org/mifosng/platform/api/PermissionsApiResource.java index 823fc9b8d..81c81ca74 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/PermissionApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/PermissionsApiResource.java @@ -20,7 +20,7 @@ import org.springframework.stereotype.Component; @Path("/permissions") @Component @Scope("singleton") -public class PermissionApiResource { +public class PermissionsApiResource { private String allowedFieldList = ""; private String filterName = "permissionFilter"; @@ -31,12 +31,11 @@ public class PermissionApiResource { private ApiJSONFormattingService jsonFormattingService; @GET - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveAllPermissions(@Context UriInfo uriInfo) { + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String retrieveAllPermissions(@Context final UriInfo uriInfo) { - Collection permissions = this.permissionReadPlatformService - .retrieveAllPermissions(); + Collection permissions = this.permissionReadPlatformService.retrieveAllPermissions(); String selectedFields = ""; return this.jsonFormattingService.convertRequest(permissions, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/RoleApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/RolesApiResource.java similarity index 71% rename from mifosng-provider/src/main/java/org/mifosng/platform/api/RoleApiResource.java rename to mifosng-provider/src/main/java/org/mifosng/platform/api/RolesApiResource.java index ea16eb056..e691dff8c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/RoleApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/RolesApiResource.java @@ -19,6 +19,7 @@ import org.mifosng.platform.api.commands.RoleCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.PermissionData; import org.mifosng.platform.api.data.RoleData; +import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService; import org.mifosng.platform.user.service.PermissionReadPlatformService; import org.mifosng.platform.user.service.RoleReadPlatformService; @@ -30,7 +31,7 @@ import org.springframework.stereotype.Component; @Path("/roles") @Component @Scope("singleton") -public class RoleApiResource { +public class RolesApiResource { private String allowedFieldList = "availablePermissions"; private String filterName = "roleFilter"; @@ -46,14 +47,16 @@ public class RoleApiResource { @Autowired private ApiJSONFormattingService jsonFormattingService; + + @Autowired + private ApiDataConversionService apiDataConversionService; @GET - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveAllRoles(@Context UriInfo uriInfo) { + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String retrieveAllRoles(@Context final UriInfo uriInfo) { - Collection roles = this.roleReadPlatformService - .retrieveAllRoles(); + Collection roles = this.roleReadPlatformService.retrieveAllRoles(); String selectedFields = "id,name,description"; return this.jsonFormattingService.convertRequest(roles, filterName, @@ -62,12 +65,11 @@ public class RoleApiResource { @GET @Path("template") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveNewRoleDetails(@Context UriInfo uriInfo) { + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String retrieveNewRoleDetails(@Context final UriInfo uriInfo) { - Collection allPermissions = this.permissionReadPlatformService - .retrieveAllPermissions(); + Collection allPermissions = this.permissionReadPlatformService.retrieveAllPermissions(); RoleData role = new RoleData(); role.setAvailablePermissions(allPermissions); @@ -78,20 +80,23 @@ public class RoleApiResource { } @POST - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response createRole(final RoleCommand command) { + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response createRole(final String jsonRequestBody) { + RoleCommand command = this.apiDataConversionService.convertJsonToRoleCommand(null, jsonRequestBody); + Long roleId = this.roleWritePlatformService.createRole(command); + return Response.ok().entity(new EntityIdentifier(roleId)).build(); } @GET @Path("{roleId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) public String retrieveRole(@PathParam("roleId") final Long roleId, - @QueryParam("template") String template, @Context UriInfo uriInfo) { + @QueryParam("template") final String template, @Context final UriInfo uriInfo) { RoleData role = this.roleReadPlatformService.retrieveRole(roleId); @@ -109,13 +114,14 @@ public class RoleApiResource { @PUT @Path("{roleId}") - @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response updateRole(@PathParam("roleId") final Long roleId, - final RoleCommand command) { + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response updateRole(@PathParam("roleId") final Long roleId, final String jsonRequestBody) { - command.setId(roleId); + RoleCommand command = this.apiDataConversionService.convertJsonToRoleCommand(roleId, jsonRequestBody); + this.roleWritePlatformService.updateRole(command); + return Response.ok().entity(new EntityIdentifier(roleId)).build(); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java index d49df3a3e..a116cc8e9 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/FundCommand.java @@ -1,22 +1,21 @@ package org.mifosng.platform.api.commands; -import javax.xml.bind.annotation.XmlRootElement; +import java.util.Set; /** - * Command used for create and update fund operations. + * Immutable command for creating or updating details of a fund. */ -@XmlRootElement public class FundCommand { - private Long id; - private String name; - private String externalId; - - protected FundCommand() { - // - } + private final Long id; + private final String name; + private final String externalId; - public FundCommand(final String fundName, final String externalId) { + private final Set modifiedParameters; + + public FundCommand(final Set modifiedParameters, final Long id, final String fundName, final String externalId) { + this.modifiedParameters = modifiedParameters; + this.id = id; this.name = fundName; this.externalId = externalId; } @@ -25,23 +24,19 @@ public class FundCommand { return id; } - public void setId(Long id) { - this.id = id; - } - public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public String getExternalId() { return externalId; } + + public boolean isNameChanged() { + return this.modifiedParameters.contains("name"); + } - public void setExternalId(String externalId) { - this.externalId = externalId; + public boolean isExternalIdChanged() { + return this.modifiedParameters.contains("externalId"); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java index 37138d085..68fb96348 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/LoanProductCommand.java @@ -11,7 +11,6 @@ public class LoanProductCommand { private final Long id; private final String name; private final String description; - private final String externalId; private final Long fundId; @@ -33,7 +32,8 @@ public class LoanProductCommand { private final Set modifiedParameters; - public LoanProductCommand(Set modifiedParameters, final Long id, final String name, final String description, final String externalId, final Long fundId, + public LoanProductCommand(final Set modifiedParameters, final Long id, final String name, final String description, + final Long fundId, final String currencyCode, final Integer digitsAfterDecimal, final BigDecimal principal, final BigDecimal inArrearsTolerance, final Integer numberOfRepayments, final Integer repaymentEvery, final BigDecimal interestRatePerPeriod, @@ -43,7 +43,6 @@ public class LoanProductCommand { this.id = id; this.name = name; this.description = description; - this.externalId = externalId; this.fundId = fundId; this.currencyCode = currencyCode; this.digitsAfterDecimal = digitsAfterDecimal; @@ -71,10 +70,6 @@ public class LoanProductCommand { return description; } - public String getExternalId() { - return externalId; - } - public Long getFundId() { return fundId; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/OfficeCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/OfficeCommand.java index 30948048c..307989c95 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/OfficeCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/OfficeCommand.java @@ -1,109 +1,66 @@ package org.mifosng.platform.api.commands; -import javax.xml.bind.annotation.XmlRootElement; +import java.util.Set; import org.joda.time.LocalDate; /** - * Command used for create and update office operations. + * Immutable command for creating or updating details of a office. */ -@XmlRootElement public class OfficeCommand { - private Long id; - private String name; - private String externalId; + private final Long id; + private final String name; + private final String externalId; + private final LocalDate openingDate; + private final Long parentId; - private String dateFormat; - private String openingDate; - private LocalDate openingLocalDate; - - private Long parentId; - private Boolean rootOffice = false; - - protected OfficeCommand() { - // - } + private final Set modifiedParameters; - public OfficeCommand(final String officeName, final String externalId, - final Long parentId, final LocalDate openingDate) { - this.name = officeName; - this.externalId = externalId; - this.parentId = parentId; - this.openingLocalDate = openingDate; - } - - public OfficeCommand(final Long id, final String officeName, + public OfficeCommand(Set modifiedParameters, final Long id, final String officeName, final String externalId, final Long parentId, final LocalDate openingDate) { + this.modifiedParameters = modifiedParameters; this.id = id; this.name = officeName; this.externalId = externalId; this.parentId = parentId; - this.openingLocalDate = openingDate; - } - - public String getName() { - return this.name; - } - - public void setName(final String name) { - this.name = name; - } - - public String getExternalId() { - return this.externalId; - } - - public void setExternalId(final String externalId) { - this.externalId = externalId; - } - - public Long getParentId() { - return this.parentId; - } - - public void setParentId(final Long parentId) { - this.parentId = parentId; - } - - public Long getId() { - return this.id; - } - - public void setId(final Long id) { - this.id = id; - } - - public String getDateFormat() { - return dateFormat; - } - - public void setDateFormat(String dateFormat) { - this.dateFormat = dateFormat; - } - - public boolean isRootOffice() { - return rootOffice; - } - - public void setRootOffice(boolean rootOffice) { - this.rootOffice = rootOffice; - } - - public String getOpeningDate() { - return openingDate; - } - - public void setOpeningDate(String openingDate) { this.openingDate = openingDate; } - public LocalDate getOpeningLocalDate() { - return openingLocalDate; + public Long getId() { + return id; } - public void setOpeningLocalDate(LocalDate openingLocalDate) { - this.openingLocalDate = openingLocalDate; + public String getName() { + return name; + } + + public String getExternalId() { + return externalId; + } + + public LocalDate getOpeningDate() { + return openingDate; + } + + public Long getParentId() { + return parentId; + } + + public boolean isNameChanged() { + return this.modifiedParameters.contains("name"); + } + + public boolean isExternalIdChanged() { + return this.modifiedParameters.contains("externalId"); + } + + public boolean isOpeningDateChanged() { + return this.modifiedParameters.contains("openingDate"); + } + + public boolean isParentChanged() { + return this.modifiedParameters.contains("parentId"); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/RoleCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/RoleCommand.java index 42cabe980..9ca4d2cdd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/RoleCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/RoleCommand.java @@ -1,58 +1,44 @@ package org.mifosng.platform.api.commands; -import javax.xml.bind.annotation.XmlRootElement; +import java.util.Set; /** - * For creating and updating roles. When updating the id is expected to be populated. + * Immutable command for creating or updating details of a role. */ -@XmlRootElement public class RoleCommand { - private Long id; - private String name; - private String description; + private final Long id; + private final String name; + private final String description; + private final String[] permissions; - private String[] permissions; + private final Set modifiedParameters; - public RoleCommand() { - // - } - - public RoleCommand(final String name, final String description, final String[] permissionIds) { + public RoleCommand(Set modifiedParameters, final Long id, final String name, final String description, final String[] permissionIds) { + this.modifiedParameters = modifiedParameters; + this.id = id; this.name = name; this.description = description; this.permissions = permissionIds; } - public String getName() { - return this.name; - } - - public void setName(final String name) { - this.name = name; - } - - public String getDescription() { - return this.description; - } - - public void setDescription(final String description) { - this.description = description; - } - public Long getId() { return id; } - public void setId(Long id) { - this.id = id; + public String getName() { + return name; + } + + public String getDescription() { + return description; } public String[] getPermissions() { return permissions; } - public void setPermissions(String[] permissions) { - this.permissions = permissions; + public Set getModifiedParameters() { + return modifiedParameters; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java index 1db2281f1..cb0d880ac 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java @@ -4,7 +4,10 @@ import java.math.BigDecimal; import java.util.Locale; import org.joda.time.LocalDate; +import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.api.commands.LoanProductCommand; +import org.mifosng.platform.api.commands.OfficeCommand; +import org.mifosng.platform.api.commands.RoleCommand; public interface ApiDataConversionService { @@ -20,5 +23,11 @@ public interface ApiDataConversionService { Locale localeFrom(String languageCode, String courntryCode, String variantCode); - LoanProductCommand convertJsonToCommand(Long productId, String jsonRequestBody); -} + LoanProductCommand convertJsonToLoanProductCommand(Long resourceIdentifier, String json); + + FundCommand convertJsonToFundCommand(Long resourceIdentifier, String json); + + OfficeCommand convertJsonToOfficeCommand(Long resourceIdentifier, String json); + + RoleCommand convertJsonToRoleCommand(Long resourceIdentifier, String json); +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 8e42dea6f..6401bdb7e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -17,7 +17,10 @@ import java.util.Set; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; +import org.mifosng.platform.api.commands.FundCommand; import org.mifosng.platform.api.commands.LoanProductCommand; +import org.mifosng.platform.api.commands.OfficeCommand; +import org.mifosng.platform.api.commands.RoleCommand; import org.mifosng.platform.api.data.ApiParameterError; import org.mifosng.platform.api.errorhandling.InvalidJsonException; import org.mifosng.platform.api.errorhandling.UnsupportedParameterException; @@ -27,6 +30,10 @@ import org.springframework.format.number.NumberFormatter; import org.springframework.stereotype.Service; import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; @Service @@ -39,8 +46,20 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } @Override - public LocalDate convertFrom(String dateAsString, String parameterName, - String dateFormat) { + public LocalDate convertFrom(final String dateAsString, final String parameterName, final String dateFormat) { + + if (StringUtils.isBlank(dateFormat)) { + + List dataValidationErrors = new ArrayList(); + String defaultMessage = new StringBuilder("The parameter '" + parameterName + "' requires a 'dateFormat' parameter to be passed with it.").toString(); + ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.dateFormat.parameter", defaultMessage, parameterName); + dataValidationErrors.add(error); + + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + LocalDate eventLocalDate = null; if (StringUtils.isNotBlank(dateAsString)) { try { @@ -243,7 +262,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } @Override - public LoanProductCommand convertJsonToCommand(final Long resourceIdentifier, final String json) { + public LoanProductCommand convertJsonToLoanProductCommand(final Long resourceIdentifier, final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); @@ -254,7 +273,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Set supportedParams = new HashSet( - Arrays.asList("name", "description", "externalId", "fundId", "currencyCode", "digitsAfterDecimalValue", + Arrays.asList("name", "description", "fundId", "currencyCode", "digitsAfterDecimalValue", "principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType") ); @@ -265,7 +284,6 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { String name = extractStringParameter("name", requestMap, modifiedParameters); String description = extractStringParameter("description", requestMap, modifiedParameters); - String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters); String currencyCode = extractStringParameter("currencyCode", requestMap, modifiedParameters); Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters); @@ -282,12 +300,103 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Integer interestTypeValue = extractIntegerParameter("interestType", requestMap, modifiedParameters); Integer interestCalculationPeriodTypeValue = extractIntegerParameter("interestCalculationPeriodType", requestMap, modifiedParameters); - return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, externalId, fundId, + return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, fundId, currencyCode, digitsAfterDecimalValue, principalValue, inArrearsToleranceValue, numberOfRepaymentsValue, repaymentEveryValue, interestRatePerPeriodValue, repaymentFrequencyTypeValue, interestRateFrequencyTypeValue, amortizationTypeValue, interestTypeValue, interestCalculationPeriodTypeValue); } + + @Override + public FundCommand convertJsonToFundCommand(final Long resourceIdentifier, final String json) { - private void checkForUnsupportedParameters(Map requestMap, Set supportedParams) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + Type typeOfMap = new TypeToken>(){}.getType(); + Map requestMap = gsonConverter.fromJson(json, typeOfMap); + + + Set supportedParams = new HashSet( + Arrays.asList("name", "externalId") + ); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + String name = extractStringParameter("name", requestMap, modifiedParameters); + String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); + + return new FundCommand(modifiedParameters, resourceIdentifier, name, externalId); + } + + @Override + public OfficeCommand convertJsonToOfficeCommand(final Long resourceIdentifier, final String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + Type typeOfMap = new TypeToken>(){}.getType(); + Map requestMap = gsonConverter.fromJson(json, typeOfMap); + + Set supportedParams = new HashSet( + Arrays.asList("name", "externalId", "parentId", "openingDate") + ); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + String name = extractStringParameter("name", requestMap, modifiedParameters); + String externalId = extractStringParameter("externalId", requestMap, modifiedParameters); + Long parentId = extractLongParameter("parentId", requestMap, modifiedParameters); + LocalDate openingLocalDate = extractLocalDateParameter("openingDate", requestMap, modifiedParameters); + + return new OfficeCommand(modifiedParameters, resourceIdentifier, name, externalId, parentId, openingLocalDate); + } + + @Override + public RoleCommand convertJsonToRoleCommand(final Long resourceIdentifier, final String json) { + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + Type typeOfMap = new TypeToken>(){}.getType(); + Map requestMap = gsonConverter.fromJson(json, typeOfMap); + + Set supportedParams = new HashSet( + Arrays.asList("name", "description", "permissions") + ); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + // check array + JsonParser parser = new JsonParser(); + + String[] permissionIds = null; + JsonElement element = parser.parse(json); + if (element.isJsonObject()) { + JsonObject object = element.getAsJsonObject(); + if (object.has("permissions")) { + modifiedParameters.add("permissions"); + JsonArray array = object.get("permissions").getAsJsonArray(); + permissionIds = new String[array.size()]; + for (int i=0; i requestMap, Set supportedParams) { List unsupportedParameterList = new ArrayList(); for (String providedParameter : requestMap.keySet()) { if (!supportedParams.contains(providedParameter)) { @@ -300,37 +409,39 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } } - private String extractStringParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { + private String extractStringParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { String paramValue = null; if (requestMap.containsKey(paramName)) { - paramValue = requestMap.get(paramName); + paramValue = (String) requestMap.get(paramName); modifiedParameters.add(paramName); } return paramValue; } - private Integer extractIntegerParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { + private Integer extractIntegerParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { Integer paramValue = null; if (requestMap.containsKey(paramName)) { - paramValue = convertToInteger(requestMap.get(paramName), paramName, extractLocaleValue(requestMap)); + String valueAsString = (String) requestMap.get(paramName); + paramValue = convertToInteger(valueAsString, paramName, extractLocaleValue(requestMap)); modifiedParameters.add(paramName); } return paramValue; } - private BigDecimal extractBigDecimalParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { + private BigDecimal extractBigDecimalParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { BigDecimal paramValue = null; if (requestMap.containsKey(paramName)) { - paramValue = convertFrom(requestMap.get(paramName), paramName, extractLocaleValue(requestMap)); + String valueAsString = (String) requestMap.get(paramName); + paramValue = convertFrom(valueAsString, paramName, extractLocaleValue(requestMap)); modifiedParameters.add(paramName); } return paramValue; } - private Long extractLongParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { + private Long extractLongParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { Long paramValue = null; if (requestMap.containsKey(paramName)) { - String valueAsString = requestMap.get(paramName); + String valueAsString = (String) requestMap.get(paramName); if (StringUtils.isNotBlank(valueAsString)) { paramValue = Long.valueOf(valueAsString); } @@ -338,12 +449,25 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } return paramValue; } + + private LocalDate extractLocalDateParameter(final String paramName, final Map requestMap, final Set modifiedParameters) { + LocalDate paramValue = null; + if (requestMap.containsKey(paramName)) { + String valueAsString = (String) requestMap.get(paramName); + if (StringUtils.isNotBlank(valueAsString)) { + final String dateFormat = (String) requestMap.get("dateFormat"); + paramValue = convertFrom(valueAsString, paramName, dateFormat); + } + modifiedParameters.add(paramName); + } + return paramValue; + } - private Locale extractLocaleValue(Map requestMap) { + private Locale extractLocaleValue(Map requestMap) { Locale clientApplicationLocale = null; String locale = null; if (requestMap.containsKey("locale")) { - locale = requestMap.get("locale"); + locale = (String) requestMap.get("locale"); clientApplicationLocale = localeFromString(locale); } return clientApplicationLocale; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java b/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java index 744cd34fa..35dfb7499 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/fund/domain/Fund.java @@ -37,11 +37,12 @@ public class Fund extends AbstractAuditableCustom { } public void update(final FundCommand command) { - if (StringUtils.isNotBlank(command.getName())) { - this.name = command.getName(); + + if (command.isNameChanged()) { + this.name = StringUtils.defaultIfEmpty(command.getName(), null); } - if (command.getExternalId() != null) { + if (command.isExternalIdChanged()) { this.externalId = StringUtils.defaultIfEmpty(command.getExternalId(), null); } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java index 341774851..732840b1a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/fund/service/FundWritePlatformServiceJpaRepositoryImpl.java @@ -56,7 +56,7 @@ public class FundWritePlatformServiceJpaRepositoryImpl implements FundWritePlatf context.authenticatedUser(); FundCommandValidator validator = new FundCommandValidator(command); - validator.validateForCreate(); + validator.validateForUpdate(); final Long fundId = command.getId(); Fund fund = this.fundRepository.findOne(fundId); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java index 9580c8195..18b26078f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductCommandValidator.java @@ -25,7 +25,6 @@ public class LoanProductCommandValidator { baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("description").value(command.getDescription()).ignoreIfNull().notExceedingLengthOf(500); - baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().notNull().inMinMaxRange(0, 6); @@ -44,7 +43,7 @@ public class LoanProductCommandValidator { baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull().notNull().inMinMaxRange(0, 1); baseDataValidator.reset().parameter("interestCalculationPeriodType").value(command.getInterestCalculationPeriodType()).ignoreIfNull().notNull().inMinMaxRange(0, 1); - baseDataValidator.reset().anyOfNotNull(command.getFundId(), command.getName(), command.getDescription(), command.getExternalId(), command.getCurrencyCode(), command.getDigitsAfterDecimal(), + baseDataValidator.reset().anyOfNotNull(command.getFundId(), command.getName(), command.getDescription(), command.getCurrencyCode(), command.getDigitsAfterDecimal(), command.getPrincipal(), command.getInArrearsTolerance(), command.getRepaymentFrequencyType(), command.getRepaymentEvery(), command.getNumberOfRepayments(), command.getInterestRatePerPeriod(), command.getInterestRateFrequencyType(), command.getAmortizationType(), command.getInterestType(), command.getInterestCalculationPeriodType()); @@ -61,7 +60,6 @@ public class LoanProductCommandValidator { baseDataValidator.reset().parameter("name").value(command.getName()).notBlank(); baseDataValidator.reset().parameter("description").value(command.getDescription()).notExceedingLengthOf(500); - baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).notExceedingLengthOf(100); baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank(); baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java index 31eef32f7..84a1fe300 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java @@ -98,28 +98,35 @@ public class Office extends AbstractAuditableCustom { return this.parent == null; } - public void update(final OfficeCommand command) { - if (StringUtils.isNotBlank(command.getName())) { - this.name = command.getName().trim(); + + if (command.isNameChanged()) { + this.name = StringUtils.defaultIfEmpty(command.getName(), null); } - if (command.getExternalId() != null) { - this.externalId = StringUtils.defaultIfEmpty(command.getExternalId().trim(), null); + if (command.isExternalIdChanged()) { + this.externalId = StringUtils.defaultIfEmpty(command.getExternalId(), null); } - if (command.getOpeningDate() != null) { - this.openingDate = command.getOpeningLocalDate().toDate(); + if (command.isOpeningDateChanged()) { + if (command.getOpeningDate() != null) { + this.openingDate = command.getOpeningDate().toDate(); + } else { + this.openingDate = null; + } } } - public void update(Office newParent) { + public void update(final Office newParent) { + if (this.parent == null) { throw new RootOfficeParentCannotBeUpdated(); } + if (this.identifiedBy(newParent.getId())) { throw new CannotUpdateOfficeWithParentOfficeSameAsSelf(this.getId(), newParent.getId()); } + this.parent = newParent; generateHierarchy(); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/OfficeWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/OfficeWritePlatformServiceJpaRepositoryImpl.java index 9cdac8a28..87a46a841 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/OfficeWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/service/OfficeWritePlatformServiceJpaRepositoryImpl.java @@ -56,7 +56,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId()); - Office office = Office.createNew(parent, command.getName(), command.getOpeningLocalDate(), command.getExternalId()); + Office office = Office.createNew(parent, command.getName(), command.getOpeningDate(), command.getExternalId()); // pre save to generate id for use in office hierarchy this.officeRepository.save(office); @@ -86,7 +86,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP office.update(command); - if (command.getParentId() != null) { + if (command.isParentChanged()) { Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId()); office.update(parent); }