switched from config to Gson for better json support as the validation config will be editable in the application directly

This commit is contained in:
Andreas Billmann
2016-02-02 03:20:14 +01:00
parent d9405eb536
commit 10c2592510
12 changed files with 312 additions and 229 deletions

View File

@@ -30,6 +30,7 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
@@ -378,9 +379,9 @@ public class SmartCSVController extends FXMLController {
private void loadCsvPreferencesFromFile() {
if (PREFERENCES_FILE.exists()) {
useLoadFileService(preferencesLoader, PREFERENCES_FILE);
useLoadFileService(preferencesLoader, PREFERENCES_FILE,
event -> setCsvPreference(preferencesLoader.getCSVpreference()));
}
setCsvPreference(preferencesLoader.getCSVpreference());
}
private void saveCsvPreferences(CsvPreference csvPreference) {
@@ -431,7 +432,10 @@ public class SmartCSVController extends FXMLController {
//Show open file dialog
File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
if (file != null) {
useLoadFileService(fileReader, file);
useLoadFileService(fileReader, file, event -> runLater(() -> {
resetContent();
fileChanged.setValue(false);
}));
return file;
} else {
return initChildFile;
@@ -462,14 +466,11 @@ public class SmartCSVController extends FXMLController {
return file;
}
private void useLoadFileService(FileReader fileReader, File file) {
private void useLoadFileService(FileReader fileReader, File file, EventHandler<WorkerStateEvent> value) {
loadFileService.setFile(file);
loadFileService.setFileReader(fileReader);
loadFileService.restart();
loadFileService.setOnSucceeded(event -> runLater(() -> {
resetContent();
fileChanged.setValue(false);
}));
loadFileService.setOnSucceeded(value);
}
private void useSaveFileService(FileWriter writer, File file) {

View File

@@ -26,8 +26,7 @@
package ninja.javafx.smartcsv.preferences;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileReader;
import org.springframework.stereotype.Service;
import org.supercsv.prefs.CsvPreference;
@@ -35,6 +34,8 @@ import org.supercsv.quote.AlwaysQuoteMode;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteMode;
@@ -44,7 +45,7 @@ import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteMode;
@Service
public class PreferencesFileReader implements FileReader {
private Config config;
private Map config;
private CsvPreference csvPreference;
public PreferencesFileReader() {
@@ -55,15 +56,15 @@ public class PreferencesFileReader implements FileReader {
@Override
public void read(File filename) throws IOException {
config = ConfigFactory.parseFile(filename);
config = new GsonBuilder().create().fromJson(new java.io.FileReader(filename), HashMap.class);
if (config != null) {
char quoteChar = config.getString("quoteChar").charAt(0);
char delimiterChar = config.getString("delimiterChar").charAt(0);
String endOfLineSymbols = config.getString("endOfLineSymbols");
boolean surroundingSpacesNeedQuotes = config.getBoolean("surroundingSpacesNeedQuotes");
boolean ignoreEmptyLines = config.getBoolean("ignoreEmptyLines");
String quoteMode = config.getString("quoteMode");
char quoteChar = config.get("quoteChar").toString().charAt(0);
char delimiterChar = config.get("delimiterChar").toString().charAt(0);
String endOfLineSymbols = config.get("endOfLineSymbols").toString();
boolean surroundingSpacesNeedQuotes = (Boolean)config.get("surroundingSpacesNeedQuotes");
boolean ignoreEmptyLines = (Boolean)config.get("ignoreEmptyLines");
String quoteMode = config.get("quoteMode").toString();
csvPreference = new CsvPreference.Builder(quoteChar, delimiterChar, endOfLineSymbols)
.useQuoteMode(getQuoteMode(quoteMode))

View File

@@ -26,9 +26,8 @@
package ninja.javafx.smartcsv.preferences;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigRenderOptions;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileWriter;
import org.springframework.stereotype.Service;
import org.supercsv.prefs.CsvPreference;
@@ -60,8 +59,8 @@ public class PreferencesFileWriter implements FileWriter {
preferences.put("ignoreEmptyLines", csvPreference.isIgnoreEmptyLines());
preferences.put("quoteMode", QuoteModeHelper.getQuoteModeName(csvPreference.getQuoteMode()));
Config config = ConfigFactory.parseMap(preferences);
Files.write(file.toPath(), config.root().render(ConfigRenderOptions.concise()).getBytes());
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Files.write(file.toPath(), gson.toJson(preferences).getBytes());
}
}

View File

@@ -0,0 +1,42 @@
/*
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 com.google.gson.annotations.SerializedName;
/**
* header configuration for the validation
*/
public class HeaderConfiguration {
@SerializedName("list")
private String[] names ;
public String[] getNames() {
return names;
}
}

View File

@@ -0,0 +1,121 @@
/*
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 com.google.gson.annotations.SerializedName;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.lang.Boolean.FALSE;
/**
* validation configuration
*/
public class ValidationConfiguration {
@SerializedName("headers")
private HeaderConfiguration headerConfiguration = new HeaderConfiguration();
@SerializedName("columns")
private Map<String, Map<String, Object>> columnConfigurations = new HashMap<>();
public String[] headerNames() {
if (noHeader()) return null;
return headerConfiguration.getNames();
}
public Boolean integerRuleFor(String column) {
if (noRulesFor(column)) return FALSE;
return defaultValue((Boolean)columnConfigurations.get(column).get("integer"), FALSE);
}
public Boolean doubleRuleFor(String column) {
if (noRulesFor(column)) return FALSE;
return defaultValue((Boolean)columnConfigurations.get(column).get("double"), FALSE);
}
public Boolean notEmptyRuleFor(String column) {
if (noRulesFor(column)) return FALSE;
return defaultValue((Boolean)columnConfigurations.get(column).get("not empty"), FALSE);
}
public Integer minLengthRuleFor(String column) {
if (noRulesFor(column)) return null;
return doubleToInteger((Double)columnConfigurations.get(column).get("minlength"));
}
public Integer maxLengthRuleFor(String column) {
if (noRulesFor(column)) return null;
return doubleToInteger((Double)columnConfigurations.get(column).get("maxlength"));
}
public String dateRuleFor(String column) {
if (noRulesFor(column)) return null;
return (String)columnConfigurations.get(column).get("date");
}
public Boolean alphanumericRuleFor(String column) {
if (noRulesFor(column)) return FALSE;
return defaultValue((Boolean)columnConfigurations.get(column).get("alphanumeric"), FALSE);
}
public String regexpRuleFor(String column) {
if (noRulesFor(column)) return null;
return (String)columnConfigurations.get(column).get("regexp");
}
public List<String> valueOfRuleFor(String column) {
if (noRulesFor(column)) return null;
return (List<String>)columnConfigurations.get(column).get("value of");
}
public String groovyRuleFor(String column) {
if (noRulesFor(column)) return null;
return (String)columnConfigurations.get(column).get("groovy");
}
private boolean noHeader() {
return headerConfiguration == null;
}
private boolean noRulesFor(String column) {
return columnConfigurations == null || columnConfigurations.get(column) == null;
}
private <T> T defaultValue(T value, T defaultValue) {
if (value == null) return defaultValue;
return value;
}
private Integer doubleToInteger(Double value) {
if (value == null) return null;
return (int)Math.round(value);
}
}

View File

@@ -26,8 +26,7 @@
package ninja.javafx.smartcsv.validation;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileReader;
import org.springframework.stereotype.Service;
@@ -40,11 +39,11 @@ import java.io.IOException;
@Service
public class ValidationFileReader implements FileReader {
private Config config;
private ValidationConfiguration config;
@Override
public void read(File file) throws IOException {
config = ConfigFactory.parseFile(file);
config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class);
}
public Validator getValidator() {

View File

@@ -26,7 +26,6 @@
package ninja.javafx.smartcsv.validation;
import com.typesafe.config.Config;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
@@ -49,7 +48,7 @@ public class Validator {
// member variables
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private Config validationConfig;
private ValidationConfiguration validationConfig;
private GroovyShell shell = new GroovyShell();
private Map<String, Script> scriptCache = new HashMap<>();
@@ -62,7 +61,7 @@ public class Validator {
* JSON configuration for this validator
* @param validationConfig
*/
public Validator(Config validationConfig) {
public Validator(ValidationConfiguration validationConfig) {
this.validationConfig = validationConfig;
}
@@ -80,29 +79,23 @@ public class Validator {
public ValidationError isValid(String column, String value, Integer lineNumber) {
ValidationError result = null;
if (validationConfig != null) {
Config columnSectionConfig = getColumnSectionConfig();
if (columnSectionConfig != null) {
Config columnConfig = getColumnConfig(columnSectionConfig, column);
if (columnConfig != null) {
ValidationError error = ValidationError.withLineNumber(lineNumber);
checkBlankOrNull(columnConfig, value, error);
if (value != null && !value.isEmpty()) {
checkRegularExpression(columnConfig, value, error);
checkAlphaNumeric(columnConfig, value, error);
checkDate(columnConfig, value, error);
checkMaxLength(columnConfig, value, error);
checkMinLength(columnConfig, value, error);
checkInteger(columnConfig, value, error);
checkGroovy(column, columnConfig, value, error);
checkValueOf(columnConfig, value, error);
checkDouble(columnConfig, value, error);
}
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);
}
if (!error.isEmpty()) {
result = error;
}
}
if (!error.isEmpty()) {
result = error;
}
}
return result;
@@ -113,8 +106,8 @@ public class Validator {
// private methods
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void checkGroovy(String column, Config columnConfig, String value, ValidationError error) {
String groovyScript = getString(columnConfig, "groovy");
private void checkGroovy(String column, String value, ValidationError error) {
String groovyScript = validationConfig.groovyRuleFor(column);
if (groovyScript != null) {
Script script = scriptCache.get(column);
@@ -149,43 +142,42 @@ public class Validator {
return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true");
}
private void checkValueOf(Config columnConfig, String value, ValidationError error) {
List<String> stringList = getStringList(columnConfig, "value of");
if (stringList != null) {
if (!stringList.contains(value)) {
String commaSeparated = stringList.stream().collect(joining(", "));
private void checkValueOf(String column, String value, ValidationError error) {
List<String> values = validationConfig.valueOfRuleFor(column);
if (values != null) {
if (!values.contains(value)) {
String commaSeparated = values.stream().collect(joining(", "));
error.add("validation.message.value.of", value, commaSeparated);
}
}
}
private void checkBlankOrNull(Config columnConfig, String value, ValidationError error) {
if (getBoolean(columnConfig, "not empty")) {
private void checkBlankOrNull(String column, String value, ValidationError error) {
if (validationConfig.notEmptyRuleFor(column)) {
if (isBlankOrNull(value)) {
error.add("validation.message.not.empty");
}
}
}
private void checkInteger(Config columnConfig, String value, ValidationError error) {
if (getBoolean(columnConfig, "integer")) {
private void checkInteger(String column, String value, ValidationError error) {
if (validationConfig.integerRuleFor(column)) {
if (!isInt(value)) {
error.add("validation.message.integer");
}
}
}
private void checkDouble(Config columnConfig, String value, ValidationError error) {
if (getBoolean(columnConfig, "double")) {
private void checkDouble(String column, String value, ValidationError error) {
if (validationConfig.doubleRuleFor(column)) {
if (!isDouble(value)) {
error.add("validation.message.double");
}
}
}
private void checkMinLength(Config columnConfig, String value, ValidationError error) {
Integer minLength = getInteger(columnConfig, "minlength");
private void checkMinLength(String column, String value, ValidationError error) {
Integer minLength = validationConfig.minLengthRuleFor(column);
if (minLength != null) {
if (!minLength(value, minLength)) {
error.add("validation.message.min.length", minLength.toString());
@@ -193,8 +185,8 @@ public class Validator {
}
}
private void checkMaxLength(Config columnConfig, String value, ValidationError error) {
Integer maxLength = getInteger(columnConfig, "maxlength");
private void checkMaxLength(String column, String value, ValidationError error) {
Integer maxLength = validationConfig.maxLengthRuleFor(column);
if (maxLength != null) {
if (!maxLength(value, maxLength)) {
error.add("validation.message.max.length", maxLength.toString());
@@ -202,8 +194,8 @@ public class Validator {
}
}
private void checkDate(Config columnConfig, String value, ValidationError error) {
String dateformat = getString(columnConfig, "date");
private void checkDate(String column, String value, ValidationError error) {
String dateformat = validationConfig.dateRuleFor(column);
if (dateformat != null && !dateformat.trim().isEmpty()) {
if (!isDate(value, dateformat, true)) {
error.add("validation.message.date.format", dateformat);
@@ -211,16 +203,16 @@ public class Validator {
}
}
private void checkAlphaNumeric(Config columnConfig, String value, ValidationError error) {
if (getBoolean(columnConfig, "alphanumeric")) {
private void checkAlphaNumeric(String column, String value, ValidationError error) {
if (validationConfig.alphanumericRuleFor(column)) {
if (!matchRegexp(value, "[0-9a-zA-Z]*")) {
error.add("validation.message.alphanumeric");
}
}
}
private void checkRegularExpression(Config columnConfig, String value, ValidationError error) {
String regexp = getString(columnConfig, "regexp");
private void checkRegularExpression(String column, String value, ValidationError error) {
String regexp = validationConfig.regexpRuleFor(column);
if (regexp != null && !regexp.trim().isEmpty()) {
if (!matchRegexp(value, regexp)) {
error.add("validation.message.regexp", regexp);
@@ -228,60 +220,31 @@ public class Validator {
}
}
private Config getColumnSectionConfig() {
return validationConfig.hasPath("columns") ? validationConfig.getConfig("columns") : null;
}
private Config getColumnConfig(Config columnSectionConfig, String column) {
return columnSectionConfig.hasPath(column) ? columnSectionConfig.getConfig(column) : null;
}
private String getString(Config columnConfig, String path) {
return columnConfig.hasPath(path) ? columnConfig.getString(path) : null;
}
private Integer getInteger(Config columnConfig, String path) {
return columnConfig.hasPath(path) ? columnConfig.getInt(path) : null;
}
private boolean getBoolean(Config columnConfig, String path) {
return columnConfig.hasPath(path) && columnConfig.getBoolean(path);
}
private List<String> getStringList(Config columnConfig, String path) {
return columnConfig.hasPath(path) ? columnConfig.getStringList(path) : null;
}
public ValidationError isHeaderValid(String[] headerNames) {
ValidationError result = null;
if (validationConfig != null) {
if (validationConfig.hasPath("headers")) {
Config headerSectionConfig = validationConfig.getConfig("headers");
List<String> headerConfig = getStringList(headerSectionConfig, "list");
if (headerConfig != null) {
if (headerNames.length != headerConfig.size()) {
result = ValidationError.withoutLineNumber().add("validation.message.header.length",
Integer.toString(headerNames.length),
Integer.toString(headerConfig.size()));
return result;
}
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;
}
ValidationError error = ValidationError.withoutLineNumber();
ValidationError error = ValidationError.withoutLineNumber();
for(int i=0; i<headerConfig.size(); i++) {
String header = headerConfig.get(i);
if (!header.equals(headerNames[i])) {
error.add("validation.message.header.match",
Integer.toString(i),
header,
headerNames[i]);
}
}
if (!error.isEmpty()) {
result = error;
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]);
}
}
if (!error.isEmpty()) {
result = error;
}
}
}
return result;