/*
* 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.List;
import java.util.Properties;
import org.mifos.dto.domain.GLCodeDto;
import org.mifos.dto.screen.PenaltyParametersDto;
import org.springframework.util.StringUtils;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
public class PenaltyFormValidator implements Validator {
private final int digits;
private final int decimal;
@SuppressWarnings("unchecked")
public PenaltyFormValidator(Properties properties) {
this.digits = Integer.valueOf(properties.getProperty("digitsBeforeDecimal"));
this.decimal = Integer.valueOf(((List<Properties>) properties.get("currencies")).get(0).getProperty("digitsAfterDecimal"));
}
@Override
public boolean supports(Class<?> clazz) {
return PenaltyFormBean.class.isAssignableFrom(clazz) || PenaltyParametersDto.class.isAssignableFrom(clazz) || GLCodeDto.class.isAssignableFrom(clazz) ;
}
@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = { "REC_CATCH_EXCEPTION"}, justification = "Using catch all to detect invalid dates.")
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
@Override
public void validate(Object target, Errors errors) {
if(target instanceof PenaltyParametersDto) {
return;
}
PenaltyFormBean formBean = (PenaltyFormBean) target;
checkCategory(errors, formBean.getCategoryTypeId());
checkStatus(errors, formBean.getStatusId());
if(StringUtils.hasText(formBean.getPeriodTypeId()) && !formBean.getPeriodTypeId().equalsIgnoreCase("3")) {
checkNumber(errors, formBean.getDuration(), "Grace Period Duration", digits);
} else {
formBean.setDuration("");
}
emptyField(errors, formBean.getName(), "Penalty Name");
emptyField(errors, formBean.getFrequencyId(), "Penalty Application Frequency");
emptyField(errors, formBean.getGlCodeId(), "GL Code");
checkNumber(errors, formBean.getMin(), "Cumulative Penalty Limit (Minimum)", digits, decimal);
checkNumber(errors, formBean.getMax(), "Cumulative Penalty Limit (Maximum)", digits, decimal);
checkMinGreaterMax(errors, formBean.getMin(), formBean.getMax());
if(StringUtils.hasText(formBean.getCategoryTypeId()) && formBean.getCategoryTypeId().equalsIgnoreCase("1")) {
if (StringUtils.hasText(formBean.getRate()) && StringUtils.hasText(formBean.getAmount())) {
errors.reject("error.penalty.amountAndRateOrFormula");
} else if (StringUtils.hasText(formBean.getRate()) && StringUtils.hasText(formBean.getFormulaId())) {
checkNumber(errors, formBean.getRate(), "Rate", digits, decimal);
} else if (StringUtils.hasText(formBean.getRate()) && !StringUtils.hasText(formBean.getFormulaId())) {
errors.reject("error.penalty.rate");
} else if (StringUtils.hasText(formBean.getAmount())) {
checkNumber(errors, formBean.getAmount(), "Amount", digits, decimal);
} else {
errors.reject("error.penalty.amountAndRateOrFormula");
}
} else {
checkNumber(errors, formBean.getAmount(), "Amount", digits, decimal);
}
}
private void checkNumber(Errors errors, String value, String field, int digits, int decimal) {
int count = errors.getErrorCount();
emptyField(errors, value, field);
if (errors.getErrorCount() > count) {
return;
}
incorrectDoubleValue(errors, value, field, digits, decimal);
}
private void checkNumber(Errors errors, String value, String field, int digits) {
int count = errors.getErrorCount();
emptyField(errors, value, field);
if (errors.getErrorCount() > count) {
return;
}
incorrectIntegerValue(errors, value, field, digits);
}
private void incorrectDoubleValue(Errors errors, String value, String field, int digits, int decimal) {
if (value != null && StringUtils.hasText(value)) {
try {
Double val = Double.valueOf(value);
if (val < 0.0d) {
errors.reject("error.penalty.incorrectDouble", new String[] { field }, null);
} else if (Long.toString(val.longValue()).length() > digits) {
errors.reject("error.penalty.digitsBeforeDecimal", new String[] { field, Integer.toString(digits) }, null);
} else if (value.indexOf('.') >= 0 && value.substring(value.indexOf('.') + 1).length() > decimal) {
errors.reject("error.penalty.digitsAfterDecimal", new String[] { field, Integer.toString(decimal) }, null);
}
} catch (NumberFormatException e) {
errors.reject("error.penalty.incorrectDouble", new String[] { field }, null);
}
}
}
private void incorrectIntegerValue(Errors errors, String value, String field, int digits) {
if (value != null && StringUtils.hasText(value)) {
try {
long val = Long.valueOf(value);
if (val < 0) {
errors.reject("error.penalty.incorrectInteger", new String[] { field }, null);
} else if (value.length() > digits) {
errors.reject("error.penalty.digitsBeforeDecimal", new String[] { field, Integer.toString(digits) }, null);
}
} catch (NumberFormatException e) {
errors.reject("error.penalty.incorrectInteger", new String[] { field }, null);
}
}
}
private void emptyField(Errors errors, String value, String field) {
if(value == null || !StringUtils.hasText(value)) {
if(field == null) {
errors.reject("error.penalty.mandatory");
} else {
errors.reject("error.penalty.mandatory", new String[] { field }, null);
}
}
}
@SuppressWarnings("PMD.EmptyCatchBlock")
private void checkMinGreaterMax(Errors errors, String min, String max) {
if((min == null || !StringUtils.hasText(min)) || (max == null || !StringUtils.hasText(max))) {
return;
}
try {
Double minimum = Double.valueOf(min);
Double maximum = Double.valueOf(max);
if(minimum > 0 && maximum > 0 && Double.compare(minimum, maximum) > 0) {
errors.reject("error.penalty.minGreaterMax");
}
} catch (NumberFormatException e) {
//error was found in incorrectIntegerValue method
}
}
private void checkCategory(Errors errors, String value) {
if(value == null || !StringUtils.hasText(value)) {
errors.reject("error.penalty.category");
}
}
private void checkStatus(Errors errors, String value) {
if(value == null || !StringUtils.hasText(value)) {
errors.reject("error.penalty.status");
}
}
}