From 0bfeecad7bcf084aa725b663d2ded12f898a2929 Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Thu, 19 Jul 2012 11:41:22 +0100 Subject: [PATCH] json returned for funds using gson. --- .../platform/api/FundsApiResource.java | 34 +- .../ApiDataConversionService.java | 11 +- .../ApiDataConversionServiceImpl.java | 518 +++++++++--------- .../ParameterListExclusionStrategy.java | 26 + 4 files changed, 326 insertions(+), 263 deletions(-) create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ParameterListExclusionStrategy.java 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 022ad22f1..292c27e38 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,6 +1,9 @@ package org.mifosng.platform.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; @@ -11,6 +14,7 @@ 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.MultivaluedMap; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; @@ -18,7 +22,6 @@ 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; import org.springframework.beans.factory.annotation.Autowired; @@ -30,9 +33,6 @@ import org.springframework.stereotype.Component; @Scope("singleton") public class FundsApiResource { - private String allowedFieldList = "allowedParents"; - private String filterName = "myFilter"; - @Autowired private FundReadPlatformService readPlatformService; @@ -42,18 +42,28 @@ public class FundsApiResource { @Autowired private ApiDataConversionService apiDataConversionService; - @Autowired - private ApiJSONFormattingService jsonFormattingService; - @GET @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) public String retrieveFunds(@Context final UriInfo uriInfo) { + MultivaluedMap queryParams = uriInfo.getQueryParameters(); + String commaSerperatedParameters = ""; + if (queryParams.getFirst("fields") != null) { + commaSerperatedParameters = queryParams.getFirst("fields"); + } + + boolean prettyPrint = false; + if (queryParams.getFirst("pretty") != null) { + String prettyPrintValue = queryParams.getFirst("pretty"); + prettyPrint = "true".equalsIgnoreCase(prettyPrintValue); + } + + Set responseParameters = new HashSet(Arrays.asList(commaSerperatedParameters.split("\\s*,\\s*"))); + Collection funds = this.readPlatformService.retrieveAllFunds(); - String selectedFields = ""; - return this.jsonFormattingService.convertRequest(funds, filterName, - allowedFieldList, selectedFields, uriInfo.getQueryParameters()); + + return this.apiDataConversionService.covertFundDataToJson(prettyPrint, responseParameters, funds.toArray(new FundData[funds.size()])); } @POST @@ -76,9 +86,7 @@ public class FundsApiResource { FundData fund = this.readPlatformService.retrieveFund(fundId); - String selectedFields = ""; - return this.jsonFormattingService.convertRequest(fund, filterName, - allowedFieldList, selectedFields, uriInfo.getQueryParameters()); + return this.apiDataConversionService.covertFundDataToJson(fund); } @PUT 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 3fc74b440..de2aa0067 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 @@ -1,5 +1,7 @@ package org.mifosng.platform.api.infrastructure; +import java.util.Set; + import org.mifosng.platform.api.commands.AdjustLoanTransactionCommand; import org.mifosng.platform.api.commands.BranchMoneyTransferCommand; import org.mifosng.platform.api.commands.ClientCommand; @@ -13,12 +15,13 @@ import org.mifosng.platform.api.commands.OrganisationCurrencyCommand; import org.mifosng.platform.api.commands.RoleCommand; import org.mifosng.platform.api.commands.SubmitLoanApplicationCommand; import org.mifosng.platform.api.commands.UserCommand; +import org.mifosng.platform.api.data.FundData; public interface ApiDataConversionService { - LoanProductCommand convertJsonToLoanProductCommand(Long resourceIdentifier, String json); - FundCommand convertJsonToFundCommand(Long resourceIdentifier, String json); + + String covertFundDataToJson(boolean prettyPrint, Set responseParameters, FundData... funds); OfficeCommand convertJsonToOfficeCommand(Long resourceIdentifier, String json); @@ -27,6 +30,8 @@ public interface ApiDataConversionService { UserCommand convertJsonToUserCommand(Long resourceIdentifier, String json); BranchMoneyTransferCommand convertJsonToBranchMoneyTransferCommand(String jsonRequestBody); + + LoanProductCommand convertJsonToLoanProductCommand(Long resourceIdentifier, String json); ClientCommand convertJsonToClientCommand(Long resourceIdentifier, String jsonRequestBody); @@ -42,4 +47,6 @@ public interface ApiDataConversionService { OrganisationCurrencyCommand convertJsonToOrganisationCurrencyCommand(String jsonRequestBody); NoteCommand convertJsonToNoteCommand(Long resourceIdentifier, Long clientId, String jsonRequestBody); + + } \ 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 46a2af8bc..6f917ac34 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 @@ -31,6 +31,7 @@ import org.mifosng.platform.api.commands.RoleCommand; import org.mifosng.platform.api.commands.SubmitLoanApplicationCommand; import org.mifosng.platform.api.commands.UserCommand; import org.mifosng.platform.api.data.ApiParameterError; +import org.mifosng.platform.api.data.FundData; import org.mifosng.platform.api.errorhandling.InvalidJsonException; import org.mifosng.platform.api.errorhandling.UnsupportedParameterException; import org.mifosng.platform.exceptions.PlatformApiDataValidationException; @@ -38,7 +39,9 @@ import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.format.number.NumberFormatter; import org.springframework.stereotype.Service; +import com.google.gson.ExclusionStrategy; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -54,258 +57,23 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { gsonConverter = new Gson(); } - private 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 { - Locale locale = LocaleContextHolder.getLocale(); - eventLocalDate = DateTimeFormat.forPattern(dateFormat) - .withLocale(locale) - .parseLocalDate(dateAsString.toLowerCase(locale)); - } catch (IllegalArgumentException e) { - List dataValidationErrors = new ArrayList(); - ApiParameterError error = ApiParameterError - .parameterError( - "validation.msg.invalid.date.format", - "The parameter " - + parameterName - + " is invalid based on the dateFormat provided:" - + dateFormat, parameterName, - dateAsString, dateFormat); - dataValidationErrors.add(error); - - throw new PlatformApiDataValidationException( - "validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); - } - } - - return eventLocalDate; - } - - private Integer convertToInteger(String numericalValueFormatted, String parameterName, Locale clientApplicationLocale) { - try { - Integer number = null; - - if (StringUtils.isNotBlank(numericalValueFormatted)) { - - String source = numericalValueFormatted.trim(); - - NumberFormat format = NumberFormat.getInstance(clientApplicationLocale); - DecimalFormat df = (DecimalFormat) format; - DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); - df.setParseBigDecimal(true); - - // http://bugs.sun.com/view_bug.do?bug_id=4510618 - char groupingSeparator = symbols.getGroupingSeparator(); - if (groupingSeparator == '\u00a0') { - source = source.replaceAll(" ", Character.toString('\u00a0')); - } - - Number parsedNumber = df.parse(source); - - double parsedNumberDouble = parsedNumber.doubleValue(); - int parsedNumberInteger = parsedNumber.intValue(); - - if (source.contains(Character.toString(symbols.getDecimalSeparator()))) { - throw new ParseException(source, 0); - } - - if (!Double.valueOf(parsedNumberDouble).equals(Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { - throw new ParseException(source, 0); - } - - number = parsedNumber.intValue(); - } - - return number; - } catch (ParseException e) { - - List dataValidationErrors = new ArrayList(); - ApiParameterError error = ApiParameterError.parameterError( - "validation.msg.invalid.integer.format", "The parameter " - + parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of [" - + clientApplicationLocale.toString() + "].", - parameterName, numericalValueFormatted, - clientApplicationLocale); - dataValidationErrors.add(error); - - throw new PlatformApiDataValidationException( - "validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); - } - } - - private BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) { - - if (clientApplicationLocale == null) { - - List dataValidationErrors = new ArrayList(); - String defaultMessage = new StringBuilder("The parameter '" + parameterName + "' requires a 'locale' parameter to be passed with it.").toString(); - ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage, parameterName); - dataValidationErrors.add(error); - - throw new PlatformApiDataValidationException( - "validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); - } - - try { - BigDecimal number = null; - - if (StringUtils.isNotBlank(numericalValueFormatted)) { - - String source = numericalValueFormatted.trim(); - - NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale); - DecimalFormat df = (DecimalFormat) format; - DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); - // http://bugs.sun.com/view_bug.do?bug_id=4510618 - char groupingSeparator = symbols.getGroupingSeparator(); - if (groupingSeparator == '\u00a0') { - source = source.replaceAll(" ", Character.toString('\u00a0')); - } - - NumberFormatter numberFormatter = new NumberFormatter(); - Number parsedNumber = numberFormatter.parse(source, clientApplicationLocale); - number = BigDecimal.valueOf(Double.valueOf(parsedNumber.doubleValue())); - } - - return number; - } catch (ParseException e) { - - List dataValidationErrors = new ArrayList(); - ApiParameterError error = ApiParameterError.parameterError( - "validation.msg.invalid.decimal.format", "The parameter " - + parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of [" - + clientApplicationLocale.toString() + "].", - parameterName, numericalValueFormatted, - clientApplicationLocale); - dataValidationErrors.add(error); - - throw new PlatformApiDataValidationException( - "validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); - } - } - - private Locale localeFromString(final String localeAsString) { - - if (StringUtils.isBlank(localeAsString)) { - List dataValidationErrors = new ArrayList(); - ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale is invalid. It cannot be blank.", "locale"); - dataValidationErrors.add(error); - - throw new PlatformApiDataValidationException( - "validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); - } - - String languageCode = ""; - String courntryCode = ""; - String variantCode = ""; - - String[] localeParts = localeAsString.split("_"); - - if (localeParts != null && localeParts.length == 1) { - languageCode = localeParts[0]; - } - - if (localeParts != null && localeParts.length == 2) { - languageCode = localeParts[0]; - courntryCode = localeParts[1]; - } - - if (localeParts != null && localeParts.length == 3) { - languageCode = localeParts[0]; - courntryCode = localeParts[1]; - variantCode = localeParts[2]; - } - - return localeFrom(languageCode, courntryCode, variantCode); - } - - private Locale localeFrom(final String languageCode, final String courntryCode, final String variantCode) { - - List dataValidationErrors = new ArrayList(); - - List allowedLanguages = Arrays.asList(Locale.getISOLanguages()); - if (!allowedLanguages.contains(languageCode.toLowerCase())) { - ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale has an invalid language value " + languageCode + " .", "locale", languageCode); - dataValidationErrors.add(error); - } - - if (StringUtils.isNotBlank(courntryCode.toUpperCase())) { - List allowedCountries = Arrays.asList(Locale.getISOCountries()); - if (!allowedCountries.contains(courntryCode)) { - ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale has an invalid country value " + courntryCode + " .", "locale", courntryCode); - dataValidationErrors.add(error); - } - } - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException( - "validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); - } - - return new Locale(languageCode.toLowerCase(), courntryCode.toUpperCase(), variantCode); - } - @Override - public LoanProductCommand convertJsonToLoanProductCommand(final Long resourceIdentifier, final String json) { + public String covertFundDataToJson(final boolean prettyPrint, final Set responseParameters, final FundData... funds) { - if (StringUtils.isBlank(json)) { - throw new InvalidJsonException(); + Set supportedParameters = new HashSet(Arrays.asList("id", "name", "externalId")); + + if (!supportedParameters.containsAll(responseParameters)) { + throw new UnsupportedParameterException(new ArrayList(responseParameters)); } - Type typeOfMap = new TypeToken>(){}.getType(); - Map requestMap = gsonConverter.fromJson(json, typeOfMap); - - Set supportedParams = new HashSet( - Arrays.asList("name", "description", "fundId", "currencyCode", "digitsAfterDecimal", - "principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", - "repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "locale") - ); - - checkForUnsupportedParameters(requestMap, supportedParams); - - Set modifiedParameters = new HashSet(); - - String name = extractStringParameter("name", requestMap, modifiedParameters); - String description = extractStringParameter("description", requestMap, modifiedParameters); - Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters); - String currencyCode = extractStringParameter("currencyCode", requestMap, modifiedParameters); - Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters); - BigDecimal principalValue = extractBigDecimalParameter("principal", requestMap, modifiedParameters); - BigDecimal inArrearsToleranceValue = extractBigDecimalParameter("inArrearsTolerance", requestMap, modifiedParameters); - BigDecimal interestRatePerPeriodValue = extractBigDecimalParameter("interestRatePerPeriod", requestMap, modifiedParameters); - - Integer repaymentEveryValue = extractIntegerParameter("repaymentEvery", requestMap, modifiedParameters); - Integer numberOfRepaymentsValue = extractIntegerParameter("numberOfRepayments", requestMap, modifiedParameters); - Integer repaymentFrequencyTypeValue = extractIntegerParameter("repaymentFrequencyType", requestMap, modifiedParameters); - - Integer interestRateFrequencyTypeValue = extractIntegerParameter("interestRateFrequencyType", requestMap, modifiedParameters); - Integer amortizationTypeValue = extractIntegerParameter("amortizationType", requestMap, modifiedParameters); - Integer interestTypeValue = extractIntegerParameter("interestType", requestMap, modifiedParameters); - Integer interestCalculationPeriodTypeValue = extractIntegerParameter("interestCalculationPeriodType", requestMap, modifiedParameters); - - return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, fundId, - currencyCode, digitsAfterDecimalValue, principalValue, inArrearsToleranceValue, numberOfRepaymentsValue, repaymentEveryValue, interestRatePerPeriodValue, - repaymentFrequencyTypeValue, interestRateFrequencyTypeValue, amortizationTypeValue, interestTypeValue, interestCalculationPeriodTypeValue); + final Set parameterNamesToSkip = new HashSet(supportedParameters); + parameterNamesToSkip.removeAll(responseParameters); + + ExclusionStrategy strategy = new ParameterListExclusionStrategy(parameterNamesToSkip); + + Gson gsonDeserializer = new GsonBuilder().addSerializationExclusionStrategy(strategy).create(); + + return gsonDeserializer.toJson(funds); } @Override @@ -511,6 +279,49 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { return new ClientCommand(resourceIdentifier, externalId, firstname, lastname, clientOrBusinessName, officeId, joiningDate); } + @Override + public LoanProductCommand convertJsonToLoanProductCommand(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", "fundId", "currencyCode", "digitsAfterDecimal", + "principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", + "repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "locale") + ); + + checkForUnsupportedParameters(requestMap, supportedParams); + + Set modifiedParameters = new HashSet(); + + String name = extractStringParameter("name", requestMap, modifiedParameters); + String description = extractStringParameter("description", requestMap, modifiedParameters); + Long fundId = extractLongParameter("fundId", requestMap, modifiedParameters); + String currencyCode = extractStringParameter("currencyCode", requestMap, modifiedParameters); + Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters); + BigDecimal principalValue = extractBigDecimalParameter("principal", requestMap, modifiedParameters); + BigDecimal inArrearsToleranceValue = extractBigDecimalParameter("inArrearsTolerance", requestMap, modifiedParameters); + BigDecimal interestRatePerPeriodValue = extractBigDecimalParameter("interestRatePerPeriod", requestMap, modifiedParameters); + + Integer repaymentEveryValue = extractIntegerParameter("repaymentEvery", requestMap, modifiedParameters); + Integer numberOfRepaymentsValue = extractIntegerParameter("numberOfRepayments", requestMap, modifiedParameters); + Integer repaymentFrequencyTypeValue = extractIntegerParameter("repaymentFrequencyType", requestMap, modifiedParameters); + + Integer interestRateFrequencyTypeValue = extractIntegerParameter("interestRateFrequencyType", requestMap, modifiedParameters); + Integer amortizationTypeValue = extractIntegerParameter("amortizationType", requestMap, modifiedParameters); + Integer interestTypeValue = extractIntegerParameter("interestType", requestMap, modifiedParameters); + Integer interestCalculationPeriodTypeValue = extractIntegerParameter("interestCalculationPeriodType", requestMap, modifiedParameters); + + return new LoanProductCommand(modifiedParameters, resourceIdentifier, name, description, fundId, + currencyCode, digitsAfterDecimalValue, principalValue, inArrearsToleranceValue, numberOfRepaymentsValue, repaymentEveryValue, interestRatePerPeriodValue, + repaymentFrequencyTypeValue, interestRateFrequencyTypeValue, amortizationTypeValue, interestTypeValue, interestCalculationPeriodTypeValue); + } + @Override public SubmitLoanApplicationCommand convertJsonToSubmitLoanApplicationCommand(final String json) { @@ -778,4 +589,215 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } return clientApplicationLocale; } + + private 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 { + Locale locale = LocaleContextHolder.getLocale(); + eventLocalDate = DateTimeFormat.forPattern(dateFormat) + .withLocale(locale) + .parseLocalDate(dateAsString.toLowerCase(locale)); + } catch (IllegalArgumentException e) { + List dataValidationErrors = new ArrayList(); + ApiParameterError error = ApiParameterError + .parameterError( + "validation.msg.invalid.date.format", + "The parameter " + + parameterName + + " is invalid based on the dateFormat provided:" + + dateFormat, parameterName, + dateAsString, dateFormat); + dataValidationErrors.add(error); + + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + } + + return eventLocalDate; + } + + private Integer convertToInteger(String numericalValueFormatted, String parameterName, Locale clientApplicationLocale) { + try { + Integer number = null; + + if (StringUtils.isNotBlank(numericalValueFormatted)) { + + String source = numericalValueFormatted.trim(); + + NumberFormat format = NumberFormat.getInstance(clientApplicationLocale); + DecimalFormat df = (DecimalFormat) format; + DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); + df.setParseBigDecimal(true); + + // http://bugs.sun.com/view_bug.do?bug_id=4510618 + char groupingSeparator = symbols.getGroupingSeparator(); + if (groupingSeparator == '\u00a0') { + source = source.replaceAll(" ", Character.toString('\u00a0')); + } + + Number parsedNumber = df.parse(source); + + double parsedNumberDouble = parsedNumber.doubleValue(); + int parsedNumberInteger = parsedNumber.intValue(); + + if (source.contains(Character.toString(symbols.getDecimalSeparator()))) { + throw new ParseException(source, 0); + } + + if (!Double.valueOf(parsedNumberDouble).equals(Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { + throw new ParseException(source, 0); + } + + number = parsedNumber.intValue(); + } + + return number; + } catch (ParseException e) { + + List dataValidationErrors = new ArrayList(); + ApiParameterError error = ApiParameterError.parameterError( + "validation.msg.invalid.integer.format", "The parameter " + + parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of [" + + clientApplicationLocale.toString() + "].", + parameterName, numericalValueFormatted, + clientApplicationLocale); + dataValidationErrors.add(error); + + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + } + + private BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) { + + if (clientApplicationLocale == null) { + + List dataValidationErrors = new ArrayList(); + String defaultMessage = new StringBuilder("The parameter '" + parameterName + "' requires a 'locale' parameter to be passed with it.").toString(); + ApiParameterError error = ApiParameterError.parameterError("validation.msg.missing.locale.parameter", defaultMessage, parameterName); + dataValidationErrors.add(error); + + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + + try { + BigDecimal number = null; + + if (StringUtils.isNotBlank(numericalValueFormatted)) { + + String source = numericalValueFormatted.trim(); + + NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale); + DecimalFormat df = (DecimalFormat) format; + DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); + // http://bugs.sun.com/view_bug.do?bug_id=4510618 + char groupingSeparator = symbols.getGroupingSeparator(); + if (groupingSeparator == '\u00a0') { + source = source.replaceAll(" ", Character.toString('\u00a0')); + } + + NumberFormatter numberFormatter = new NumberFormatter(); + Number parsedNumber = numberFormatter.parse(source, clientApplicationLocale); + number = BigDecimal.valueOf(Double.valueOf(parsedNumber.doubleValue())); + } + + return number; + } catch (ParseException e) { + + List dataValidationErrors = new ArrayList(); + ApiParameterError error = ApiParameterError.parameterError( + "validation.msg.invalid.decimal.format", "The parameter " + + parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of [" + + clientApplicationLocale.toString() + "].", + parameterName, numericalValueFormatted, + clientApplicationLocale); + dataValidationErrors.add(error); + + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + } + + private Locale localeFromString(final String localeAsString) { + + if (StringUtils.isBlank(localeAsString)) { + List dataValidationErrors = new ArrayList(); + ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale is invalid. It cannot be blank.", "locale"); + dataValidationErrors.add(error); + + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + + String languageCode = ""; + String courntryCode = ""; + String variantCode = ""; + + String[] localeParts = localeAsString.split("_"); + + if (localeParts != null && localeParts.length == 1) { + languageCode = localeParts[0]; + } + + if (localeParts != null && localeParts.length == 2) { + languageCode = localeParts[0]; + courntryCode = localeParts[1]; + } + + if (localeParts != null && localeParts.length == 3) { + languageCode = localeParts[0]; + courntryCode = localeParts[1]; + variantCode = localeParts[2]; + } + + return localeFrom(languageCode, courntryCode, variantCode); + } + + private Locale localeFrom(final String languageCode, final String courntryCode, final String variantCode) { + + List dataValidationErrors = new ArrayList(); + + List allowedLanguages = Arrays.asList(Locale.getISOLanguages()); + if (!allowedLanguages.contains(languageCode.toLowerCase())) { + ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale has an invalid language value " + languageCode + " .", "locale", languageCode); + dataValidationErrors.add(error); + } + + if (StringUtils.isNotBlank(courntryCode.toUpperCase())) { + List allowedCountries = Arrays.asList(Locale.getISOCountries()); + if (!allowedCountries.contains(courntryCode)) { + ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale has an invalid country value " + courntryCode + " .", "locale", courntryCode); + dataValidationErrors.add(error); + } + } + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + + return new Locale(languageCode.toLowerCase(), courntryCode.toUpperCase(), variantCode); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ParameterListExclusionStrategy.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ParameterListExclusionStrategy.java new file mode 100644 index 000000000..6633032ff --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ParameterListExclusionStrategy.java @@ -0,0 +1,26 @@ +package org.mifosng.platform.api.infrastructure; + +import java.util.Set; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; + +public class ParameterListExclusionStrategy implements ExclusionStrategy { + + private final Set parameterNamesToSkip; + + public ParameterListExclusionStrategy(final Set parameterNamesToSkip) { + this.parameterNamesToSkip = parameterNamesToSkip; + } + + @Override + public boolean shouldSkipField(FieldAttributes f) { + return parameterNamesToSkip.contains(f.getName()); + } + + @Override + public boolean shouldSkipClass(Class clazz) { + return false; + } + +}