public void validateForCreate()

in fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java [110:549]


    public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans, final LoanProduct loanProduct) {
        if (StringUtils.isBlank(json)) {
            throw new InvalidJsonException();
        }

        final Type typeOfMap = new TypeToken<Map<String, Object>>() {

        }.getType();
        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);

        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");

        final JsonElement element = this.fromApiJsonHelper.parse(json);

        final String loanTypeStr = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.loanTypeParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.loanTypeParameterName).value(loanTypeStr).notNull();

        if (!StringUtils.isBlank(loanTypeStr)) {
            final AccountType loanType = AccountType.fromName(loanTypeStr);
            baseDataValidator.reset().parameter(LoanApiConstants.loanTypeParameterName).value(loanType.getValue()).inMinMaxRange(1, 4);

            final Long clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element);
            final Long groupId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.groupIdParameterName, element);
            if (loanType.isIndividualAccount()) {
                baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull().longGreaterThanZero();
                baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId)
                        .mustBeBlankWhenParameterProvided(LoanApiConstants.clientIdParameterName, clientId);
            }

            if (loanType.isGroupAccount()) {
                baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull().longGreaterThanZero();
                baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId)
                        .mustBeBlankWhenParameterProvided(LoanApiConstants.groupIdParameterName, groupId);
            }

            if (loanType.isJLGAccount()) {
                baseDataValidator.reset().parameter(LoanApiConstants.clientIdParameterName).value(clientId).notNull()
                        .integerGreaterThanZero();
                baseDataValidator.reset().parameter(LoanApiConstants.groupIdParameterName).value(groupId).notNull().longGreaterThanZero();

                // if it is JLG loan that must have meeting details
                if (isMeetingMandatoryForJLGLoans) {

                    final Long calendarId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.calendarIdParameterName, element);
                    baseDataValidator.reset().parameter(LoanApiConstants.calendarIdParameterName).value(calendarId).notNull()
                            .integerGreaterThanZero();

                    // if it is JLG loan then must have a value for
                    // syncDisbursement passed in
                    final Boolean syncDisbursement = this.fromApiJsonHelper
                            .extractBooleanNamed(LoanApiConstants.syncDisbursementWithMeetingParameterName, element);

                    if (syncDisbursement == null) {
                        baseDataValidator.reset().parameter(LoanApiConstants.syncDisbursementWithMeetingParameterName)
                                .value(syncDisbursement).trueOrFalseRequired(false);
                    }
                }

            }

        }

        boolean isEqualAmortization = false;
        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.isEqualAmortizationParam, element)) {
            isEqualAmortization = this.fromApiJsonHelper.extractBooleanNamed(LoanApiConstants.isEqualAmortizationParam, element);
            baseDataValidator.reset().parameter(LoanApiConstants.isEqualAmortizationParam).value(isEqualAmortization).ignoreIfNull()
                    .validateForBooleanValue();
            if (isEqualAmortization && loanProduct.isInterestRecalculationEnabled()) {
                throw new EqualAmortizationUnsupportedFeatureException("interest.recalculation", "interest recalculation");
            }
        }

        BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
                .extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
                .value(fixedPrincipalPercentagePerInstallment).notLessThanMin(BigDecimal.ONE).notGreaterThanMax(BigDecimal.valueOf(100));

        final Long productId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.productIdParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.productIdParameterName).value(productId).notNull().integerGreaterThanZero();

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.accountNoParameterName, element)) {
            final String accountNo = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.accountNoParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.accountNoParameterName).value(accountNo).ignoreIfNull()
                    .notExceedingLengthOf(20);
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.externalIdParameterName, element)) {
            final String externalId = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.externalIdParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.externalIdParameterName).value(externalId).ignoreIfNull()
                    .notExceedingLengthOf(100);
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.fundIdParameterName, element)) {
            final Long fundId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.fundIdParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.fundIdParameterName).value(fundId).ignoreIfNull().integerGreaterThanZero();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanOfficerIdParameterName, element)) {
            final Long loanOfficerId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.loanOfficerIdParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.loanOfficerIdParameterName).value(loanOfficerId).ignoreIfNull()
                    .integerGreaterThanZero();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.loanPurposeIdParameterName, element)) {
            final Long loanPurposeId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.loanPurposeIdParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.loanPurposeIdParameterName).value(loanPurposeId).ignoreIfNull()
                    .integerGreaterThanZero();
        }

        final BigDecimal principal = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.principalParamName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.principalParamName).value(principal).notNull().positiveAmount();

        final Integer loanTermFrequency = this.fromApiJsonHelper
                .extractIntegerWithLocaleNamed(LoanApiConstants.loanTermFrequencyParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.loanTermFrequencyParameterName).value(loanTermFrequency).notNull()
                .integerGreaterThanZero();

        final Integer loanTermFrequencyType = this.fromApiJsonHelper
                .extractIntegerSansLocaleNamed(LoanApiConstants.loanTermFrequencyTypeParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.loanTermFrequencyTypeParameterName).value(loanTermFrequencyType).notNull()
                .inMinMaxRange(0, 3);

        final Integer numberOfRepayments = this.fromApiJsonHelper
                .extractIntegerWithLocaleNamed(LoanApiConstants.numberOfRepaymentsParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.numberOfRepaymentsParameterName).value(numberOfRepayments).notNull()
                .integerGreaterThanZero();

        final Integer repaymentEvery = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(LoanApiConstants.repaymentEveryParameterName,
                element);
        baseDataValidator.reset().parameter(LoanApiConstants.repaymentEveryParameterName).value(repaymentEvery).notNull()
                .integerGreaterThanZero();

        final Integer repaymentEveryType = this.fromApiJsonHelper
                .extractIntegerSansLocaleNamed(LoanApiConstants.repaymentFrequencyTypeParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.repaymentFrequencyTypeParameterName).value(repaymentEveryType).notNull()
                .inMinMaxRange(0, 3);

        CalendarUtils.validateNthDayOfMonthFrequency(baseDataValidator, LoanApiConstants.repaymentFrequencyNthDayTypeParameterName,
                LoanApiConstants.repaymentFrequencyDayOfWeekTypeParameterName, element, this.fromApiJsonHelper);

        final Integer interestType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(LoanApiConstants.interestTypeParameterName,
                element);
        baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).value(interestType).notNull().inMinMaxRange(0, 1);

        final Integer interestCalculationPeriodType = this.fromApiJsonHelper
                .extractIntegerSansLocaleNamed(LoanApiConstants.interestCalculationPeriodTypeParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.interestCalculationPeriodTypeParameterName)
                .value(interestCalculationPeriodType).notNull().inMinMaxRange(0, 1);

        if (loanProduct.isLinkedToFloatingInterestRate()) {
            if (isEqualAmortization) {
                throw new EqualAmortizationUnsupportedFeatureException("floating.interest.rate", "floating interest rate");
            }
            if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestRatePerPeriodParameterName, element)) {
                baseDataValidator.reset().parameter(LoanApiConstants.interestRatePerPeriodParameterName).failWithCode(
                        "not.supported.loanproduct.linked.to.floating.rate",
                        "interestRatePerPeriod param is not supported, selected Loan Product is linked with floating interest rate.");
            }

            if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.isFloatingInterestRate, element)) {
                final Boolean isFloatingInterestRate = this.fromApiJsonHelper.extractBooleanNamed(LoanApiConstants.isFloatingInterestRate,
                        element);
                if (isFloatingInterestRate != null && isFloatingInterestRate
                        && !loanProduct.getFloatingRates().isFloatingInterestRateCalculationAllowed()) {
                    baseDataValidator.reset().parameter(LoanApiConstants.isFloatingInterestRate).failWithCode(
                            "true.not.supported.for.selected.loanproduct",
                            "isFloatingInterestRate value of true not supported for selected Loan Product.");
                }
            } else {
                baseDataValidator.reset().parameter(LoanApiConstants.isFloatingInterestRate).trueOrFalseRequired(false);
            }

            if (interestType != null && interestType.equals(InterestMethod.FLAT.getValue())) {
                baseDataValidator.reset().parameter(LoanApiConstants.interestTypeParameterName).failWithCode(
                        "should.be.0.for.selected.loan.product",
                        "interestType should be DECLINING_BALANCE for selected Loan Product as it is linked to floating rates.");
            }

            final String interestRateDifferentialParameterName = LoanApiConstants.interestRateDifferential;
            final BigDecimal interestRateDifferential = this.fromApiJsonHelper
                    .extractBigDecimalWithLocaleNamed(interestRateDifferentialParameterName, element);
            baseDataValidator.reset().parameter(interestRateDifferentialParameterName).value(interestRateDifferential).notNull()
                    .zeroOrPositiveAmount().inMinAndMaxAmountRange(loanProduct.getFloatingRates().getMinDifferentialLendingRate(),
                            loanProduct.getFloatingRates().getMaxDifferentialLendingRate());

        } else {

            if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.isFloatingInterestRate, element)) {
                baseDataValidator.reset().parameter(LoanApiConstants.isFloatingInterestRate).failWithCode(
                        "not.supported.loanproduct.not.linked.to.floating.rate",
                        "isFloatingInterestRate param is not supported, selected Loan Product is not linked with floating interest rate.");
            }
            if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestRateDifferential, element)) {
                baseDataValidator.reset().parameter(LoanApiConstants.interestRateDifferential).failWithCode(
                        "not.supported.loanproduct.not.linked.to.floating.rate",
                        "interestRateDifferential param is not supported, selected Loan Product is not linked with floating interest rate.");
            }

            final BigDecimal interestRatePerPeriod = this.fromApiJsonHelper
                    .extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRatePerPeriodParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.interestRatePerPeriodParameterName).value(interestRatePerPeriod).notNull()
                    .zeroOrPositiveAmount();

        }

        final Integer amortizationType = this.fromApiJsonHelper
                .extractIntegerSansLocaleNamed(LoanApiConstants.amortizationTypeParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.amortizationTypeParameterName).value(amortizationType).notNull()
                .inMinMaxRange(0, 1);

        if (!AmortizationMethod.EQUAL_PRINCIPAL.getValue().equals(amortizationType) && fixedPrincipalPercentagePerInstallment != null) {
            baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName).failWithCode(
                    "not.supported.principal.fixing.not.allowed.with.equal.installments",
                    "Principal fixing cannot be done with equal installment amortization");
        }

        final LocalDate expectedDisbursementDate = this.fromApiJsonHelper
                .extractLocalDateNamed(LoanApiConstants.expectedDisbursementDateParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.expectedDisbursementDateParameterName).value(expectedDisbursementDate)
                .notNull();

        // grace validation
        final Integer graceOnPrincipalPayment = this.fromApiJsonHelper
                .extractIntegerWithLocaleNamed(LoanApiConstants.graceOnPrincipalPaymentParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.graceOnPrincipalPaymentParameterName).value(graceOnPrincipalPayment)
                .zeroOrPositiveAmount();

        final Integer graceOnInterestPayment = this.fromApiJsonHelper
                .extractIntegerWithLocaleNamed(LoanApiConstants.graceOnInterestPaymentParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.graceOnInterestPaymentParameterName).value(graceOnInterestPayment)
                .zeroOrPositiveAmount();

        final Integer graceOnInterestCharged = this.fromApiJsonHelper
                .extractIntegerWithLocaleNamed(LoanApiConstants.graceOnInterestChargedParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.graceOnInterestChargedParameterName).value(graceOnInterestCharged)
                .zeroOrPositiveAmount();

        final Integer graceOnArrearsAgeing = this.fromApiJsonHelper
                .extractIntegerWithLocaleNamed(LoanProductConstants.GRACE_ON_ARREARS_AGEING_PARAMETER_NAME, element);
        baseDataValidator.reset().parameter(LoanProductConstants.GRACE_ON_ARREARS_AGEING_PARAMETER_NAME).value(graceOnArrearsAgeing)
                .zeroOrPositiveAmount();

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.interestChargedFromDateParameterName, element)) {
            final LocalDate interestChargedFromDate = this.fromApiJsonHelper
                    .extractLocalDateNamed(LoanApiConstants.interestChargedFromDateParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.interestChargedFromDateParameterName).value(interestChargedFromDate)
                    .ignoreIfNull().notNull();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.repaymentsStartingFromDateParameterName, element)) {
            final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper
                    .extractLocalDateNamed(LoanApiConstants.repaymentsStartingFromDateParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.repaymentsStartingFromDateParameterName).value(repaymentsStartingFromDate)
                    .ignoreIfNull().notNull();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.inArrearsToleranceParameterName, element)) {
            final BigDecimal inArrearsTolerance = this.fromApiJsonHelper
                    .extractBigDecimalWithLocaleNamed(LoanApiConstants.inArrearsToleranceParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.inArrearsToleranceParameterName).value(inArrearsTolerance).ignoreIfNull()
                    .zeroOrPositiveAmount();
        }

        final LocalDate submittedOnDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.submittedOnDateParameterName,
                element);
        if (submittedOnDate == null) {
            baseDataValidator.reset().parameter(LoanApiConstants.submittedOnDateParameterName).value(submittedOnDate).notNull();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.submittedOnNoteParameterName, element)) {
            final String submittedOnNote = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.submittedOnNoteParameterName,
                    element);
            baseDataValidator.reset().parameter(LoanApiConstants.submittedOnNoteParameterName).value(submittedOnNote).ignoreIfNull()
                    .notExceedingLengthOf(500);
        }

        final String transactionProcessingStrategy = this.fromApiJsonHelper
                .extractStringNamed(LoanApiConstants.transactionProcessingStrategyCodeParameterName, element);
        baseDataValidator.reset().parameter(LoanApiConstants.transactionProcessingStrategyCodeParameterName)
                .value(transactionProcessingStrategy).notNull();
        // Validating whether the processor is existing
        loanRepaymentScheduleTransactionProcessorFactory.determineProcessor(transactionProcessingStrategy);

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.linkAccountIdParameterName, element)) {
            final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.linkAccountIdParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.linkAccountIdParameterName).value(linkAccountId).ignoreIfNull()
                    .longGreaterThanZero();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.createStandingInstructionAtDisbursementParameterName, element)) {
            final Boolean createStandingInstructionAtDisbursement = this.fromApiJsonHelper
                    .extractBooleanNamed(LoanApiConstants.createStandingInstructionAtDisbursementParameterName, element);
            final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.linkAccountIdParameterName, element);

            if (createStandingInstructionAtDisbursement) {
                baseDataValidator.reset().parameter(LoanApiConstants.linkAccountIdParameterName).value(linkAccountId).notNull()
                        .longGreaterThanZero();
            }
        }

        // charges
        if (element.isJsonObject() && this.fromApiJsonHelper.parameterExists(LoanApiConstants.chargesParameterName, element)) {
            final JsonObject topLevelJsonElement = element.getAsJsonObject();
            final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement);
            final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);

            if (topLevelJsonElement.get(LoanApiConstants.chargesParameterName).isJsonArray()) {
                final Type arrayObjectParameterTypeOfMap = new TypeToken<Map<String, Object>>() {

                }.getType();
                final Set<String> supportedParameters = new HashSet<>(
                        Arrays.asList(LoanApiConstants.idParameterName, LoanApiConstants.chargeIdParameterName,
                                LoanApiConstants.amountParameterName, LoanApiConstants.chargeTimeTypeParameterName,
                                LoanApiConstants.chargeCalculationTypeParameterName, LoanApiConstants.dueDateParamName));

                final JsonArray array = topLevelJsonElement.get(LoanApiConstants.chargesParameterName).getAsJsonArray();
                for (int i = 1; i <= array.size(); i++) {

                    final JsonObject loanChargeElement = array.get(i - 1).getAsJsonObject();
                    final String arrayObjectJson = this.fromApiJsonHelper.toJson(loanChargeElement);
                    this.fromApiJsonHelper.checkForUnsupportedParameters(arrayObjectParameterTypeOfMap, arrayObjectJson,
                            supportedParameters);

                    final Long chargeId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.chargeIdParameterName,
                            loanChargeElement);
                    baseDataValidator.reset().parameter(LoanApiConstants.chargesParameterName)
                            .parameterAtIndexArray(LoanApiConstants.chargeIdParameterName, i).value(chargeId).notNull()
                            .integerGreaterThanZero();

                    final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalNamed(LoanApiConstants.amountParameterName,
                            loanChargeElement, locale);
                    baseDataValidator.reset().parameter(LoanApiConstants.chargesParameterName)
                            .parameterAtIndexArray(LoanApiConstants.amountParameterName, i).value(amount).notNull().positiveAmount();

                    this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.dueDateParamName, loanChargeElement, dateFormat, locale);
                }
            }
        }

        /**
         * TODO: Add collaterals for other loan accounts if needed. For now it's only applicable for individual
         * accounts. (loanType.isJLG() || loanType.isGLIM())
         */

        if (!StringUtils.isBlank(loanTypeStr)) {
            final AccountType loanType = AccountType.fromName(loanTypeStr);

            // collateral
            if (loanType.isIndividualAccount() && element.isJsonObject()
                    && this.fromApiJsonHelper.parameterExists(LoanApiConstants.collateralParameterName, element)) {
                final JsonObject topLevelJsonElement = element.getAsJsonObject();
                final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
                if (topLevelJsonElement.get(LoanApiConstants.collateralParameterName).isJsonArray()) {

                    final Type collateralParameterTypeOfMap = new TypeToken<Map<String, Object>>() {

                    }.getType();
                    final Set<String> supportedParameters = new HashSet<>(
                            Arrays.asList(LoanApiConstants.clientCollateralIdParameterName, LoanApiConstants.quantityParameterName));
                    final JsonArray array = topLevelJsonElement.get(LoanApiConstants.collateralParameterName).getAsJsonArray();
                    for (int i = 1; i <= array.size(); i++) {
                        final JsonObject collateralItemElement = array.get(i - 1).getAsJsonObject();

                        final String collateralJson = this.fromApiJsonHelper.toJson(collateralItemElement);
                        this.fromApiJsonHelper.checkForUnsupportedParameters(collateralParameterTypeOfMap, collateralJson,
                                supportedParameters);

                        final Long clientCollateralId = this.fromApiJsonHelper
                                .extractLongNamed(LoanApiConstants.clientCollateralIdParameterName, collateralItemElement);
                        baseDataValidator.reset().parameter(LoanApiConstants.collateralParameterName)
                                .parameterAtIndexArray(LoanApiConstants.clientCollateralIdParameterName, i).value(clientCollateralId)
                                .notNull().integerGreaterThanZero();

                        final BigDecimal quantity = this.fromApiJsonHelper.extractBigDecimalNamed(LoanApiConstants.quantityParameterName,
                                collateralItemElement, locale);
                        baseDataValidator.reset().parameter(LoanApiConstants.collateralParameterName)
                                .parameterAtIndexArray(LoanApiConstants.quantityParameterName, i).value(quantity).notNull()
                                .positiveAmount();

                        final ClientCollateralManagement clientCollateralManagement = this.clientCollateralManagementRepositoryWrapper
                                .getCollateral(clientCollateralId);

                        if (clientCollateralId != null && BigDecimal.valueOf(0).compareTo(clientCollateralManagement.getQuantity()) >= 0) {
                            throw new InvalidAmountOfCollateralQuantity(clientCollateralManagement.getQuantity());
                        }
                    }
                } else {
                    baseDataValidator.reset().parameter(LoanApiConstants.collateralParameterName).expectedArrayButIsNot();
                }
            }
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.emiAmountParameterName, element)) {
            if (!(loanProduct.canDefineInstallmentAmount() || loanProduct.isMultiDisburseLoan())) {
                List<String> unsupportedParameterList = new ArrayList<>();
                unsupportedParameterList.add(LoanApiConstants.emiAmountParameterName);
                throw new UnsupportedParameterException(unsupportedParameterList);
            }
            if (isEqualAmortization) {
                throw new EqualAmortizationUnsupportedFeatureException("fixed.emi", "fixed emi");
            }
            final BigDecimal emiAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(LoanApiConstants.emiAmountParameterName,
                    element);
            baseDataValidator.reset().parameter(LoanApiConstants.emiAmountParameterName).value(emiAmount).ignoreIfNull().positiveAmount();
        }
        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.maxOutstandingBalanceParameterName, element)) {
            final BigDecimal maxOutstandingBalance = this.fromApiJsonHelper
                    .extractBigDecimalWithLocaleNamed(LoanApiConstants.maxOutstandingBalanceParameterName, element);
            baseDataValidator.reset().parameter(LoanApiConstants.maxOutstandingBalanceParameterName).value(maxOutstandingBalance)
                    .ignoreIfNull().positiveAmount();
        }

        if (loanProduct.canUseForTopup() && this.fromApiJsonHelper.parameterExists(LoanApiConstants.isTopup, element)) {
            final Boolean isTopup = this.fromApiJsonHelper.extractBooleanNamed(LoanApiConstants.isTopup, element);
            baseDataValidator.reset().parameter(LoanApiConstants.isTopup).value(isTopup).validateForBooleanValue();

            if (isTopup != null && isTopup) {
                final Long loanId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.loanIdToClose, element);
                baseDataValidator.reset().parameter(LoanApiConstants.loanIdToClose).value(loanId).notNull().longGreaterThanZero();
            }
        }
        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.datatables, element)) {
            final JsonArray datatables = this.fromApiJsonHelper.extractJsonArrayNamed(LoanApiConstants.datatables, element);
            baseDataValidator.reset().parameter(LoanApiConstants.datatables).value(datatables).notNull().jsonArrayNotEmpty();
        }

        if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.daysInYearTypeParameterName, element)) {
            final Integer daysInYearType = this.fromApiJsonHelper.extractIntegerNamed(LoanApiConstants.daysInYearTypeParameterName, element,
                    Locale.getDefault());
            baseDataValidator.reset().parameter(LoanApiConstants.daysInYearTypeParameterName).value(daysInYearType).notNull()
                    .isOneOfTheseValues(1, 360, 364, 365);
        }

        validateLoanMultiDisbursementDate(element, baseDataValidator, expectedDisbursementDate, principal);
        validatePartialPeriodSupport(interestCalculationPeriodType, baseDataValidator, element, loanProduct);
        if (!dataValidationErrors.isEmpty()) {
            throw new PlatformApiDataValidationException(dataValidationErrors);
        }
    }