/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.ui.core.controller;
import java.util.Set;
import javax.validation.ConstraintViolation;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") // suppress optimisation rule
public class LoanProductFormBeanValidator {
private LocalValidatorFactoryBean validator;
public void validate(LoanProductFormBean loanProductFormBean, BindingResult result) {
validateLoanAmount(loanProductFormBean, result);
validateInterestRateRange(loanProductFormBean, result);
validateInstallments(loanProductFormBean, result);
}
private void validateInterestRateRange(LoanProductFormBean loanProductFormBean, BindingResult result) {
if (!result.hasErrors()) {
if (loanProductFormBean.getMinInterestRate() > loanProductFormBean.getMaxInterestRate()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Range.loanProduct.maxInterestRate" }, new Object[] {},
"The min must be less than max.");
result.addError(error);
}
if (loanProductFormBean.getDefaultInterestRate() < loanProductFormBean.getMinInterestRate()
|| loanProductFormBean.getDefaultInterestRate() > loanProductFormBean.getMaxInterestRate()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Range.loanProduct.defaultInterestRate" }, new Object[] {},
"The min must be less than max.");
result.addError(error);
}
}
}
private void validateInstallments(LoanProductFormBean loanProductFormBean, BindingResult result) {
Integer loanAmountType = Integer.valueOf(loanProductFormBean.getSelectedInstallmentsCalculationType());
switch (loanAmountType) {
case 1:
SameForAllLoanBean sameForAllLoanBean = loanProductFormBean.getInstallmentsSameForAllLoans();
Set<ConstraintViolation<SameForAllLoanBean>> violations = validator.validate(sameForAllLoanBean);
convertInstallmentsSameForAllLoansJsr303ViolationsToSpringErrors(result, sameForAllLoanBean, violations);
break;
case 2:
ByLastLoanAmountBean[] byLastLoanAmounts = loanProductFormBean.getInstallmentsByLastLoanAmount();
int lastLoanRow = 0;
for (ByLastLoanAmountBean byLoanCycle : byLastLoanAmounts) {
Set<ConstraintViolation<ByLastLoanAmountBean>> cycleViolations = validator.validate(byLoanCycle);
convertInstallmentsByLastLoanJsr303ViolationsToSpringErrors(result, lastLoanRow, byLoanCycle,
cycleViolations);
lastLoanRow++;
}
break;
case 3:
ByLoanCycleBean[] byLoanCycleBeans = loanProductFormBean.getInstallmentsByLoanCycle();
int loanCycleRow = 0;
for (ByLoanCycleBean byLoanCycle : byLoanCycleBeans) {
Set<ConstraintViolation<ByLoanCycleBean>> cycleViolations = validator.validate(byLoanCycle);
convertInstallmentsByLoanCycleJsr303ViolationsToSpringErrors(result, loanCycleRow, byLoanCycle,
cycleViolations);
loanCycleRow++;
}
break;
default:
break;
}
}
private void convertInstallmentsByLoanCycleJsr303ViolationsToSpringErrors(BindingResult result, int loanCycleRow,
ByLoanCycleBean byLoanCycle, Set<ConstraintViolation<ByLoanCycleBean>> cycleViolations) {
for (ConstraintViolation<ByLoanCycleBean> constraintViolation : cycleViolations) {
ObjectError error = new ObjectError("loanProduct", new String[] { buildViolationMessage(
"loanProduct.installmentsByLoanCycle", constraintViolation) }, new Object[] {loanCycleRow + 1},
constraintViolation.getMessage());
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.minIsLessThanMax()) {
ObjectError error = new ObjectError("loanProduct", new String[] { "Max.loanProduct.installmentsByLoanCycle.max" },
new Object[] {loanCycleRow + 1}, "The min must be less than max.");
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.defaultIsBetweenMinAndMax()) {
ObjectError error = new ObjectError("loanProduct", new String[] { "Max.loanProduct.installmentsByLoanCycle.theDefault" },
new Object[] {loanCycleRow + 1}, "The default is not within min and max range.");
result.addError(error);
}
}
private void convertInstallmentsByLastLoanJsr303ViolationsToSpringErrors(BindingResult result, int lastLoanRow,
ByLastLoanAmountBean byLoanCycle, Set<ConstraintViolation<ByLastLoanAmountBean>> cycleViolations) {
for (ConstraintViolation<ByLastLoanAmountBean> constraintViolation : cycleViolations) {
ObjectError error = new ObjectError("loanProduct", new String[] { buildViolationMessage(
"loanProduct.installmentsByLastLoanAmount", constraintViolation) }, new Object[] {lastLoanRow + 1},
constraintViolation.getMessage());
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.isRangeValid()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.installmentsByLastLoanAmount.upper" },
new Object[] {lastLoanRow + 1}, "The upper value must be greater than lower.");
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.minIsLessThanMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.installmentsByLastLoanAmount.max" },
new Object[] {lastLoanRow + 1}, "The min must be less than max.");
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.defaultIsBetweenMinAndMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.installmentsByLastLoanAmount.theDefault" },
new Object[] {lastLoanRow + 1}, "The default is not within min and max range.");
result.addError(error);
}
}
private void convertInstallmentsSameForAllLoansJsr303ViolationsToSpringErrors(BindingResult result,
SameForAllLoanBean sameForAllLoanBean, Set<ConstraintViolation<SameForAllLoanBean>> violations) {
for (ConstraintViolation<SameForAllLoanBean> constraintViolation : violations) {
ObjectError error = new ObjectError("loanProduct", new String[] { buildViolationMessage(
"loanProduct.installmentsSameForAllLoans", constraintViolation) }, new Object[] {},
constraintViolation.getMessage());
result.addError(error);
}
if (violations.isEmpty() && !sameForAllLoanBean.minIsLessThanMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.installmentsSameForAllLoans.max" }, new Object[] {},
"The min must be less than max.");
result.addError(error);
}
if (violations.isEmpty() && !sameForAllLoanBean.defaultIsBetweenMinAndMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.installmentsSameForAllLoans.theDefault" }, new Object[] {},
"The default is not within min and max range.");
result.addError(error);
}
}
private void validateLoanAmount(LoanProductFormBean loanProductFormBean, BindingResult result) {
Integer loanAmountType = Integer.valueOf(loanProductFormBean.getSelectedLoanAmountCalculationType());
switch (loanAmountType) {
case 1:
SameForAllLoanBean sameForAllLoanBean = loanProductFormBean.getLoanAmountSameForAllLoans();
Set<ConstraintViolation<SameForAllLoanBean>> violations = validator.validate(sameForAllLoanBean);
convertLoanAmountSameForAllLoansJsr303ViolationsToSpringErrors(result, sameForAllLoanBean, violations);
break;
case 2:
ByLastLoanAmountBean[] byLastLoanAmounts = loanProductFormBean.getLoanAmountByLastLoanAmount();
int lastLoanRow = 0;
for (ByLastLoanAmountBean byLoanCycle : byLastLoanAmounts) {
Set<ConstraintViolation<ByLastLoanAmountBean>> cycleViolations = validator.validate(byLoanCycle);
convertLoanAmountByLastLoanJsr303ViolationsToSpringErrors(result, lastLoanRow, byLoanCycle,
cycleViolations);
lastLoanRow++;
}
break;
case 3:
ByLoanCycleBean[] byLoanCycleBeans = loanProductFormBean.getLoanAmountByLoanCycle();
int loanCycleRow = 0;
for (ByLoanCycleBean byLoanCycle : byLoanCycleBeans) {
Set<ConstraintViolation<ByLoanCycleBean>> cycleViolations = validator.validate(byLoanCycle);
convertLoanAmountByLoanCycleJsr303ViolationsToSpringErrors(result, loanCycleRow, byLoanCycle,
cycleViolations);
loanCycleRow++;
}
break;
default:
break;
}
}
private void convertLoanAmountByLoanCycleJsr303ViolationsToSpringErrors(BindingResult result, int loanCycleRow,
ByLoanCycleBean byLoanCycle, Set<ConstraintViolation<ByLoanCycleBean>> cycleViolations) {
for (ConstraintViolation<ByLoanCycleBean> constraintViolation : cycleViolations) {
ObjectError error = new ObjectError("loanProduct", new String[] { buildViolationMessage(
"loanProduct.loanAmountByLoanCycle", constraintViolation) }, new Object[] {loanCycleRow + 1},
constraintViolation.getMessage());
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.minIsLessThanMax()) {
ObjectError error = new ObjectError("loanProduct", new String[] { "Max.loanProduct.loanAmountByLoanCycle.max" },
new Object[] {loanCycleRow + 1}, "The min must be less than max.");
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.defaultIsBetweenMinAndMax()) {
ObjectError error = new ObjectError("loanProduct", new String[] { "Max.loanProduct.loanAmountByLoanCycle.theDefault" },
new Object[] {loanCycleRow + 1}, "The default is not within min and max range.");
result.addError(error);
}
}
private void convertLoanAmountByLastLoanJsr303ViolationsToSpringErrors(BindingResult result, int lastLoanRow,
ByLastLoanAmountBean byLoanCycle, Set<ConstraintViolation<ByLastLoanAmountBean>> cycleViolations) {
for (ConstraintViolation<ByLastLoanAmountBean> constraintViolation : cycleViolations) {
ObjectError error = new ObjectError("loanProduct", new String[] { buildViolationMessage(
"loanProduct.loanAmountByLastLoanAmount", constraintViolation) }, new Object[] {lastLoanRow+1},
constraintViolation.getMessage());
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.isRangeValid()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.loanAmountByLastLoanAmount.upper" },
new Object[] {lastLoanRow + 1}, "The upper value must be greater than lower.");
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.minIsLessThanMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.loanAmountByLastLoanAmount.max" },
new Object[] {lastLoanRow + 1}, "The min must be less than max.");
result.addError(error);
}
if (cycleViolations.isEmpty() && !byLoanCycle.defaultIsBetweenMinAndMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.loanAmountByLastLoanAmount.theDefault" },
new Object[] {lastLoanRow + 1}, "The default is not within min and max range.");
result.addError(error);
}
}
private void convertLoanAmountSameForAllLoansJsr303ViolationsToSpringErrors(BindingResult result,
SameForAllLoanBean sameForAllLoanBean, Set<ConstraintViolation<SameForAllLoanBean>> violations) {
for (ConstraintViolation<SameForAllLoanBean> constraintViolation : violations) {
ObjectError error = new ObjectError("loanProduct", new String[] { buildViolationMessage(
"loanProduct.sameForAllLoans", constraintViolation) }, new Object[] {}, constraintViolation
.getMessage());
result.addError(error);
}
if (violations.isEmpty() && !sameForAllLoanBean.minIsLessThanMax()) {
ObjectError error = new ObjectError("loanProduct", new String[] { "Max.loanProduct.sameForAllLoans.max" },
new Object[] {}, "The min must be less than max.");
result.addError(error);
}
if (violations.isEmpty() && !sameForAllLoanBean.defaultIsBetweenMinAndMax()) {
ObjectError error = new ObjectError("loanProduct",
new String[] { "Max.loanProduct.sameForAllLoans.theDefault" }, new Object[] {},
"The default is not within min and max range.");
result.addError(error);
}
}
private String buildViolationMessage(String objectName, ConstraintViolation<?> constraintViolation) {
StringBuilder builder = new StringBuilder();
String constraintMessage = constraintViolation.getMessageTemplate().substring(30);
String constraintType = constraintMessage.substring(0, constraintMessage.indexOf('.'));
builder.append(constraintType).append('.').append(objectName).append('.').append(
constraintViolation.getPropertyPath().toString());
return builder.toString();
}
public void setValidator(LocalValidatorFactoryBean validator) {
this.validator = validator;
}
}