diff --git a/build.gradle b/build.gradle index e251185..faf05e4 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,7 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' + testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3' testCompile group: 'org.mockito', name: 'mockito-all', version: '1.10.19' compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.5' compile group: 'org.springframework', name:'spring-context', version: '4.2.3.RELEASE' diff --git a/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java b/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java index 94992d8..53129e4 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java @@ -32,27 +32,26 @@ import javafx.concurrent.Task; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; -import javafx.scene.control.Alert; -import javafx.scene.control.Label; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableView; +import javafx.scene.control.*; +import javafx.scene.layout.AnchorPane; import javafx.scene.layout.BorderPane; import javafx.stage.FileChooser; import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.csv.CSVFileReader; import ninja.javafx.smartcsv.csv.CSVFileWriter; +import ninja.javafx.smartcsv.fx.list.ValidationErrorListCell; import ninja.javafx.smartcsv.fx.table.ObservableMapValueFactory; import ninja.javafx.smartcsv.fx.table.ValidationCellFactory; import ninja.javafx.smartcsv.fx.table.model.CSVModel; -import ninja.javafx.smartcsv.fx.table.model.CSVValue; import ninja.javafx.smartcsv.fx.table.model.CSVRow; +import ninja.javafx.smartcsv.fx.table.model.CSVValue; +import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationFileReader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.File; -import java.io.IOException; import java.net.URL; import java.util.ResourceBundle; @@ -83,15 +82,22 @@ public class SmartCSVController extends FXMLController { @FXML private Label stateline; + @FXML + private ListView errorList; + + @FXML + private AnchorPane tableWrapper; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // injections + // members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private ValidationCellFactory cellFactory = new ValidationCellFactory(); + private ValidationCellFactory cellFactory; private final LoadCSVService loadCSVService = new LoadCSVService(); private final SaveCSVService saveCSVService = new SaveCSVService(); private CSVModel model; + private TableView tableView; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -99,8 +105,13 @@ public class SmartCSVController extends FXMLController { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Override - public void initialize(URL location, ResourceBundle resources) { + public void initialize(URL location, ResourceBundle resourceBundle) { + cellFactory = new ValidationCellFactory(resourceBundle); stateline.setVisible(false); + errorList.setCellFactory(param -> new ValidationErrorListCell(resourceBundle)); + errorList.getSelectionModel().selectedItemProperty().addListener( + observable -> scrollToError() + ); } @@ -215,7 +226,7 @@ public class SmartCSVController extends FXMLController { model = csvLoader.getData(); model.setValidator(validationLoader.getValidator()); - TableView tableView = new TableView<>(); + tableView = new TableView<>(); for (String column: model.getHeader()) { addColumn(column, tableView); @@ -223,7 +234,14 @@ public class SmartCSVController extends FXMLController { tableView.getItems().setAll(model.getRows()); tableView.setEditable(true); - applicationPane.setCenter(tableView); + AnchorPane.setBottomAnchor(tableView, 0.0); + AnchorPane.setTopAnchor(tableView, 0.0); + AnchorPane.setLeftAnchor(tableView, 0.0); + AnchorPane.setRightAnchor(tableView, 0.0); + tableWrapper.getChildren().setAll(tableView); + + + errorList.setItems(model.getValidationError()); } /** @@ -248,6 +266,17 @@ public class SmartCSVController extends FXMLController { tableView.getColumns().add(column); } + private void scrollToError() { + ValidationError entry = (ValidationError)errorList.getSelectionModel().getSelectedItem(); + if (entry != null) { + if (entry.getLineNumber() != null) { + tableView.scrollTo(entry.getLineNumber()); + tableView.getSelectionModel().select(entry.getLineNumber()); + } else { + tableView.scrollTo(0); + } + } + } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // inner class @@ -277,7 +306,7 @@ public class SmartCSVController extends FXMLController { try { fileReader.read(file); runLater(SmartCSVController.this::resetContent); - } catch (IOException ex) { + } catch (Throwable ex) { ex.printStackTrace(); } } @@ -300,7 +329,7 @@ public class SmartCSVController extends FXMLController { try { csvFileWriter.saveFile(model); runLater(SmartCSVController.this::resetContent); - } catch (IOException ex) { + } catch (Throwable ex) { ex.printStackTrace(); } return null; diff --git a/src/main/java/ninja/javafx/smartcsv/fx/list/ValidationErrorListCell.java b/src/main/java/ninja/javafx/smartcsv/fx/list/ValidationErrorListCell.java new file mode 100644 index 0000000..9865cf9 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/fx/list/ValidationErrorListCell.java @@ -0,0 +1,70 @@ +/* + 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.fx.list; + +import javafx.scene.control.ListCell; +import javafx.scene.text.Text; +import ninja.javafx.smartcsv.validation.ValidationError; + +import java.util.ResourceBundle; + +import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage; + +/** + * TODO: DESCRIPTION!!! + */ +public class ValidationErrorListCell extends ListCell { + + private ResourceBundle resourceBundle; + + public ValidationErrorListCell(ResourceBundle resourceBundle) { + this.resourceBundle = resourceBundle; + } + + @Override + public void updateItem(ValidationError validationError, boolean empty) { + super.updateItem(validationError, empty); + if (empty) { + clearContent(); + } else { + addContent(validationError); + } + } + + + private void clearContent() { + setText(null); + setGraphic(null); + } + + private void addContent(ValidationError validationError) { + setText(null); + Text text = new Text(getI18nValidatioMessage(resourceBundle, validationError)); + text.setWrappingWidth(180); + setGraphic(text); + } +} 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 9576417..c80e861 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/table/EditableValidationCell.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/table/EditableValidationCell.java @@ -34,7 +34,10 @@ import javafx.scene.input.KeyCode; import ninja.javafx.smartcsv.fx.table.model.CSVRow; import ninja.javafx.smartcsv.fx.table.model.CSVValue; +import java.util.ResourceBundle; + import static javafx.application.Platform.runLater; +import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage; /** * Created by Andreas on 27.11.2015. @@ -42,6 +45,11 @@ import static javafx.application.Platform.runLater; public class EditableValidationCell extends TableCell { private ValueTextField textField; + private ResourceBundle resourceBundle; + + public EditableValidationCell(ResourceBundle resourceBundle) { + this.resourceBundle = resourceBundle; + } @Override public void startEdit() { @@ -64,12 +72,12 @@ public class EditableValidationCell extends TableCell { protected void updateItem(CSVValue item, boolean empty) { super.updateItem(item, empty); - if (item == null || item.getValid().isValid() || isEditing()) { + if (item == null || item.getValidationError() == null || isEditing()) { setStyle(""); setTooltip(null); - } else if (!item.getValid().isValid()) { + } else if (item.getValidationError() != null) { setStyle("-fx-background-color: #ff8888"); - setTooltip(new Tooltip(item.getValid().error())); + setTooltip(new Tooltip(getI18nValidatioMessage(resourceBundle, item.getValidationError()))); } if (item == null || empty) { diff --git a/src/main/java/ninja/javafx/smartcsv/fx/table/ValidationCellFactory.java b/src/main/java/ninja/javafx/smartcsv/fx/table/ValidationCellFactory.java index 3e77d69..457ca60 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/table/ValidationCellFactory.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/table/ValidationCellFactory.java @@ -29,17 +29,24 @@ package ninja.javafx.smartcsv.fx.table; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.util.Callback; -import ninja.javafx.smartcsv.fx.table.model.CSVModel; import ninja.javafx.smartcsv.fx.table.model.CSVRow; import ninja.javafx.smartcsv.fx.table.model.CSVValue; +import java.util.ResourceBundle; + /** * Created by Andreas on 18.11.2015. */ public class ValidationCellFactory implements Callback, TableCell> { + private ResourceBundle resourceBundle; + + public ValidationCellFactory(ResourceBundle resourceBundle) { + this.resourceBundle = resourceBundle; + } + @Override public TableCell call(TableColumn param) { - return new EditableValidationCell(); + return new EditableValidationCell(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 7a2f31e..de2bc28 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 @@ -28,7 +28,7 @@ package ninja.javafx.smartcsv.fx.table.model; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import ninja.javafx.smartcsv.validation.ValidationState; +import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.Validator; /** @@ -41,6 +41,7 @@ public class CSVModel { private ObservableList rows = FXCollections.observableArrayList(); private String[] header; private String filepath; + private ObservableList validationError = FXCollections.observableArrayList(); public CSVModel(String filepath) { this.filepath = filepath; @@ -71,6 +72,10 @@ public class CSVModel { return rows; } + public ObservableList getValidationError() { + return validationError; + } + /** * adds a new and empty row * @return the new row @@ -89,6 +94,7 @@ public class CSVModel { */ public void setHeader(String[] header) { this.header = header; + revalidate(); } /** @@ -104,18 +110,37 @@ public class CSVModel { * walks through the data and validates each value */ private void revalidate() { - for (CSVRow row: rows) { + validationError.clear(); + + if (header != null && validator != null) { + addValidationError(validator.isHeaderValid(header)); + } + + for (int lineNumber = 0; lineNumber < rows.size(); lineNumber++) { + CSVRow row = rows.get(lineNumber); row.setValidator(validator); for (String column: row.getColumns().keySet()) { CSVValue value = row.getColumns().get(column).getValue(); value.setValidator(validator); if (validator != null) { - value.setValid(validator.isValid(column, value.getValue())); + ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber); + if (validationError != null) { + addValidationError(validationError); + value.setValidationError(validationError); + } else { + value.setValidationError(null); + } } else { - value.setValid(new ValidationState()); + value.setValidationError(null); } } } } + private void addValidationError(ValidationError validationError) { + if (validationError != null) { + this.validationError.add(validationError); + } + } + } 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 dce22e3..3a573b3 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 @@ -28,7 +28,7 @@ package ninja.javafx.smartcsv.fx.table.model; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import ninja.javafx.smartcsv.validation.ValidationState; +import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.Validator; /** @@ -41,7 +41,7 @@ public class CSVValue { private int rowNumber; private String column; private StringProperty value = new SimpleStringProperty(); - private ValidationState valid = new ValidationState(); + private ValidationError valid; /** * single value of a cell @@ -89,7 +89,7 @@ public class CSVValue { */ public void setValue(String value) { if (validator != null) { - valid = validator.isValid(column, value); + valid = validator.isValid(column, value, rowNumber); } this.value.set(value); } @@ -98,7 +98,7 @@ public class CSVValue { * returns if the value is valid to the rules of the validator * @return */ - public ValidationState getValid() { + public ValidationError getValidationError() { return valid; } @@ -106,7 +106,7 @@ public class CSVValue { * sets the state if a value is valid or not * @param valid the validation state */ - protected void setValid(ValidationState valid) { + protected 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 new file mode 100644 index 0000000..1fdd15d --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/fx/util/I18nValidationUtil.java @@ -0,0 +1,63 @@ +/* + 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.fx.util; + +import ninja.javafx.smartcsv.validation.ValidationError; +import ninja.javafx.smartcsv.validation.ValidationMessage; + +import java.io.StringWriter; +import java.util.List; +import java.util.ResourceBundle; + +import static java.text.MessageFormat.format; + +/** + * This class makes validation messages readable in supported languages + */ +public class I18nValidationUtil { + + public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) { + + List validationMessages = error.getMessages(); + StringWriter message = new StringWriter(); + for (ValidationMessage validationMessage: validationMessages) { + if (resourceBundle.containsKey(validationMessage.getKey())) { + String resourceText = resourceBundle.getString(validationMessage.getKey()); + if (validationMessage.getParameters().length > 0) { + message.append(format(resourceText, validationMessage.getParameters())).append("\n"); + } else { + message.append(resourceText).append("\n"); + } + } else { + message.append(validationMessage.getKey()).append("\n"); + } + } + + return message.toString(); + } + +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationState.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationError.java similarity index 57% rename from src/main/java/ninja/javafx/smartcsv/validation/ValidationState.java rename to src/main/java/ninja/javafx/smartcsv/validation/ValidationError.java index b0423ea..32da30e 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/ValidationState.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationError.java @@ -26,26 +26,45 @@ package ninja.javafx.smartcsv.validation; -import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; /** - * Created by Andreas on 28.11.2015. + * This class holds all the error messages + * for a single cell and the information in + * which row the cell is */ -public class ValidationState { - private boolean valid = true; - private StringWriter messages = new StringWriter(); +public class ValidationError { - public void invalidate(String message) { - valid = false; - messages.append(message).append('\n'); + private List messages = new ArrayList<>(); + private Integer lineNumber; + + private ValidationError(Integer lineNumber) { + this.lineNumber = lineNumber; } - public boolean isValid() { - return valid; + public static ValidationError withLineNumber(int lineNumber) { + return new ValidationError(lineNumber); } - public String error() { - return messages.toString(); + public static ValidationError withoutLineNumber() { + return new ValidationError(-1); } + public Integer getLineNumber() { + return lineNumber; + } + + public List getMessages() { + return messages; + } + + public ValidationError add(String key, String... parameters) { + messages.add(new ValidationMessage(key, parameters)); + return this; + } + + public boolean isEmpty() { + return messages.isEmpty(); + } } diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationMessage.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationMessage.java new file mode 100644 index 0000000..fea0678 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationMessage.java @@ -0,0 +1,79 @@ +/* + 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.Arrays; + +/** + * TODO: DESCRIPTION!!! + */ +public class ValidationMessage { + + private String key; + private String[] parameters; + + public ValidationMessage(String key, String... parameters) { + this.key = key; + this.parameters = parameters; + } + + public String getKey() { + return key; + } + + public String[] getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ValidationMessage that = (ValidationMessage) o; + + if (key != null ? !key.equals(that.key) : that.key != null) return false; + // Probably incorrect - comparing Object[] arrays with Arrays.equals + return Arrays.equals(parameters, that.parameters); + + } + + @Override + public int hashCode() { + int result = key != null ? key.hashCode() : 0; + result = 31 * result + Arrays.hashCode(parameters); + return result; + } + + @Override + public String toString() { + return "ValidationMessage{" + + "key='" + key + '\'' + + ", parameters=" + Arrays.toString(parameters) + + '}'; + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java index 5b5614e..94dc53b 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java @@ -33,6 +33,7 @@ import groovy.lang.Script; import org.codehaus.groovy.control.CompilationFailedException; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.apache.commons.validator.GenericValidator.*; @@ -73,22 +74,31 @@ public class Validator { * checks if the value is valid for the column configuration * @param column the column name * @param value the value to check - * @return ValidationState with information if valid and if not which error happened + * @return ValidationError with information if valid and if not which getMessage happened */ - public ValidationState isValid(String column, String value) { - ValidationState result = new ValidationState(); + public ValidationError isValid(String column, String value, Integer lineNumber) { + ValidationError result = null; if (validationConfig != null) { - Config columnConfig = getColumnConfig(column); - if (columnConfig != null) { - checkBlankOrNull(columnConfig, value, result); - if (value != null) { - checkRegularExpression(columnConfig, value, result); - checkAlphaNumeric(columnConfig, value, result); - checkDate(columnConfig, value, result); - checkMaxLength(columnConfig, value, result); - checkMinLength(columnConfig, value, result); - checkInteger(columnConfig, value, result); - checkGroovy(column, columnConfig, value, result); + 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) { + 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); + } + + if (!error.isEmpty()) { + result = error; + } } } } @@ -100,7 +110,7 @@ public class Validator { // private methods //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private void checkGroovy(String column, Config columnConfig, String value, ValidationState result) { + private void checkGroovy(String column, Config columnConfig, String value, ValidationError error) { String groovyScript = getString(columnConfig, "groovy"); if (groovyScript != null) { @@ -118,15 +128,15 @@ public class Validator { try { groovyResult = script.run(); } catch (CompilationFailedException e) { - result.invalidate("groovy script '"+groovyScript+"' throws exception: "+e.getMessage()); + error.add("validation.message.groovy.exception", groovyScript, e.getMessage()); e.printStackTrace(); } if (groovyResult == null) { - result.invalidate("groovy script '"+groovyScript+"' returns null"); + error.add("validation.message.groovy.return.null", groovyScript); } if (!isScriptResultTrue(groovyResult)) { - result.invalidate(groovyResult.toString()); + error.add(groovyResult.toString()); } } @@ -136,70 +146,75 @@ public class Validator { return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true"); } - private void checkBlankOrNull(Config columnConfig, String value, ValidationState result) { + private void checkBlankOrNull(Config columnConfig, String value, ValidationError error) { if (getBoolean(columnConfig, "not empty")) { if (isBlankOrNull(value)) { - result.invalidate("should not be empty"); + error.add("validation.message.not.empty"); } } } - private void checkInteger(Config columnConfig, String value, ValidationState result) { + private void checkInteger(Config columnConfig, String value, ValidationError error) { if (getBoolean(columnConfig, "integer")) { if (!isInt(value)) { - result.invalidate("should be an integer"); + error.add("validation.message.integer"); } } } - private void checkMinLength(Config columnConfig, String value, ValidationState result) { + private void checkMinLength(Config columnConfig, String value, ValidationError error) { Integer minLength = getInteger(columnConfig, "minlength"); if (minLength != null) { if (!minLength(value, minLength)) { - result.invalidate("has not min length of " + minLength); + error.add("validation.message.min.length", minLength.toString()); } } } - private void checkMaxLength(Config columnConfig, String value, ValidationState result) { + private void checkMaxLength(Config columnConfig, String value, ValidationError error) { Integer maxLength = getInteger(columnConfig, "maxlength"); if (maxLength != null) { if (!maxLength(value, maxLength)) { - result.invalidate("has not max length of " + maxLength); + error.add("validation.message.max.length", maxLength.toString()); } } } - private void checkDate(Config columnConfig, String value, ValidationState result) { + private void checkDate(Config columnConfig, String value, ValidationError error) { String dateformat = getString(columnConfig, "date"); if (dateformat != null && !dateformat.trim().isEmpty()) { if (!isDate(value, dateformat, true)) { - result.invalidate("is not a date of format " + dateformat); + error.add("validation.message.date.format", dateformat); } } } - private void checkAlphaNumeric(Config columnConfig, String value, ValidationState result) { + private void checkAlphaNumeric(Config columnConfig, String value, ValidationError error) { if (getBoolean(columnConfig, "alphanumeric")) { if (!matchRegexp(value, "[0-9a-zA-Z]*")) { - result.invalidate("should not be alphanumeric"); + error.add("validation.message.alphanumeric"); } } } - private void checkRegularExpression(Config columnConfig, String value, ValidationState result) { + private void checkRegularExpression(Config columnConfig, String value, ValidationError error) { String regexp = getString(columnConfig, "regexp"); if (regexp != null && !regexp.trim().isEmpty()) { if (!matchRegexp(value, regexp)) { - result.invalidate("does not match " + regexp); + error.add("validation.message.regexp", regexp); } } } - private Config getColumnConfig(String column) { - return validationConfig.hasPath(column) ? validationConfig.getConfig(column) : null; + 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; } @@ -213,4 +228,39 @@ public class Validator { return columnConfig.hasPath(path) && columnConfig.getBoolean(path); } + public ValidationError isHeaderValid(String[] headerNames) { + ValidationError result = null; + if (validationConfig != null) { + if (validationConfig.hasPath("headers")) { + Config headerSectionConfig = validationConfig.getConfig("headers"); + if (headerSectionConfig.hasPath("list")) { + List headerConfig = headerSectionConfig.getStringList("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; + } + + ValidationError error = ValidationError.withoutLineNumber(); + + for(int i=0; i - + - - - - - - - + + + + + + + - + - - - - - - + @@ -39,10 +34,26 @@
- - - - + + + + + + + + + + + + + + + +
@@ -54,4 +65,6 @@ + + diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties new file mode 100644 index 0000000..475cd86 --- /dev/null +++ b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.properties @@ -0,0 +1,24 @@ +menu.open.csv = Open CSV File +menu.open.config = Open Validation Config +menu.save = Save +menu.save.as = Save As ... +menu.close = Close +menu.about = About +menu.file = File +menu.edit = Edit +menu.help = Help +title.validation.errors = Validation Errors: + +# validaton messages +validation.message.not.empty = should not be empty +validation.message.integer = should be an integer +validation.message.alphanumeric = should be alphanumeric +validation.message.groovy.exception = groovy script '{0}' throws exception: {1} +validation.message.groovy.return.null = groovy script '{0}' returns null +validation.message.min.length = has not min length of {0} +validation.message.max.length = has not max length of {0} +validation.message.date.format = is not a date of format {0} +validation.message.regexp = does not match {0} + +validation.message.header.length = number of headers is not correct! there are {0} but there should be {1} +validation.message.header.match = header number {0} does not match "{1}" should be "{3}" \ No newline at end of file diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties index abd2741..2ac332a 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties +++ b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_de.properties @@ -1,52 +1,32 @@ -menu.title.import.gpx = Importiere GPX -menu.title.file = Datei -menu.title.quit = Beenden -menu.title.help = Hilfe -menu.title.settings = Einstellungen -menu.title.about = \u00dcber GeoFroggerFX -menu.title.plugins = Plugins -menu.title.list = Listen -menu.title.list.new = Liste anlegen -menu.title.list.delete = Liste l\u00F6schen +# ae = u00e4 +# Ae = u00c4 +# oe = u00f6 +# Oe =u00d6 +# ue = u00fc +# Ue = u00dc +# ss = u00df -menu.title.sort = Sortieren -menu.title.filter = Filtern +menu.open.csv = CSV Datei \u00f6ffnen +menu.open.config = Pr\u00fcfkonfiguration \u00f6ffnen +menu.save = Speichern +menu.save.as = Speichern als ... +menu.close = Beenden +menu.about = \u00dcber ... +menu.file = Datei +menu.edit = Bearbeiten +menu.help = Hilfe +title.validation.errors = Fehler in der Datei: -label.text.cache.list=Liste: -label.text.cache.list.count=Anzahl: -label.text.name=Name: -label.text.difficulty=Schwierigkeit: -label.text.terrain=Gel\u00E4nde -label.text.placedBy=Platziert von: -label.text.owner=Betreut von: -label.text.date=Datum: -label.text.type=Typ: -label.text.container=Gr\u00F6\u00dfe: -label.text.shortdescription=Kurze Beschreibung: -label.text.htmldescription=HTML Beschreibung -label.text.longdescription=Lange Beschreibung: +# validaton messages +validation.message.not.empty = Darf nicht leer sein. +validation.message.integer = Muss eine Zahl sein. +validation.message.alphanumeric = Darf nur Zahlen und Buchstaben enthalten. +validation.message.groovy.exception = groovy script '{0}' wirft folgenden Fehler: {1} +validation.message.groovy.return.null = groovy script '{0}' meldet "null" +validation.message.min.length = Hat nicht die minimale L\u00e4nge von {0} +validation.message.max.length = Hat nicht die maximale L\u00e4nge von {0} +validation.message.date.format = Das Datumsformat entspricht nicht {0} +validation.message.regexp = entspricht nicht dem regul\u00e4ren Ausdruck {0} -tab.text.descriptions=Beschreibungen -tab.text.general=Allgemein - -sort.cache.name = GC Code -sort.cache.type = Art -sort.cache.difficulty = Schwierigkeitsgrad -sort.cache.terrain = Gel\u00E4nde -sort.cache.placedBy = Platziert von -sort.cache.owner = Betreut von - -dialog.title.about = Über -dialog.title.new_list = Neue Liste -dialog.label.listname = Name der Liste: -dialog.msg.list.does.exist = Diese Liste existiert schon! -dialog.title.delete_list = Liste löschen - -all.caches = Alle Caches - -status.load.all.caches.from.db = Lade alle Caches von der Datenbank. -status.all.cache.lists.loaded = Alle Listen geladen. -status.load.caches.from.db = Lade Caches von der Datenbank. -status.all.caches.loaded = Alle Caches geladen. -status.store.all.caches = Speichere Caches in Datenbank. -status.all.caches.stored = Alle Caches in der Datenbank gespeichert. \ No newline at end of file +validation.message.header.length = Anzahl der \u00dcberschriften ist nicht korrekt! Es sind {0} aber es sollten {1} sein +validation.message.header.match = \u00dcberschrift in Spalte {0} stimmt nicht. "{1}" sollte "{3}" sein \ No newline at end of file diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_en.properties b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_en.properties deleted file mode 100644 index 41802fb..0000000 --- a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv_en.properties +++ /dev/null @@ -1,53 +0,0 @@ -menu.title.import.gpx = Import GPX -menu.title.file = File -menu.title.quit = Quit -menu.title.help = Help -menu.title.settings = Settings -menu.title.about = About GeoFroggerFX -menu.title.plugins = Plugins -menu.title.list = Lists -menu.title.list.new = New list -menu.title.list.delete = Delete list - - -menu.title.sort = Sort -menu.title.filter = Filter - -label.text.cache.list=List: -label.text.cache.list.count=Number: -label.text.name=Name: -label.text.difficulty=Difficulty: -label.text.terrain=Terrain: -label.text.placedBy=Placed By: -label.text.owner=Owner: -label.text.date=Date: -label.text.type=Type: -label.text.container=Container: -label.text.shortdescription=Short description: -label.text.htmldescription=HTML Description -label.text.longdescription=Long description: - -tab.text.descriptions=Descriptions -tab.text.general=General - -sort.cache.name = GC Code -sort.cache.type = Type -sort.cache.difficulty = Difficulty -sort.cache.terrain = Terrain -sort.cache.placedBy = Placed by -sort.cache.owner = Owner - -dialog.title.about = About -dialog.title.new_list = New list -dialog.label.listname = Name of list: -dialog.msg.list.does.exist = List does already exist! -dialog.title.delete_list = Delete list - -all.caches = All caches - -status.load.all.caches.from.db = Load cache lists from database. -status.all.cache.lists.loaded = All cache lists loaded. -status.load.caches.from.db = Load caches from database. -status.all.caches.loaded = All caches loaded. -status.store.all.caches = Store caches in database. -status.all.caches.stored = All caches are stored in database. \ No newline at end of file diff --git a/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVModelTest.java b/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVModelTest.java index 8ff6939..67fb072 100644 --- a/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVModelTest.java +++ b/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVModelTest.java @@ -88,7 +88,7 @@ public class CSVModelTest { sut.setValidator(validator); // assertion - verify(validator).isValid(TESTHEADER, TESTVALUE); + verify(validator).isValid(TESTHEADER, TESTVALUE, 0); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVValueTest.java b/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVValueTest.java index b2bff24..acf016e 100644 --- a/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVValueTest.java +++ b/src/test/java/ninja/javafx/smartcsv/fx/table/model/CSVValueTest.java @@ -4,6 +4,8 @@ import ninja.javafx.smartcsv.validation.Validator; import org.junit.Before; import org.junit.Test; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -53,6 +55,6 @@ public class CSVValueTest { sut.setValue(VALUE); // assertion - verify(validator).isValid(COLUMN, VALUE); + verify(validator).isValid(eq(COLUMN), eq(VALUE), anyInt()); } } \ No newline at end of file diff --git a/src/test/java/ninja/javafx/smartcsv/validation/ConfigMock.java b/src/test/java/ninja/javafx/smartcsv/validation/ConfigMock.java new file mode 100644 index 0000000..63853aa --- /dev/null +++ b/src/test/java/ninja/javafx/smartcsv/validation/ConfigMock.java @@ -0,0 +1,58 @@ +package ninja.javafx.smartcsv.validation; + +import com.typesafe.config.Config; + +import static java.util.Arrays.asList; +import static org.mockito.Mockito.*; + +public class ConfigMock { + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // constants + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + private static final String HEADER_SECTION_KEY = "headers"; + private static final String COLUMN_SECTION_KEY = "columns"; + private static final String LIST_KEY = "list"; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // mocks + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + public static Config headerSectionConfig(String[] headerNames) { + + Config headerSectionConfig = mock(Config.class); + Config listConfig = mock(Config.class); + + when(headerSectionConfig.hasPath(HEADER_SECTION_KEY)).thenReturn(true); + when(headerSectionConfig.getConfig(HEADER_SECTION_KEY)).thenReturn(listConfig); + + when(listConfig.hasPath(LIST_KEY)).thenReturn(true); + when(listConfig.getStringList(LIST_KEY)).thenReturn(asList(headerNames)); + + return headerSectionConfig; + } + + + public static Config columnSectionConfig(String column, String validation, Object value) { + + Config columnSectionConfig = mock(Config.class); + Config columnConfig = mock(Config.class); + Config validatorConfig = mock(Config.class); + + when(columnSectionConfig.hasPath(COLUMN_SECTION_KEY)).thenReturn(true); + when(columnSectionConfig.getConfig(COLUMN_SECTION_KEY)).thenReturn(columnConfig); + + when(columnConfig.hasPath(column)).thenReturn(true); + when(columnConfig.getConfig(column)).thenReturn(validatorConfig); + + when(validatorConfig.hasPath(validation)).thenReturn(true); + if (value instanceof Boolean) { + when(validatorConfig.getBoolean(validation)).thenReturn((Boolean) value); + } else if (value instanceof String) { + when(validatorConfig.getString(validation)).thenReturn((String) value); + } else if (value instanceof Integer) { + when(validatorConfig.getInt(validation)).thenReturn((Integer) value); + } + + return columnSectionConfig; + } +} \ No newline at end of file diff --git a/src/test/java/ninja/javafx/smartcsv/validation/HeaderValidationTest.java b/src/test/java/ninja/javafx/smartcsv/validation/HeaderValidationTest.java new file mode 100644 index 0000000..27a125d --- /dev/null +++ b/src/test/java/ninja/javafx/smartcsv/validation/HeaderValidationTest.java @@ -0,0 +1,116 @@ +/* + 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.typesafe.config.Config; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static ninja.javafx.smartcsv.validation.ConfigMock.headerSectionConfig; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +/** + * unit test for header validator + */ +@RunWith(Parameterized.class) +public class HeaderValidationTest { + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // parameters + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + private Config config; + private Boolean expectedResult; + private List expectedErrors; + private String[] headerNames; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // subject under test + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + private Validator sut; + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // parameterized constructor + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + public HeaderValidationTest(String[] configHeaderNames, + String[] headerNames, + Boolean expectedResult, + List expectedErrors) { + this.config = headerSectionConfig(configHeaderNames); + this.headerNames = headerNames; + this.expectedResult = expectedResult; + this.expectedErrors = expectedErrors; + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // init + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Before + public void initialize() { + sut = new Validator(config); + } + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // tests + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Test + public void validation() { + // execution + ValidationError result = sut.isHeaderValid(headerNames); + + // assertion + assertThat(result == null, is(expectedResult)); + if (!expectedResult) { + assertTrue(result.getMessages().containsAll(expectedErrors)); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // parameters for tests + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Parameterized.Parameters + public static Collection validationConfigurations() { + return asList(new Object[][] { + { new String[] {}, new String[] {}, true, null }, + { new String[] {"a"}, new String[] {"a"}, true, null }, + { new String[] {"a"}, new String[] {"b"}, false, singletonList(new ValidationMessage("validation.message.header.match", "0", "a", "b"))}, + { new String[] {"a"}, new String[] {"a","b"}, false, singletonList(new ValidationMessage("validation.message.header.length", "2", "1"))}, + { new String[] {"a", "b"}, new String[] {"b", "a"}, false, asList(new ValidationMessage("validation.message.header.match", "0", "a", "b"), new ValidationMessage("validation.message.header.match", "1", "b", "a")) } + }); + } +} diff --git a/src/test/java/ninja/javafx/smartcsv/validation/ValidatorTest.java b/src/test/java/ninja/javafx/smartcsv/validation/ValidatorTest.java index d2ba076..29bd918 100644 --- a/src/test/java/ninja/javafx/smartcsv/validation/ValidatorTest.java +++ b/src/test/java/ninja/javafx/smartcsv/validation/ValidatorTest.java @@ -9,10 +9,10 @@ import org.junit.runners.Parameterized; import java.util.Collection; import static java.util.Arrays.asList; +import static ninja.javafx.smartcsv.validation.ConfigMock.columnSectionConfig; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; /** * unit test for validator @@ -27,7 +27,7 @@ public class ValidatorTest { private String column; private String value; private Boolean expectedResult; - private String expectedError; + private ValidationMessage expectedError; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -45,8 +45,8 @@ public class ValidatorTest { String column, String value, Boolean expectedResult, - String expectedError) { - this.config = config(configcolumn, configValidation, configValue); + ValidationMessage expectedError) { + this.config = columnSectionConfig(configcolumn, configValidation, configValue); this.column = column; this.value = value; this.expectedResult = expectedResult; @@ -69,38 +69,15 @@ public class ValidatorTest { @Test public void validation() { // execution - ValidationState result = sut.isValid(column, value); + ValidationError result = sut.isValid(column, value, 0); // assertion - assertThat(result.isValid(), is(expectedResult)); + assertThat(result == null, is(expectedResult)); if (!expectedResult) { - assertThat(result.error(), is(expectedError)); + assertThat(result.getMessages(), contains(expectedError)); } } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // mocks - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private Config config(String column, String validation, Object value) { - - Config columnConfig = mock(Config.class); - Config validatorConfig = mock(Config.class); - - when(columnConfig.hasPath(column)).thenReturn(true); - when(columnConfig.getConfig(column)).thenReturn(validatorConfig); - - when(validatorConfig.hasPath(validation)).thenReturn(true); - if (value instanceof Boolean) { - when(validatorConfig.getBoolean(validation)).thenReturn((Boolean) value); - } else if (value instanceof String) { - when(validatorConfig.getString(validation)).thenReturn((String) value); - } else if (value instanceof Integer) { - when(validatorConfig.getInt(validation)).thenReturn((Integer)value); - } - - return columnConfig; - } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // parameters for tests //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -108,22 +85,22 @@ public class ValidatorTest { public static Collection validationConfigurations() { return asList(new Object[][] { { "column", "not empty", true, "column", "value", true, null }, - { "column", "not empty", true, "column", "", false, "should not be empty\n" }, - { "column", "not empty", true, "column", null, false, "should not be empty\n" }, + { "column", "not empty", true, "column", "", false, new ValidationMessage("validation.message.not.empty") }, + { "column", "not empty", true, "column", null, false, new ValidationMessage("validation.message.not.empty") }, { "column", "integer", true, "column", "999", true, null }, - { "column", "integer", true, "column", "a", false, "should be an integer\n" }, + { "column", "integer", true, "column", "a", false, new ValidationMessage("validation.message.integer") }, { "column", "minlength", 2, "column", "12", true, null }, - { "column", "minlength", 2, "column", "1", false, "has not min length of 2\n" }, + { "column", "minlength", 2, "column", "1", false, new ValidationMessage("validation.message.min.length", "2") }, { "column", "maxlength", 2, "column", "12", true, null }, - { "column", "maxlength", 2, "column", "123", false, "has not max length of 2\n" }, + { "column", "maxlength", 2, "column", "123", false, new ValidationMessage("validation.message.max.length", "2") }, { "column", "date", "yyyyMMdd", "column", "20151127", true, null }, - { "column", "date", "yyyyMMdd", "column", "27.11.2015", false, "is not a date of format yyyyMMdd\n" }, + { "column", "date", "yyyyMMdd", "column", "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyyMMdd") }, { "column", "alphanumeric", true, "column", "abcABC123", true, null }, - { "column", "alphanumeric", true, "column", "-abcABC123", false, "should not be alphanumeric\n" }, + { "column", "alphanumeric", true, "column", "-abcABC123", false, new ValidationMessage("validation.message.alphanumeric") }, { "column", "regexp", "[a-z]*", "column", "abc", true, null }, - { "column", "regexp", "[a-z]*", "column", "abcA", false, "does not match [a-z]*\n" }, + { "column", "regexp", "[a-z]*", "column", "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") }, { "column", "groovy", "value.contains('a')? 'true' : 'no a inside'", "column", "abcdef", true, null }, - { "column", "groovy", "value.contains('a')? 'true' : 'no a inside'", "column", "bcdefg", false, "no a inside\n" }, + { "column", "groovy", "value.contains('a')? 'true' : 'no a inside'", "column", "bcdefg", false, new ValidationMessage("no a inside") }, }); }