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;
|
|
|
|
|
|
2016-08-09 20:58:16 +02:00
|
|
|
import ninja.javafx.smartcsv.fx.table.model.ColumnValueProvider;
|
|
|
|
|
|
2015-11-28 23:06:14 +01:00
|
|
|
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;
|
|
|
|
|
|
2016-09-01 22:05:31 +02:00
|
|
|
import static ninja.javafx.smartcsv.validation.ValidationFormatHelper.dateFormat;
|
|
|
|
|
import static ninja.javafx.smartcsv.validation.ValidationFormatHelper.doubleToInteger;
|
2016-09-01 00:01:13 +02:00
|
|
|
|
2015-11-28 23:06:14 +01:00
|
|
|
/**
|
|
|
|
|
* 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;
|
2016-08-09 20:58:16 +02:00
|
|
|
private ColumnValueProvider columnValueProvider;
|
2016-08-07 23:13:02 +02:00
|
|
|
private Map<String, Map<Validation.Type, Validation>> columnValidationMap = new HashMap<>();
|
2015-11-28 23:06:14 +01:00
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// constructors
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* JSON configuration for this validator
|
2016-08-07 23:13:02 +02:00
|
|
|
*
|
2015-11-28 23:06:14 +01:00
|
|
|
* @param validationConfig
|
|
|
|
|
*/
|
2016-08-09 20:58:16 +02:00
|
|
|
public Validator(ValidationConfiguration validationConfig, ColumnValueProvider columnValueProvider) {
|
2016-08-07 23:13:02 +02:00
|
|
|
this.validationConfig = validationConfig;
|
2016-08-09 20:58:16 +02:00
|
|
|
this.columnValueProvider = columnValueProvider;
|
2016-08-07 16:57:55 +02:00
|
|
|
initColumnValidations();
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
2016-07-22 20:45:26 +02:00
|
|
|
// public methods
|
2015-11-28 23:06:14 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2016-08-07 23:13:02 +02:00
|
|
|
public boolean needsColumnValidation(String column) {
|
|
|
|
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
|
|
|
|
if (validationMap != null) {
|
|
|
|
|
return validationMap.containsKey(Validation.Type.UNIQUE);
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-11-28 23:06:14 +01:00
|
|
|
/**
|
|
|
|
|
* checks if the value is valid for the column configuration
|
2016-08-07 23:13:02 +02:00
|
|
|
*
|
2015-11-28 23:06:14 +01:00
|
|
|
* @param column the column name
|
2016-08-07 23:13:02 +02:00
|
|
|
* @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
|
|
|
*/
|
2016-08-07 23:13:02 +02:00
|
|
|
public ValidationError isValid(Integer row, String column, String value) {
|
2015-12-07 22:41:59 +01:00
|
|
|
ValidationError result = null;
|
2016-07-22 20:45:26 +02:00
|
|
|
if (hasConfig()) {
|
2016-08-10 23:41:47 +02:00
|
|
|
ValidationError error = ValidationError.withLineNumber(row).column(column);
|
2016-08-07 23:13:02 +02:00
|
|
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
|
|
|
|
if (validationMap != null) {
|
|
|
|
|
for (Validation validation: validationMap.values()) {
|
2016-08-09 17:25:05 +02:00
|
|
|
if (validation.canBeChecked(value)) {
|
2016-08-07 23:13:02 +02:00
|
|
|
validation.check(row, value, 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-08-07 16:57:55 +02:00
|
|
|
|
2016-07-22 20:45:26 +02:00
|
|
|
public boolean hasConfig() {
|
|
|
|
|
return validationConfig != null;
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-08-07 23:13:02 +02:00
|
|
|
public void reinitializeColumn(String column) {
|
|
|
|
|
clear(column);
|
|
|
|
|
initializeColumnWithRules(column);
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-28 23:06:14 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// private methods
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2016-08-07 23:13:02 +02:00
|
|
|
private void add(String column, Validation validation) {
|
|
|
|
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
|
|
|
|
if (validationMap == null) {
|
|
|
|
|
validationMap = new HashMap<>();
|
|
|
|
|
columnValidationMap.put(column, validationMap);
|
|
|
|
|
}
|
|
|
|
|
validationMap.put(validation.getType(), validation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void clear(String column) {
|
|
|
|
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
|
|
|
|
if (validationMap != null) {
|
|
|
|
|
validationMap.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-07 16:57:55 +02:00
|
|
|
private void initColumnValidations() {
|
|
|
|
|
if (hasConfig()) {
|
2016-09-01 00:01:13 +02:00
|
|
|
for (FieldConfiguration column : validationConfig.getFieldConfigurations()) {
|
2016-08-07 23:13:02 +02:00
|
|
|
initializeColumnWithRules(column);
|
2016-08-05 23:09:22 +02:00
|
|
|
}
|
2016-08-07 23:13:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 00:01:13 +02:00
|
|
|
private void initializeColumnWithRules(String columnName) {
|
|
|
|
|
if (hasConfig()) {
|
|
|
|
|
for (FieldConfiguration column : validationConfig.getFieldConfigurations()) {
|
|
|
|
|
if (column.getName().equals(columnName)) {
|
|
|
|
|
initializeColumnWithRules(column);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-07 23:13:02 +02:00
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 00:01:13 +02:00
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 00:01:13 +02:00
|
|
|
private void initializeColumnWithRules(FieldConfiguration column) {
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 00:01:13 +02:00
|
|
|
if (column.getType() != null) {
|
2016-09-01 08:12:26 +02:00
|
|
|
if (column.getType() == FieldConfiguration.Type.NUMBER) {
|
2016-09-01 00:01:13 +02:00
|
|
|
add(column.getName(), new DoubleValidation());
|
|
|
|
|
}
|
2015-12-17 23:41:20 +01:00
|
|
|
|
2016-09-01 08:12:26 +02:00
|
|
|
if (column.getType() == FieldConfiguration.Type.INTEGER) {
|
2016-09-01 00:01:13 +02:00
|
|
|
add(column.getName(), new IntegerValidation());
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 08:12:26 +02:00
|
|
|
if (column.getType() == FieldConfiguration.Type.DATE) {
|
2016-09-01 00:01:13 +02:00
|
|
|
String format = dateFormat(column.getFormat(), "YYYY-MM-DD");
|
|
|
|
|
add(column.getName(), new DateValidation(format));
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 08:12:26 +02:00
|
|
|
if (column.getType() == FieldConfiguration.Type.DATETIME) {
|
2016-09-01 00:01:13 +02:00
|
|
|
String format = dateFormat(column.getFormat(), "YYYY-MM-DDThh:mm:ssZ");
|
|
|
|
|
add(column.getName(), new DateValidation(format));
|
|
|
|
|
}
|
2015-12-17 23:55:08 +01:00
|
|
|
|
2016-09-01 08:12:26 +02:00
|
|
|
if (column.getType() == FieldConfiguration.Type.TIME) {
|
2016-09-01 00:01:13 +02:00
|
|
|
String format = dateFormat(column.getFormat(), "hh:mm:ss");
|
|
|
|
|
add(column.getName(), new DateValidation(format));
|
|
|
|
|
}
|
2016-08-07 23:13:02 +02:00
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
|
2016-09-01 00:01:13 +02:00
|
|
|
if (column.getConstraints() != null) {
|
|
|
|
|
Boolean notEmptyRule = (Boolean)column.getConstraints().get("required");
|
|
|
|
|
if (notEmptyRule != null && notEmptyRule) {
|
|
|
|
|
add(column.getName(), new NotEmptyValidation());
|
|
|
|
|
}
|
2016-08-07 23:13:02 +02:00
|
|
|
|
2016-09-01 00:01:13 +02:00
|
|
|
Boolean uniqueRule = (Boolean)column.getConstraints().get("unique");
|
|
|
|
|
if (uniqueRule != null && uniqueRule) {
|
|
|
|
|
add(column.getName(), new UniqueValidation(columnValueProvider, column.getName()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Integer minLength = doubleToInteger((Double)column.getConstraints().get("minLength"));
|
|
|
|
|
if (minLength != null) {
|
|
|
|
|
add(column.getName(), new MinLengthValidation(minLength));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Integer maxLength = doubleToInteger((Double)column.getConstraints().get("maxLength"));
|
|
|
|
|
if (maxLength != null) {
|
|
|
|
|
add(column.getName(), new MaxLengthValidation(maxLength));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String regexp = (String)column.getConstraints().get("pattern");
|
|
|
|
|
if (regexp != null && !regexp.trim().isEmpty()) {
|
|
|
|
|
add(column.getName(), new RegExpValidation(regexp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String groovy = (String)column.getConstraints().get("groovy");
|
|
|
|
|
if (groovy != null && !groovy.trim().isEmpty()) {
|
|
|
|
|
add(column.getName(), new GroovyValidation(groovy));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<String> valueOfRule = (List<String>)column.getConstraints().get("enum");
|
|
|
|
|
if (valueOfRule != null && !valueOfRule.isEmpty()) {
|
|
|
|
|
add(column.getName(), new ValueOfValidation(valueOfRule));
|
|
|
|
|
}
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-09-01 00:01:13 +02: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-08-07 23:13:02 +02:00
|
|
|
for (int i = 0; i < headerNamesConfig.length; i++) {
|
2016-02-02 03:20:14 +01:00
|
|
|
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-09-01 00:01:13 +02:00
|
|
|
|
2016-09-01 22:05:31 +02:00
|
|
|
|
2015-11-28 23:06:14 +01:00
|
|
|
}
|