2015-11-28 23:06:14 +01:00
|
|
|
/*
|
|
|
|
|
The MIT License (MIT)
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Copyright (c) 2015 javafx.ninja <info@javafx.ninja>
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package ninja.javafx.smartcsv.validation;
|
|
|
|
|
|
|
|
|
|
import groovy.lang.Binding;
|
|
|
|
|
import groovy.lang.GroovyShell;
|
|
|
|
|
import groovy.lang.Script;
|
|
|
|
|
import org.codehaus.groovy.control.CompilationFailedException;
|
|
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
2015-12-04 16:22:21 +01:00
|
|
|
import java.util.List;
|
2015-11-28 23:06:14 +01:00
|
|
|
import java.util.Map;
|
|
|
|
|
|
2015-12-17 23:41:20 +01:00
|
|
|
import static java.util.stream.Collectors.joining;
|
2015-11-28 23:06:14 +01:00
|
|
|
import static org.apache.commons.validator.GenericValidator.*;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This class checks all the validations defined in the
|
|
|
|
|
* Config against a given value
|
|
|
|
|
*/
|
|
|
|
|
public class Validator {
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// member variables
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private ValidationConfiguration validationConfig;
|
2015-11-28 23:06:14 +01:00
|
|
|
private GroovyShell shell = new GroovyShell();
|
|
|
|
|
private Map<String, Script> scriptCache = new HashMap<>();
|
2016-08-05 23:09:22 +02:00
|
|
|
private Map<String, HashMap<String, Integer>> uniquenessLookupTable = new HashMap<>();
|
2015-11-28 23:06:14 +01:00
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// constructors
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* JSON configuration for this validator
|
|
|
|
|
* @param validationConfig
|
|
|
|
|
*/
|
2016-02-02 03:20:14 +01:00
|
|
|
public Validator(ValidationConfiguration validationConfig) {
|
2015-11-28 23:06:14 +01:00
|
|
|
this.validationConfig = validationConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
2016-07-22 20:45:26 +02:00
|
|
|
// public methods
|
2015-11-28 23:06:14 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* checks if the value is valid for the column configuration
|
|
|
|
|
* @param column the column name
|
|
|
|
|
* @param value the value to check
|
2015-12-07 22:41:59 +01:00
|
|
|
* @return ValidationError with information if valid and if not which getMessage happened
|
2015-11-28 23:06:14 +01:00
|
|
|
*/
|
2015-12-07 22:41:59 +01:00
|
|
|
public ValidationError isValid(String column, String value, Integer lineNumber) {
|
|
|
|
|
ValidationError result = null;
|
2016-07-22 20:45:26 +02:00
|
|
|
if (hasConfig()) {
|
2015-12-07 22:41:59 +01:00
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
ValidationError error = ValidationError.withLineNumber(lineNumber);
|
|
|
|
|
checkBlankOrNull(column, value, error);
|
|
|
|
|
if (value != null && !value.isEmpty()) {
|
|
|
|
|
checkRegularExpression(column, value, error);
|
|
|
|
|
checkAlphaNumeric(column, value, error);
|
|
|
|
|
checkDate(column, value, error);
|
|
|
|
|
checkMaxLength(column, value, error);
|
|
|
|
|
checkMinLength(column, value, error);
|
|
|
|
|
checkInteger(column, value, error);
|
|
|
|
|
checkGroovy(column, value, error);
|
|
|
|
|
checkValueOf(column, value, error);
|
|
|
|
|
checkDouble(column, value, error);
|
2016-08-05 23:09:22 +02:00
|
|
|
checkUniqueness(column, value, lineNumber, error);
|
2016-02-02 03:20:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!error.isEmpty()) {
|
|
|
|
|
result = error;
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-22 20:45:26 +02:00
|
|
|
public boolean hasConfig() {
|
|
|
|
|
return validationConfig != null;
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// private methods
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2016-08-05 23:09:22 +02:00
|
|
|
private void checkUniqueness(String column, String value, Integer lineNumber, ValidationError error) {
|
2016-08-05 23:45:23 +02:00
|
|
|
if (validationConfig.getUniqueRuleFor(column) != null && validationConfig.getUniqueRuleFor(column)) {
|
2016-08-05 23:09:22 +02:00
|
|
|
HashMap<String, Integer> columnValueMap = uniquenessLookupTable.get(column);
|
|
|
|
|
columnValueMap = getColumnValueMap(column, columnValueMap);
|
|
|
|
|
Integer valueInLineNumber = columnValueMap.get(value);
|
|
|
|
|
if (valueInLineNumber != null) {
|
|
|
|
|
if (!valueInLineNumber.equals(lineNumber)) {
|
|
|
|
|
error.add("validation.message.uniqueness", value, valueInLineNumber.toString());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
columnValueMap.put(value, lineNumber);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private HashMap<String, Integer> getColumnValueMap(String column, HashMap<String, Integer> valueLineNumber) {
|
|
|
|
|
if (valueLineNumber == null) {
|
|
|
|
|
valueLineNumber = new HashMap<>();
|
|
|
|
|
uniquenessLookupTable.put(column, valueLineNumber);
|
|
|
|
|
}
|
|
|
|
|
return valueLineNumber;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkGroovy(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
String groovyScript = validationConfig.getGroovyRuleFor(column);
|
2015-11-28 23:06:14 +01:00
|
|
|
if (groovyScript != null) {
|
|
|
|
|
|
|
|
|
|
Script script = scriptCache.get(column);
|
|
|
|
|
if (script == null) {
|
|
|
|
|
script = shell.parse(groovyScript);
|
|
|
|
|
scriptCache.put(column, script);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Binding binding = new Binding();
|
|
|
|
|
binding.setVariable("value", value);
|
|
|
|
|
script.setBinding(binding);
|
|
|
|
|
|
|
|
|
|
Object groovyResult = null;
|
|
|
|
|
try {
|
|
|
|
|
groovyResult = script.run();
|
|
|
|
|
} catch (CompilationFailedException e) {
|
2015-12-17 22:09:32 +01:00
|
|
|
error.add("validation.message.groovy.exception", groovyScript, e.getMessage());
|
2015-11-28 23:06:14 +01:00
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
if (groovyResult == null) {
|
2015-12-17 22:09:32 +01:00
|
|
|
error.add("validation.message.groovy.return.null", groovyScript);
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isScriptResultTrue(groovyResult)) {
|
2015-12-17 21:32:52 +01:00
|
|
|
error.add(groovyResult.toString());
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean isScriptResultTrue(Object groovyResult) {
|
|
|
|
|
return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true");
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkValueOf(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
List<String> values = validationConfig.getValueOfRuleFor(column);
|
2016-02-02 03:20:14 +01:00
|
|
|
if (values != null) {
|
|
|
|
|
if (!values.contains(value)) {
|
|
|
|
|
String commaSeparated = values.stream().collect(joining(", "));
|
2015-12-17 23:41:20 +01:00
|
|
|
error.add("validation.message.value.of", value, commaSeparated);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkBlankOrNull(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
if (validationConfig.getNotEmptyRuleFor(column) != null && validationConfig.getNotEmptyRuleFor(column)) {
|
2015-11-28 23:06:14 +01:00
|
|
|
if (isBlankOrNull(value)) {
|
2015-12-17 21:32:52 +01:00
|
|
|
error.add("validation.message.not.empty");
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkInteger(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
if (validationConfig.getIntegerRuleFor(column) != null && validationConfig.getIntegerRuleFor(column)) {
|
2015-11-28 23:06:14 +01:00
|
|
|
if (!isInt(value)) {
|
2015-12-17 21:32:52 +01:00
|
|
|
error.add("validation.message.integer");
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkDouble(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
if (validationConfig.getDoubleRuleFor(column) != null && validationConfig.getDoubleRuleFor(column)) {
|
2015-12-17 23:55:08 +01:00
|
|
|
if (!isDouble(value)) {
|
|
|
|
|
error.add("validation.message.double");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkMinLength(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
Integer minLength = validationConfig.getMinLengthRuleFor(column);
|
2015-11-28 23:06:14 +01:00
|
|
|
if (minLength != null) {
|
|
|
|
|
if (!minLength(value, minLength)) {
|
2015-12-17 22:09:32 +01:00
|
|
|
error.add("validation.message.min.length", minLength.toString());
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkMaxLength(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
Integer maxLength = validationConfig.getMaxLengthRuleFor(column);
|
2015-11-28 23:06:14 +01:00
|
|
|
if (maxLength != null) {
|
|
|
|
|
if (!maxLength(value, maxLength)) {
|
2015-12-17 22:09:32 +01:00
|
|
|
error.add("validation.message.max.length", maxLength.toString());
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkDate(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
String dateformat = validationConfig.getDateRuleFor(column);
|
2015-11-28 23:06:14 +01:00
|
|
|
if (dateformat != null && !dateformat.trim().isEmpty()) {
|
|
|
|
|
if (!isDate(value, dateformat, true)) {
|
2015-12-17 22:09:32 +01:00
|
|
|
error.add("validation.message.date.format", dateformat);
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkAlphaNumeric(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
if (validationConfig.getAlphanumericRuleFor(column) != null && validationConfig.getAlphanumericRuleFor(column)) {
|
2015-11-28 23:06:14 +01:00
|
|
|
if (!matchRegexp(value, "[0-9a-zA-Z]*")) {
|
2015-12-17 21:32:52 +01:00
|
|
|
error.add("validation.message.alphanumeric");
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
private void checkRegularExpression(String column, String value, ValidationError error) {
|
2016-02-05 08:00:32 +01:00
|
|
|
String regexp = validationConfig.getRegexpRuleFor(column);
|
2015-11-28 23:06:14 +01:00
|
|
|
if (regexp != null && !regexp.trim().isEmpty()) {
|
|
|
|
|
if (!matchRegexp(value, regexp)) {
|
2015-12-17 22:09:32 +01:00
|
|
|
error.add("validation.message.regexp", regexp);
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 22:41:59 +01:00
|
|
|
public ValidationError isHeaderValid(String[] headerNames) {
|
|
|
|
|
ValidationError result = null;
|
2015-12-04 16:22:21 +01:00
|
|
|
if (validationConfig != null) {
|
2016-02-02 03:20:14 +01:00
|
|
|
String[] headerNamesConfig = validationConfig.headerNames();
|
|
|
|
|
if (headerNamesConfig != null) {
|
|
|
|
|
if (headerNames.length != headerNamesConfig.length) {
|
|
|
|
|
result = ValidationError.withoutLineNumber().add("validation.message.header.length",
|
|
|
|
|
Integer.toString(headerNames.length),
|
|
|
|
|
Integer.toString(headerNamesConfig.length));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2015-12-04 16:22:21 +01:00
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
ValidationError error = ValidationError.withoutLineNumber();
|
2015-12-07 22:41:59 +01:00
|
|
|
|
2016-02-02 03:20:14 +01:00
|
|
|
for(int i=0; i<headerNamesConfig.length; i++) {
|
|
|
|
|
if (!headerNamesConfig[i].equals(headerNames[i])) {
|
|
|
|
|
error.add("validation.message.header.match",
|
|
|
|
|
Integer.toString(i),
|
|
|
|
|
headerNamesConfig[i],
|
|
|
|
|
headerNames[i]);
|
2015-12-17 23:41:20 +01:00
|
|
|
}
|
2015-12-04 16:22:21 +01:00
|
|
|
}
|
2016-02-02 03:20:14 +01:00
|
|
|
if (!error.isEmpty()) {
|
|
|
|
|
result = error;
|
|
|
|
|
}
|
2015-12-04 16:22:21 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2016-07-30 17:12:34 +02:00
|
|
|
|
|
|
|
|
public void clearScriptCache() {
|
|
|
|
|
scriptCache.clear();
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|