diff --git a/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java b/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java index a48570f..99f077f 100644 --- a/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/csv/CSVFileReader.java @@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.csv; import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.fx.table.model.CSVModel; import ninja.javafx.smartcsv.fx.table.model.CSVRow; -import org.springframework.stereotype.Service; import org.supercsv.io.CsvMapReader; import org.supercsv.io.ICsvMapReader; @@ -60,7 +59,7 @@ public class CSVFileReader extends CSVConfigurable implements FileReader { validationEditorController.updateConfiguration(); currentCsvFile.setFileChanged(true); - currentCsvFile.getContent().revalidate(); + currentCsvFile.getContent().revalidate(column); }); } } @@ -590,7 +583,7 @@ public class SmartCSVController extends FXMLController { * @param header name of the column header * @param tableView the tableview */ - private void addColumn(String header, TableView tableView) { + private void addColumn(final String header, TableView tableView) { TableColumn column = new TableColumn(header); column.setCellValueFactory(new ObservableMapValueFactory(header)); column.setCellFactory(cellFactory); @@ -607,7 +600,6 @@ public class SmartCSVController extends FXMLController { getColumns().get(header).setValue(event.getNewValue()); runLater(() -> { currentCsvFile.setFileChanged(true); - currentCsvFile.getContent().revalidate(); }); } }); diff --git a/src/main/java/ninja/javafx/smartcsv/fx/list/ErrorSideBar.java b/src/main/java/ninja/javafx/smartcsv/fx/list/ErrorSideBar.java index cca48f6..6b2cfa4 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/list/ErrorSideBar.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/list/ErrorSideBar.java @@ -36,7 +36,6 @@ import javafx.scene.layout.Region; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import ninja.javafx.smartcsv.fx.table.model.CSVModel; -import ninja.javafx.smartcsv.fx.util.ColorConstants; import ninja.javafx.smartcsv.validation.ValidationError; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/ninja/javafx/smartcsv/fx/list/GotoLineDialog.java b/src/main/java/ninja/javafx/smartcsv/fx/list/GotoLineDialog.java index f187ff6..e92e2ef 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/list/GotoLineDialog.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/list/GotoLineDialog.java @@ -1,6 +1,5 @@ package ninja.javafx.smartcsv.fx.list; -import com.sun.javafx.scene.control.skin.resources.ControlResources; import javafx.application.Platform; import javafx.geometry.Pos; import javafx.scene.control.*; diff --git a/src/main/java/ninja/javafx/smartcsv/fx/table/EditableValidationCell.java b/src/main/java/ninja/javafx/smartcsv/fx/table/EditableValidationCell.java index 98453b0..c4054cf 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/table/EditableValidationCell.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/table/EditableValidationCell.java @@ -33,7 +33,6 @@ import javafx.scene.control.Tooltip; import javafx.scene.input.KeyCode; import ninja.javafx.smartcsv.fx.table.model.CSVRow; import ninja.javafx.smartcsv.fx.table.model.CSVValue; -import ninja.javafx.smartcsv.fx.util.ColorConstants; import java.util.ResourceBundle; diff --git a/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVModel.java b/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVModel.java index 7356d83..8dce7da 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVModel.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVModel.java @@ -26,38 +26,32 @@ package ninja.javafx.smartcsv.fx.table.model; -import javafx.beans.property.ObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.concurrent.Service; -import javafx.concurrent.Task; +import ninja.javafx.smartcsv.validation.RevalidationService; import ninja.javafx.smartcsv.validation.ValidationConfiguration; import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.Validator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - /** * The CSVModel is the client representation for the csv filepath. * It holds the data in rows, stores the header and manages the validator. */ -public class CSVModel { +public final class CSVModel { private static final Logger logger = LogManager.getLogger(CSVModel.class); private Validator validator; private ObservableList rows = FXCollections.observableArrayList(); private String[] header; - private ObservableList validationError = FXCollections.observableArrayList(); + private ObservableList validationError = FXCollections.observableArrayList(); private RevalidationService revalidationService = new RevalidationService(); /** * sets the validator configuration for the data revalidates + * * @param validationConfiguration the validator configuration for this data */ public void setValidationConfiguration(ValidationConfiguration validationConfiguration) { @@ -67,6 +61,7 @@ public class CSVModel { /** * returns the data as a list of rows of the + * * @return list of rows */ public ObservableList getRows() { @@ -79,18 +74,30 @@ public class CSVModel { /** * adds a new and empty row + * * @return the new row */ public CSVRow addRow() { CSVRow row = new CSVRow(); - row.setValidator(validator); row.setRowNumber(rows.size()); rows.add(row); return row; } + public void addValue(final CSVRow row, final String column, final String value) { + final CSVValue csvValue = row.addValue(column, value); + csvValue.valueProperty().addListener(observable -> { + if (validator.needsColumnValidation(column)) { + revalidate(); + } else { + csvValue.setValidationError(validator.isValid(row.getRowNumber(), column, csvValue.getValue())); + } + }); + } + /** * sets the column headers as string array + * * @param header the headers of the columns */ public void setHeader(String[] header) { @@ -100,6 +107,7 @@ public class CSVModel { /** * returns the column headers + * * @return the column headers */ public String[] getHeader() { @@ -107,6 +115,12 @@ public class CSVModel { } + public void revalidate(String column) { + if (!hasValidator()) return; + validator.reinitializeColumn(column); + revalidate(); + } + /** * walks through the data and validates each value */ @@ -116,8 +130,6 @@ public class CSVModel { logger.info("revalidate: hasValidator -> {}", hasValidator()); if (!hasValidator()) return; - - validator.clearScriptCache(); revalidationService.setHeader(header); revalidationService.setRows(rows); revalidationService.setValidator(validator); @@ -138,72 +150,6 @@ public class CSVModel { return newValidationConfiguration; } - private static class RevalidationService extends Service> { - private Validator validator; - private List rows; - private String[] header; - - public void setValidator(Validator validator) { - this.validator = validator; - } - - public void setRows(List rows) { - this.rows = rows; - } - - public void setHeader(String[] header) { - this.header = header; - } - - @Override - protected Task> createTask() { - return new Task>() { - @Override - protected List call() throws Exception { - List errors = new ArrayList<>(); - try { - if (header != null) { - ValidationError headerError = validator.isHeaderValid(header); - if (headerError != null) { - logger.info("revalidate: header error found"); - errors.add(headerError); - } - } - - int maxRows = rows.size(); - for (int lineNumber = 0; lineNumber < maxRows; lineNumber++) { - CSVRow row = rows.get(lineNumber); - row.setValidator(validator); - - Map> table = row.getColumns(); - Set columns = table.keySet(); - - for (String column : columns) { - CSVValue value = table.get(column).getValue(); - value.setValidator(validator); - if (validator != null) { - ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber); - if (validationError != null) { - logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber); - errors.add(validationError); - value.setValidationError(validationError); - } else { - value.setValidationError(null); - } - } else { - value.setValidationError(null); - } - } - } - - } catch (Throwable t) { - logger.error("validation error", t); - } - return errors; - } - }; - } - } } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVRow.java b/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVRow.java index 7f144bd..fcd0429 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVRow.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVRow.java @@ -30,24 +30,14 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableMap; -import ninja.javafx.smartcsv.validation.Validator; /** * This class represents a single row in the csv file. */ public class CSVRow { - private Validator validator; private ObservableMap> columns = FXCollections.observableHashMap(); private int rowNumber; - /** - * single row - * @param validator the reference to the validator - */ - public void setValidator(Validator validator) { - this.validator = validator; - } - /** * sets the row number * @param rowNumber @@ -78,13 +68,11 @@ public class CSVRow { * @param column column name * @param value the value to store */ - public void addValue(String column, String value) { + CSVValue addValue(String column, String value) { CSVValue v = new CSVValue(); - v.setValidator(validator); - v.setColumn(column); - v.setRowNumber(rowNumber); v.setValue(value); columns.put(column, new SimpleObjectProperty<>(v)); + return v; } } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVValue.java b/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVValue.java index 3a573b3..7903655 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVValue.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/table/model/CSVValue.java @@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.fx.table.model; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import ninja.javafx.smartcsv.validation.ValidationError; -import ninja.javafx.smartcsv.validation.Validator; /** * The csv value represents the value of a single cell. @@ -37,36 +36,9 @@ import ninja.javafx.smartcsv.validation.Validator; * and if the value is valid based on the validator. */ public class CSVValue { - private Validator validator; - private int rowNumber; - private String column; private StringProperty value = new SimpleStringProperty(); private ValidationError valid; - /** - * single value of a cell - * @param validator the reference to the validator - */ - public void setValidator(Validator validator) { - this.validator = validator; - } - - /** - * the row number this value is stored in - * @param row row number - */ - public void setRowNumber(int row) { - this.rowNumber = row; - } - - /** - * the column this value is stored in - * @param column header name of the column - */ - public void setColumn(String column) { - this.column = column; - } - /** * returns the real value * @return the real value @@ -88,9 +60,6 @@ public class CSVValue { * @param value the real value */ public void setValue(String value) { - if (validator != null) { - valid = validator.isValid(column, value, rowNumber); - } this.value.set(value); } @@ -106,7 +75,7 @@ public class CSVValue { * sets the state if a value is valid or not * @param valid the validation state */ - protected void setValidationError(ValidationError valid) { + public void setValidationError(ValidationError valid) { this.valid = valid; } } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/util/I18nValidationUtil.java b/src/main/java/ninja/javafx/smartcsv/fx/util/I18nValidationUtil.java index 071a54e..a518b7d 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/util/I18nValidationUtil.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/util/I18nValidationUtil.java @@ -62,7 +62,7 @@ public class I18nValidationUtil { if (resourceBundle.containsKey(validationMessage.getKey())) { String resourceText = resourceBundle.getString(validationMessage.getKey()); if (validationMessage.getParameters().length > 0) { - message.append(format(resourceText, validationMessage.getParameters())).append("\n"); + message.append(format(resourceText, (Object[]) validationMessage.getParameters())).append("\n"); } else { message.append(resourceText).append("\n"); } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/util/LoadFileService.java b/src/main/java/ninja/javafx/smartcsv/fx/util/LoadFileService.java index 3aa3335..49606f0 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/util/LoadFileService.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/util/LoadFileService.java @@ -28,11 +28,8 @@ package ninja.javafx.smartcsv.fx.util; import javafx.concurrent.Service; import javafx.concurrent.Task; -import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.files.FileStorage; -import java.io.File; - /** * Service class for async load of a csv file */ diff --git a/src/main/java/ninja/javafx/smartcsv/fx/util/SaveFileService.java b/src/main/java/ninja/javafx/smartcsv/fx/util/SaveFileService.java index 86c6295..03c943b 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/util/SaveFileService.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/util/SaveFileService.java @@ -28,14 +28,8 @@ package ninja.javafx.smartcsv.fx.util; import javafx.concurrent.Service; import javafx.concurrent.Task; -import ninja.javafx.smartcsv.FileWriter; -import ninja.javafx.smartcsv.csv.CSVFileWriter; import ninja.javafx.smartcsv.files.FileStorage; -import java.io.File; - -import static javafx.application.Platform.runLater; - /** * Service class for async load of a csv file */ diff --git a/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java b/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java index ac6615e..dd20e9a 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java @@ -274,6 +274,8 @@ public class ValidationEditorController extends FXMLController { } else { validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), null); } + + } private void updateForm() { diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java index 5a9c920..f6258f6 100644 --- a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileReader.java @@ -28,7 +28,6 @@ package ninja.javafx.smartcsv.preferences; import com.google.gson.GsonBuilder; import ninja.javafx.smartcsv.FileReader; -import org.springframework.stereotype.Service; import org.supercsv.prefs.CsvPreference; import org.supercsv.quote.AlwaysQuoteMode; diff --git a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java index 9b70649..76fe6e9 100644 --- a/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java +++ b/src/main/java/ninja/javafx/smartcsv/preferences/PreferencesFileWriter.java @@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.preferences; 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; import java.io.File; diff --git a/src/main/java/ninja/javafx/smartcsv/validation/AlphaNumericValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/AlphaNumericValidation.java new file mode 100644 index 0000000..c8cc094 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/AlphaNumericValidation.java @@ -0,0 +1,45 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.matchRegexp; + +/** + * Checks if the value is alpha numeric + */ +public class AlphaNumericValidation implements Validation { + @Override + public void check(int row, String value, ValidationError error) { + if (!matchRegexp(value, "[0-9a-zA-Z]*")) { + error.add("validation.message.alphanumeric"); + } + } + + @Override + public Type getType() { + return Type.ALPHANUMERIC; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/DateValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/DateValidation.java new file mode 100644 index 0000000..65db299 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/DateValidation.java @@ -0,0 +1,53 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.isDate; + +/** + * Checks if the date has the right format + */ +public class DateValidation implements Validation { + + private String dateformat; + + public DateValidation(String dateformat) { + assert dateformat != null && !dateformat.trim().isEmpty() : "empty date format for date validation"; + this.dateformat = dateformat; + } + + @Override + public void check(int row, String value, ValidationError error) { + if (!isDate(value, dateformat, true)) { + error.add("validation.message.date.format", dateformat); + } + } + + @Override + public Type getType() { + return Type.DATE; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/DoubleValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/DoubleValidation.java new file mode 100644 index 0000000..8224e3d --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/DoubleValidation.java @@ -0,0 +1,46 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.isDouble; + +/** + * Checks if the value is a double + */ +public class DoubleValidation implements Validation { + + @Override + public void check(int row, String value, ValidationError error) { + if (!isDouble(value)) { + error.add("validation.message.double"); + } + } + + @Override + public Type getType() { + return Type.DOUBLE; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/GroovyValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/GroovyValidation.java new file mode 100644 index 0000000..3d74bd8 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/GroovyValidation.java @@ -0,0 +1,78 @@ +/* + 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 groovy.lang.Binding; +import groovy.lang.GroovyShell; +import groovy.lang.Script; +import org.codehaus.groovy.control.CompilationFailedException; + +/** + * Executes the given groovy as check + */ +public class GroovyValidation implements Validation { + + private String groovyScript; + private GroovyShell shell = new GroovyShell(); + private Script script; + + public GroovyValidation(String groovyScript) { + this.groovyScript = groovyScript; + script = shell.parse(groovyScript); + } + + + @Override + public void check(int row, String value, ValidationError error) { + Binding binding = new Binding(); + binding.setVariable("value", value); + script.setBinding(binding); + + Object groovyResult = null; + try { + groovyResult = script.run(); + } catch (CompilationFailedException e) { + error.add("validation.message.groovy.exception", groovyScript, e.getMessage()); + e.printStackTrace(); + } + if (groovyResult == null) { + error.add("validation.message.groovy.return.null", groovyScript); + } + + if (!isScriptResultTrue(groovyResult)) { + error.add(groovyResult.toString()); + } + } + + @Override + public Type getType() { + return Type.GROOVY; + } + + private boolean isScriptResultTrue(Object groovyResult) { + return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true"); + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/IntegerValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/IntegerValidation.java new file mode 100644 index 0000000..198bf36 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/IntegerValidation.java @@ -0,0 +1,46 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.isInt; + +/** + * Checks if the value is an integer + */ +public class IntegerValidation implements Validation { + + @Override + public void check(int row, String value, ValidationError error) { + if (!isInt(value)) { + error.add("validation.message.integer"); + } + } + + @Override + public Type getType() { + return Type.INTEGER; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/MaxLengthValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/MaxLengthValidation.java new file mode 100644 index 0000000..add6740 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/MaxLengthValidation.java @@ -0,0 +1,52 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.maxLength; + +/** + * Checks if the value is shorter or exactly as long as the given max length + */ +public class MaxLengthValidation implements Validation { + + private int maxLength; + + public MaxLengthValidation(int maxLength) { + this.maxLength = maxLength; + } + + @Override + public void check(int row, String value, ValidationError error) { + if (!maxLength(value, maxLength)) { + error.add("validation.message.max.length", Integer.toString(maxLength)); + } + } + + @Override + public Type getType() { + return Type.MAX_LENGTH; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/MinLengthValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/MinLengthValidation.java new file mode 100644 index 0000000..7a2080c --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/MinLengthValidation.java @@ -0,0 +1,52 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.minLength; + +/** + * Checks if the value is at minimum long as the given min length + */ +public class MinLengthValidation implements Validation { + + private int minLength; + + public MinLengthValidation(int minLength) { + this.minLength = minLength; + } + + @Override + public void check(int row, String value, ValidationError error) { + if (!minLength(value, minLength)) { + error.add("validation.message.min.length", Integer.toString(minLength)); + } + } + + @Override + public Type getType() { + return Type.MIN_LENGTH; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/NotEmptyValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/NotEmptyValidation.java new file mode 100644 index 0000000..12deaba --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/NotEmptyValidation.java @@ -0,0 +1,46 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.isBlankOrNull; + +/** + * Checks if the value is not empty + */ +public class NotEmptyValidation implements Validation { + + @Override + public void check(int row, String value, ValidationError error) { + if (isBlankOrNull(value)) { + error.add("validation.message.not.empty"); + } + } + + @Override + public Type getType() { + return Type.NOT_EMPTY; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/RegExpValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/RegExpValidation.java new file mode 100644 index 0000000..0f6f6be --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/RegExpValidation.java @@ -0,0 +1,52 @@ +/* + 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 static org.apache.commons.validator.GenericValidator.matchRegexp; + +/** + * Checks the value against the given reg exp + */ +public class RegExpValidation implements Validation { + + private String regexp; + + public RegExpValidation(String regexp) { + this.regexp = regexp; + } + + @Override + public void check(int row, String value, ValidationError error) { + if (!matchRegexp(value, regexp)) { + error.add("validation.message.regexp", regexp); + } + } + + @Override + public Type getType() { + return Type.REGEXP; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/RevalidationService.java b/src/main/java/ninja/javafx/smartcsv/validation/RevalidationService.java new file mode 100644 index 0000000..9a36af2 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/RevalidationService.java @@ -0,0 +1,110 @@ +/* + 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 javafx.beans.property.ObjectProperty; +import javafx.concurrent.Service; +import javafx.concurrent.Task; +import ninja.javafx.smartcsv.fx.table.model.CSVRow; +import ninja.javafx.smartcsv.fx.table.model.CSVValue; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Service for running the validation async of the ui thread + */ +public class RevalidationService extends Service> { + + private static final Logger logger = LogManager.getLogger(RevalidationService.class); + + private Validator validator; + private List rows; + private String[] header; + + public void setValidator(Validator validator) { + this.validator = validator; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public void setHeader(String[] header) { + this.header = header; + } + + @Override + protected Task> createTask() { + return new Task>() { + @Override + protected List call() throws Exception { + List errors = new ArrayList<>(); + try { + if (header != null) { + ValidationError headerError = validator.isHeaderValid(header); + if (headerError != null) { + logger.info("revalidate: header error found"); + errors.add(headerError); + } + } + + int maxRows = rows.size(); + for (int lineNumber = 0; lineNumber < maxRows; lineNumber++) { + CSVRow row = rows.get(lineNumber); + + Map> table = row.getColumns(); + Set columns = table.keySet(); + + for (String column : columns) { + CSVValue value = table.get(column).getValue(); + if (validator != null) { + ValidationError validationError = validator.isValid(lineNumber, column, value.getValue()); + if (validationError != null) { + logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber); + errors.add(validationError); + value.setValidationError(validationError); + } else { + value.setValidationError(null); + } + } else { + value.setValidationError(null); + } + } + } + + } catch (Throwable t) { + logger.error("validation error", t); + } + return errors; + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/ninja/javafx/smartcsv/validation/UniqueValidation.java b/src/main/java/ninja/javafx/smartcsv/validation/UniqueValidation.java new file mode 100644 index 0000000..4b769c0 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/UniqueValidation.java @@ -0,0 +1,54 @@ +/* + 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 java.util.HashMap; + +/** + * Checks if the value is unique in the column + */ +public class UniqueValidation implements Validation { + + private HashMap columnValueMap = new HashMap<>(); + + @Override + public void check(int row, String value, ValidationError error) { + Integer valueInLineNumber = columnValueMap.get(value); + if (valueInLineNumber != null) { + if (!valueInLineNumber.equals(row)) { + valueInLineNumber += 1; // show not 0 based line numbers to user + error.add("validation.message.uniqueness", value, valueInLineNumber.toString()); + } + } else { + columnValueMap.put(value, row); + } + } + + @Override + public Type getType() { + return Type.UNIQUE; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/Validation.java b/src/main/java/ninja/javafx/smartcsv/validation/Validation.java new file mode 100644 index 0000000..27c4b76 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/Validation.java @@ -0,0 +1,36 @@ +/* + 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; + +/** + * Interface for all validations + */ +public interface Validation { + + enum Type { NOT_EMPTY, UNIQUE, DOUBLE, INTEGER, MIN_LENGTH, MAX_LENGTH, DATE, ALPHANUMERIC, REGEXP, VALUE_OF, GROOVY } + void check(int row, String value, ValidationError error); + Type getType(); +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java index 6d4ede7..45e8a60 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java @@ -28,7 +28,6 @@ package ninja.javafx.smartcsv.validation; import com.google.gson.GsonBuilder; import ninja.javafx.smartcsv.FileReader; -import org.springframework.stereotype.Service; import java.io.File; import java.io.IOException; diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java index 8fe2a49..328fcb9 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java @@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.validation; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import ninja.javafx.smartcsv.FileWriter; -import org.springframework.stereotype.Service; import java.io.File; import java.io.IOException; diff --git a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java index 0c4c820..b7de5a4 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java @@ -26,18 +26,10 @@ 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; import java.util.List; import java.util.Map; -import static java.util.stream.Collectors.joining; -import static org.apache.commons.validator.GenericValidator.*; - /** * This class checks all the validations defined in the * Config against a given value @@ -49,9 +41,7 @@ public class Validator { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private ValidationConfiguration validationConfig; - private GroovyShell shell = new GroovyShell(); - private Map scriptCache = new HashMap<>(); - private Map> uniquenessLookupTable = new HashMap<>(); + private Map> columnValidationMap = new HashMap<>(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // constructors @@ -59,10 +49,12 @@ public class Validator { /** * JSON configuration for this validator + * * @param validationConfig */ public Validator(ValidationConfiguration validationConfig) { - this.validationConfig = validationConfig; + this.validationConfig = validationConfig; + initColumnValidations(); } @@ -70,31 +62,40 @@ public class Validator { // public methods //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + public boolean needsColumnValidation(String column) { + Map validationMap = columnValidationMap.get(column); + if (validationMap != null) { + return validationMap.containsKey(Validation.Type.UNIQUE); + } + return false; + + } + + /** * checks if the value is valid for the column configuration + * * @param column the column name - * @param value the value to check + * @param value the value to check * @return ValidationError with information if valid and if not which getMessage happened */ - public ValidationError isValid(String column, String value, Integer lineNumber) { + public ValidationError isValid(Integer row, String column, String value) { ValidationError result = null; if (hasConfig()) { + ValidationError error = ValidationError.withLineNumber(row); + Map validationMap = columnValidationMap.get(column); + if (validationMap != null) { + for (Validation validation: validationMap.values()) { - 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); - checkUniqueness(column, value, lineNumber, error); + if (validation.getType() == Validation.Type.NOT_EMPTY) { + validation.check(row, value, error); + } else { + if (value != null && !value.isEmpty()) { + validation.check(row, value, error); + } + } + } } - if (!error.isEmpty()) { result = error; } @@ -102,156 +103,102 @@ public class Validator { return result; } + public boolean hasConfig() { return validationConfig != null; } + public void reinitializeColumn(String column) { + clear(column); + initializeColumnWithRules(column); + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // private methods //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private void checkUniqueness(String column, String value, Integer lineNumber, ValidationError error) { - Boolean uniqueRule = validationConfig.getUniqueRuleFor(column); - if (uniqueRule != null && uniqueRule) { - HashMap 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 void add(String column, Validation validation) { + Map 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 validationMap = columnValidationMap.get(column); + if (validationMap != null) { + validationMap.clear(); + } + } + + private void initColumnValidations() { + if (hasConfig()) { + String[] columns = validationConfig.headerNames(); + for (String column : columns) { + initializeColumnWithRules(column); } } } - private HashMap getColumnValueMap(String column, HashMap valueLineNumber) { - if (valueLineNumber == null) { - valueLineNumber = new HashMap<>(); - uniquenessLookupTable.put(column, valueLineNumber); + private void initializeColumnWithRules(String column) { + Boolean alphaNumeric = validationConfig.getAlphanumericRuleFor(column); + if (alphaNumeric != null && alphaNumeric) { + add(column, new AlphaNumericValidation()); } - return valueLineNumber; - } - private void checkGroovy(String column, String value, ValidationError error) { - String groovyScript = validationConfig.getGroovyRuleFor(column); - 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) { - error.add("validation.message.groovy.exception", groovyScript, e.getMessage()); - e.printStackTrace(); - } - if (groovyResult == null) { - error.add("validation.message.groovy.return.null", groovyScript); - } - - if (!isScriptResultTrue(groovyResult)) { - error.add(groovyResult.toString()); - } - - } - } - - private boolean isScriptResultTrue(Object groovyResult) { - return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true"); - } - - private void checkValueOf(String column, String value, ValidationError error) { - List values = validationConfig.getValueOfRuleFor(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(String column, String value, ValidationError error) { - Boolean notEmptyRule = validationConfig.getNotEmptyRuleFor(column); - if (notEmptyRule != null && notEmptyRule) { - if (isBlankOrNull(value)) { - error.add("validation.message.not.empty"); - } - } - } - - private void checkInteger(String column, String value, ValidationError error) { - Boolean integerRule = validationConfig.getIntegerRuleFor(column); - if (integerRule != null && integerRule) { - if (!isInt(value)) { - error.add("validation.message.integer"); - } - } - } - - private void checkDouble(String column, String value, ValidationError error) { Boolean doubleRule = validationConfig.getDoubleRuleFor(column); if (doubleRule != null && doubleRule) { - if (!isDouble(value)) { - error.add("validation.message.double"); - } + add(column, new DoubleValidation()); + } + + Boolean integerRule = validationConfig.getIntegerRuleFor(column); + if (integerRule != null && integerRule) { + add(column, new IntegerValidation()); + } + + Boolean notEmptyRule = validationConfig.getNotEmptyRuleFor(column); + if (notEmptyRule != null && notEmptyRule) { + add(column, new NotEmptyValidation()); + } + + Boolean uniqueRule = validationConfig.getUniqueRuleFor(column); + if (uniqueRule != null && uniqueRule) { + add(column, new UniqueValidation()); + } + + String dateRule = validationConfig.getDateRuleFor(column); + if (dateRule != null && !dateRule.trim().isEmpty()) { + add(column, new DateValidation(dateRule)); } - } - private void checkMinLength(String column, String value, ValidationError error) { Integer minLength = validationConfig.getMinLengthRuleFor(column); if (minLength != null) { - if (!minLength(value, minLength)) { - error.add("validation.message.min.length", minLength.toString()); - } + add(column, new MinLengthValidation(minLength)); } - } - private void checkMaxLength(String column, String value, ValidationError error) { Integer maxLength = validationConfig.getMaxLengthRuleFor(column); if (maxLength != null) { - if (!maxLength(value, maxLength)) { - error.add("validation.message.max.length", maxLength.toString()); - } + add(column, new MaxLengthValidation(maxLength)); } - } - private void checkDate(String column, String value, ValidationError error) { - String dateformat = validationConfig.getDateRuleFor(column); - if (dateformat != null && !dateformat.trim().isEmpty()) { - if (!isDate(value, dateformat, true)) { - error.add("validation.message.date.format", dateformat); - } - } - } - - private void checkAlphaNumeric(String column, String value, ValidationError error) { - Boolean alphaNumericRule = validationConfig.getAlphanumericRuleFor(column); - if (alphaNumericRule != null && alphaNumericRule) { - if (!matchRegexp(value, "[0-9a-zA-Z]*")) { - error.add("validation.message.alphanumeric"); - } - } - } - - private void checkRegularExpression(String column, String value, ValidationError error) { String regexp = validationConfig.getRegexpRuleFor(column); if (regexp != null && !regexp.trim().isEmpty()) { - if (!matchRegexp(value, regexp)) { - error.add("validation.message.regexp", regexp); - } + add(column, new RegExpValidation(regexp)); + } + + String groovy = validationConfig.getGroovyRuleFor(column); + if (groovy != null && !groovy.trim().isEmpty()) { + add(column, new GroovyValidation(groovy)); + } + List valueOfRule = validationConfig.getValueOfRuleFor(column); + if (valueOfRule != null && !valueOfRule.isEmpty()) { + add(column, new ValueOfValidation(valueOfRule)); } } + public ValidationError isHeaderValid(String[] headerNames) { ValidationError result = null; if (validationConfig != null) { @@ -266,7 +213,7 @@ public class Validator { ValidationError error = ValidationError.withoutLineNumber(); - for(int i=0; i + + 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 java.util.List; + +import static java.util.stream.Collectors.joining; + +/** + * Checks if the value is part of a list of values + */ +public class ValueOfValidation implements Validation { + + private List values; + + public ValueOfValidation(List values) { + this.values = values; + } + + @Override + public void check(int row, String value, ValidationError error) { + if (!values.contains(value)) { + String commaSeparated = values.stream().collect(joining(", ")); + error.add("validation.message.value.of", value, commaSeparated); + } + } + + @Override + public Type getType() { + return Type.VALUE_OF; + } +} diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/about/about.fxml b/src/main/resources/ninja/javafx/smartcsv/fx/about/about.fxml index 20ed5f5..55b5cab 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/about/about.fxml +++ b/src/main/resources/ninja/javafx/smartcsv/fx/about/about.fxml @@ -1,16 +1,9 @@ - - - - - - - - - + + + -