diff --git a/build.gradle b/build.gradle index 2df93a1..acb875b 100644 --- a/build.gradle +++ b/build.gradle @@ -21,8 +21,8 @@ dependencies { compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.5' compile group: 'org.springframework', name:'spring-context', version: '4.2.4.RELEASE' compile group: 'net.sf.supercsv', name: 'super-csv', version: '2.4.0' - compile group: 'com.typesafe', name: 'config', version: '1.3.0' compile group: 'commons-validator', name: 'commons-validator', version: '1.5.0' compile group: 'de.jensd', name: 'fontawesomefx', version: '8.8' compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.10' + compile group: 'com.google.code.gson', name: 'gson', version: '2.5' } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java b/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java index a11d6ce..4c090d2 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java @@ -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 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) { diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java index bae0290..a5b32d6 100644 --- a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java @@ -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)) diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java index c295855..53d383f 100644 --- a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java +++ b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java @@ -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()); } } diff --git a/src/main/java/ninja/javafx/smartcsv/validation/HeaderConfiguration.java b/src/main/java/ninja/javafx/smartcsv/validation/HeaderConfiguration.java new file mode 100644 index 0000000..f5d1256 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/HeaderConfiguration.java @@ -0,0 +1,42 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015 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; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java new file mode 100644 index 0000000..586a3bc --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java @@ -0,0 +1,121 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015 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> 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 valueOfRuleFor(String column) { + if (noRulesFor(column)) return null; + return (List)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 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); + } + +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java index 82a29a9..4f53b3a 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java @@ -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() { diff --git a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java index 1446aaf..ab8da26 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java @@ -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 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 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 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 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 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