public static Object[] integerValues() {
    List<Integer> values = new ArrayList<Integer>();
    for (SavingsInterestCalculationDaysInYearType enumType : values()) {
      if (enumType.getValue() > 0) {
        values.add(enumType.getValue());
      }
    }

    return values.toArray();
  }
  public void validateForCreate(final String json) {

    if (StringUtils.isBlank(json)) {
      throw new InvalidJsonException();
    }

    final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
    fromApiJsonHelper.checkForUnsupportedParameters(
        typeOfMap, json, SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS);

    final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
    final DataValidatorBuilder baseDataValidator =
        new DataValidatorBuilder(dataValidationErrors).resource(SAVINGS_PRODUCT_RESOURCE_NAME);
    final JsonElement element = fromApiJsonHelper.parse(json);

    final String name = fromApiJsonHelper.extractStringNamed(nameParamName, element);
    baseDataValidator
        .reset()
        .parameter(nameParamName)
        .value(name)
        .notBlank()
        .notExceedingLengthOf(100);

    final String description = fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
    baseDataValidator
        .reset()
        .parameter(descriptionParamName)
        .value(description)
        .notBlank()
        .notExceedingLengthOf(500);

    final String currencyCode =
        fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
    baseDataValidator.reset().parameter(currencyCodeParamName).value(currencyCode).notBlank();

    final Integer digitsAfterDecimal =
        fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element);
    baseDataValidator
        .reset()
        .parameter(digitsAfterDecimalParamName)
        .value(digitsAfterDecimal)
        .notNull()
        .inMinMaxRange(0, 6);

    final Integer inMultiplesOf =
        fromApiJsonHelper.extractIntegerSansLocaleNamed(inMultiplesOfParamName, element);
    baseDataValidator
        .reset()
        .parameter(inMultiplesOfParamName)
        .value(inMultiplesOf)
        .ignoreIfNull()
        .integerZeroOrGreater();

    final BigDecimal nominalAnnualInterestRate =
        fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
            nominalAnnualInterestRateParamName, element);
    baseDataValidator
        .reset()
        .parameter(nominalAnnualInterestRateParamName)
        .value(nominalAnnualInterestRate)
        .notNull()
        .zeroOrPositiveAmount();

    final Integer interestCompoundingPeriodType =
        fromApiJsonHelper.extractIntegerSansLocaleNamed(
            interestCompoundingPeriodTypeParamName, element);
    baseDataValidator
        .reset()
        .parameter(interestCompoundingPeriodTypeParamName)
        .value(interestCompoundingPeriodType)
        .notNull()
        .isOneOfTheseValues(SavingsCompoundingInterestPeriodType.integerValues());

    final Integer interestPostingPeriodType =
        fromApiJsonHelper.extractIntegerSansLocaleNamed(
            interestPostingPeriodTypeParamName, element);
    baseDataValidator
        .reset()
        .parameter(interestPostingPeriodTypeParamName)
        .value(interestPostingPeriodType)
        .notNull()
        .isOneOfTheseValues(SavingsPostingInterestPeriodType.integerValues());

    final Integer interestCalculationType =
        fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
    baseDataValidator
        .reset()
        .parameter(interestCalculationTypeParamName)
        .value(interestCalculationType)
        .notNull()
        .isOneOfTheseValues(SavingsInterestCalculationType.integerValues());

    final Integer interestCalculationDaysInYearType =
        fromApiJsonHelper.extractIntegerSansLocaleNamed(
            interestCalculationDaysInYearTypeParamName, element);
    baseDataValidator
        .reset()
        .parameter(interestCalculationDaysInYearTypeParamName)
        .value(interestCalculationDaysInYearType)
        .notNull()
        .isOneOfTheseValues(SavingsInterestCalculationDaysInYearType.integerValues());

    if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
      final BigDecimal minOpeningBalance =
          fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
              minRequiredOpeningBalanceParamName, element);
      baseDataValidator
          .reset()
          .parameter(minRequiredOpeningBalanceParamName)
          .value(minOpeningBalance)
          .zeroOrPositiveAmount();
    }

    if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {

      final Integer lockinPeriodFrequency =
          fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
      baseDataValidator
          .reset()
          .parameter(lockinPeriodFrequencyParamName)
          .value(lockinPeriodFrequency)
          .integerZeroOrGreater();

      if (lockinPeriodFrequency != null) {
        final Integer lockinPeriodFrequencyType =
            fromApiJsonHelper.extractIntegerSansLocaleNamed(
                lockinPeriodFrequencyTypeParamName, element);
        baseDataValidator
            .reset()
            .parameter(lockinPeriodFrequencyTypeParamName)
            .value(lockinPeriodFrequencyType)
            .notNull()
            .inMinMaxRange(0, 3);
      }
    }

    if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
      final Integer lockinPeriodFrequencyType =
          fromApiJsonHelper.extractIntegerSansLocaleNamed(
              lockinPeriodFrequencyTypeParamName, element);
      baseDataValidator
          .reset()
          .parameter(lockinPeriodFrequencyTypeParamName)
          .value(lockinPeriodFrequencyType)
          .inMinMaxRange(0, 3);

      if (lockinPeriodFrequencyType != null) {
        final Integer lockinPeriodFrequency =
            fromApiJsonHelper.extractIntegerWithLocaleNamed(
                lockinPeriodFrequencyParamName, element);
        baseDataValidator
            .reset()
            .parameter(lockinPeriodFrequencyParamName)
            .value(lockinPeriodFrequency)
            .notNull()
            .integerZeroOrGreater();
      }
    }

    if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {

      final BigDecimal withdrawalFeeAmount =
          fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
      baseDataValidator
          .reset()
          .parameter(withdrawalFeeAmountParamName)
          .value(withdrawalFeeAmount)
          .zeroOrPositiveAmount();

      if (withdrawalFeeAmount != null) {
        final Integer withdrawalFeeType =
            fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
        baseDataValidator
            .reset()
            .parameter(withdrawalFeeTypeParamName)
            .value(withdrawalFeeType)
            .isOneOfTheseValues(SavingsWithdrawalFeesType.integerValues());
      }
    }

    if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
      final Integer withdrawalFeeType =
          fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
      baseDataValidator
          .reset()
          .parameter(withdrawalFeeTypeParamName)
          .value(withdrawalFeeType)
          .ignoreIfNull()
          .isOneOfTheseValues(1, 2);

      if (withdrawalFeeType != null) {
        final BigDecimal withdrawalFeeAmount =
            fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
                withdrawalFeeAmountParamName, element);
        baseDataValidator
            .reset()
            .parameter(withdrawalFeeAmountParamName)
            .value(withdrawalFeeAmount)
            .notNull()
            .zeroOrPositiveAmount();
      }
    }

    if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
      final BigDecimal annualFeeAmount =
          fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
      baseDataValidator
          .reset()
          .parameter(annualFeeAmountParamName)
          .value(annualFeeAmount)
          .zeroOrPositiveAmount();

      if (annualFeeAmount != null) {
        MonthDay monthDayOfAnnualFee =
            fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
        baseDataValidator
            .reset()
            .parameter(annualFeeOnMonthDayParamName)
            .value(monthDayOfAnnualFee)
            .notNull();
      }
    }

    if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {

      MonthDay monthDayOfAnnualFee =
          fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
      if (monthDayOfAnnualFee != null) {
        final BigDecimal annualFeeAmount =
            fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
        baseDataValidator
            .reset()
            .parameter(annualFeeAmountParamName)
            .value(annualFeeAmount)
            .notNull()
            .zeroOrPositiveAmount();
      }
    }

    // accounting related data validation
    final Integer accountingRuleType =
        fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
    baseDataValidator
        .reset()
        .parameter("accountingRule")
        .value(accountingRuleType)
        .notNull()
        .inMinMaxRange(1, 3);

    if (isCashBasedAccounting(accountingRuleType)) {

      final Long savingsControlAccountId =
          fromApiJsonHelper.extractLongNamed(
              SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), element);
      baseDataValidator
          .reset()
          .parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue())
          .value(savingsControlAccountId)
          .notNull()
          .integerGreaterThanZero();

      final Long savingsReferenceAccountId =
          fromApiJsonHelper.extractLongNamed(
              SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(), element);
      baseDataValidator
          .reset()
          .parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue())
          .value(savingsReferenceAccountId)
          .notNull()
          .integerGreaterThanZero();

      final Long interestOnSavingsAccountId =
          fromApiJsonHelper.extractLongNamed(
              SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), element);
      baseDataValidator
          .reset()
          .parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue())
          .value(interestOnSavingsAccountId)
          .notNull()
          .integerGreaterThanZero();

      final Long incomeFromFeeId =
          fromApiJsonHelper.extractLongNamed(
              SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
      baseDataValidator
          .reset()
          .parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue())
          .value(incomeFromFeeId)
          .notNull()
          .integerGreaterThanZero();

      validatePaymentChannelFundSourceMappings(baseDataValidator, element);
    }

    throwExceptionIfValidationWarningsExist(dataValidationErrors);
  }