From fc26dcc9aaea1af7fcff63f8ef65f4c74f5b1fed Mon Sep 17 00:00:00 2001 From: Andreas Billmann Date: Fri, 5 Feb 2016 08:00:32 +0100 Subject: [PATCH] validation rules are now editable through context menu --- .../smartcsv/fx/SmartCSVController.java | 132 ++++++- .../fx/preferences/PreferencesController.java | 4 - .../smartcsv/fx/table/model/CSVModel.java | 9 +- .../ValidationEditorController.java | 348 ++++++++++++++++++ .../validation/ValidationConfiguration.java | 110 ++++-- .../validation/ValidationFileReader.java | 4 +- .../validation/ValidationFileWriter.java | 55 +++ .../javafx/smartcsv/validation/Validator.java | 20 +- .../javafx/smartcsv/fx/application.properties | 1 + .../ninja/javafx/smartcsv/fx/smartcsv.fxml | 81 +++- .../javafx/smartcsv/fx/smartcsv.properties | 18 +- .../javafx/smartcsv/fx/smartcsv_de.properties | 22 +- .../fx/validation/validationEditor.fxml | 69 ++++ .../smartcsv/fx/table/model/CSVModelTest.java | 15 +- 14 files changed, 787 insertions(+), 101 deletions(-) create mode 100644 src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java create mode 100644 src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java create mode 100644 src/main/resources/ninja/javafx/smartcsv/fx/validation/validationEditor.fxml diff --git a/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java b/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java index 4c090d2..7ccd1d2 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/SmartCSVController.java @@ -30,6 +30,8 @@ import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.ListChangeListener; +import javafx.collections.WeakListChangeListener; import javafx.concurrent.WorkerStateEvent; import javafx.event.ActionEvent; import javafx.event.EventHandler; @@ -53,10 +55,12 @@ import ninja.javafx.smartcsv.fx.table.model.CSVRow; import ninja.javafx.smartcsv.fx.table.model.CSVValue; import ninja.javafx.smartcsv.fx.util.LoadFileService; import ninja.javafx.smartcsv.fx.util.SaveFileService; +import ninja.javafx.smartcsv.fx.validation.ValidationEditorController; import ninja.javafx.smartcsv.preferences.PreferencesFileReader; import ninja.javafx.smartcsv.preferences.PreferencesFileWriter; import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationFileReader; +import ninja.javafx.smartcsv.validation.ValidationFileWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -69,6 +73,7 @@ import java.util.Optional; import java.util.ResourceBundle; import static java.lang.Math.max; +import static java.text.MessageFormat.format; import static javafx.application.Platform.exit; import static javafx.application.Platform.runLater; import static javafx.beans.binding.Bindings.*; @@ -89,6 +94,10 @@ public class SmartCSVController extends FXMLController { ".SmartCSV.fx" + File.separator + "" + "preferences.json"); + public static final String CSV_FILTER_TEXT = "CSV files (*.csv)"; + public static final String CSV_FILTER_EXTENSION = "*.csv"; + public static final String JSON_FILTER_TEXT = "JSON files (*.json)"; + public static final String JSON_FILTER_EXTENSION = "*.json"; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // injections @@ -109,12 +118,18 @@ public class SmartCSVController extends FXMLController { @Autowired private CSVFileWriter csvFileWriter; + @Autowired + private ValidationFileWriter validationFileWriter; + @Autowired private AboutController aboutController; @Autowired private PreferencesController preferencesController; + @Autowired + private ValidationEditorController validationEditorController; + @Autowired private LoadFileService loadFileService; @@ -142,6 +157,15 @@ public class SmartCSVController extends FXMLController { @FXML private MenuItem saveAsMenuItem; + @FXML + private MenuItem loadConfigMenuItem; + + @FXML + private MenuItem saveConfigMenuItem; + + @FXML + private MenuItem saveAsConfigMenuItem; + @FXML private MenuItem deleteRowMenuItem; @@ -154,14 +178,21 @@ public class SmartCSVController extends FXMLController { @FXML private Button saveAsButton; + @FXML + private Button loadConfigButton; + + @FXML + private Button saveConfigButton; + + @FXML + private Button saveAsConfigButton; + @FXML private Button deleteRowButton; @FXML private Button addRowButton; - private ErrorSideBar errorSideBar; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -170,11 +201,14 @@ public class SmartCSVController extends FXMLController { private CSVModel model; private TableView tableView; + private ErrorSideBar errorSideBar; private BooleanProperty fileChanged = new SimpleBooleanProperty(true); private ResourceBundle resourceBundle; private ObjectProperty currentCsvFile = new SimpleObjectProperty<>(); private ObjectProperty currentConfigFile= new SimpleObjectProperty<>(); + private ListChangeListener errorListListener = c -> tableView.refresh(); + private WeakListChangeListener weakErrorListListener = new WeakListChangeListener<>(errorListListener); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // init @@ -185,22 +219,28 @@ public class SmartCSVController extends FXMLController { this.resourceBundle = resourceBundle; setupTableCellFactory(); + setupErrorSideBar(resourceBundle); - errorSideBar = new ErrorSideBar(resourceBundle); + bindMenuItemsToFileExistence(currentCsvFile, saveMenuItem, saveAsMenuItem, addRowMenuItem, loadConfigMenuItem); + bindButtonsToFileExistence(currentCsvFile, saveButton, saveAsButton, addRowButton, loadConfigButton); - errorSideBar.selectedValidationErrorProperty().addListener((observable, oldValue, newValue) -> { - scrollToError(newValue); - }); - applicationPane.setRight(errorSideBar); + bindMenuItemsToFileExistence(currentConfigFile, saveConfigMenuItem, saveAsConfigMenuItem); + bindButtonsToFileExistence(currentConfigFile, saveAsConfigButton, saveConfigButton); - bindMenuItemsToCsvFileExtistence(saveMenuItem, saveAsMenuItem, addRowMenuItem); - bindButtonsToCsvFileExistence(saveButton, saveAsButton, addRowButton); bindCsvFileName(); bindConfigFileName(); loadCsvPreferencesFromFile(); } + private void setupErrorSideBar(ResourceBundle resourceBundle) { + errorSideBar = new ErrorSideBar(resourceBundle); + errorSideBar.selectedValidationErrorProperty().addListener((observable, oldValue, newValue) -> { + scrollToError(newValue); + }); + applicationPane.setRight(errorSideBar); + } + private void setupTableCellFactory() { cellFactory = new ValidationCellFactory(resourceBundle); } @@ -226,8 +266,8 @@ public class SmartCSVController extends FXMLController { currentCsvFile.setValue( loadFile( csvLoader, - "CSV files (*.csv)", - "*.csv", + CSV_FILTER_TEXT, + CSV_FILTER_EXTENSION, "Open CSV", currentCsvFile.getValue())); } @@ -237,8 +277,8 @@ public class SmartCSVController extends FXMLController { currentConfigFile.setValue( loadFile( validationLoader, - "JSON files (*.json)", - "*.json", + JSON_FILTER_TEXT, + JSON_FILTER_EXTENSION, "Open Validation Configuration", currentConfigFile.getValue())); } @@ -255,11 +295,28 @@ public class SmartCSVController extends FXMLController { currentCsvFile.setValue( saveFile( csvFileWriter, - "CSV files (*.csv)", - "*.csv", + CSV_FILTER_TEXT, + CSV_FILTER_EXTENSION, currentCsvFile.getValue())); } + @FXML + public void saveConfig(ActionEvent actionEvent) { + validationFileWriter.setValidationConfiguration(validationLoader.getValidationConfiguration()); + useSaveFileService(validationFileWriter, currentConfigFile.getValue()); + } + + @FXML + public void saveAsConfig(ActionEvent actionEvent) { + validationFileWriter.setValidationConfiguration(validationLoader.getValidationConfiguration()); + currentConfigFile.setValue( + saveFile( + validationFileWriter, + JSON_FILTER_TEXT, + JSON_FILTER_EXTENSION, + currentConfigFile.getValue())); + } + @FXML public void close(ActionEvent actionEvent) { if (canExit()) { @@ -334,6 +391,25 @@ public class SmartCSVController extends FXMLController { return canExit; } + public void showValidationEditor(String column) { + validationEditorController.setSelectedColumn(column); + + Alert alert = new Alert(Alert.AlertType.CONFIRMATION); + alert.setGraphic(null); + alert.setTitle(resourceBundle.getString("dialog.validation.rules.title")); + alert.setHeaderText(format(resourceBundle.getString("dialog.validation.rules.header"), column)); + alert.getDialogPane().setContent(validationEditorController.getView()); + Optional result = alert.showAndWait(); + + if (result.get() == ButtonType.OK){ + runLater(() -> { + validationEditorController.updateConfiguration(); + fileChanged.setValue(true); + model.revalidate(); + }); + } + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // private methods //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -345,15 +421,15 @@ public class SmartCSVController extends FXMLController { tableView.getSelectionModel().select(lastRow); } - private void bindMenuItemsToCsvFileExtistence(MenuItem... items) { + private void bindMenuItemsToFileExistence(ObjectProperty file, MenuItem... items) { for (MenuItem item: items) { - item.disableProperty().bind(isNull(currentCsvFile)); + item.disableProperty().bind(isNull(file)); } } - private void bindButtonsToCsvFileExistence(Button... items) { + private void bindButtonsToFileExistence(ObjectProperty file, Button... items) { for (Button item: items) { - item.disableProperty().bind(isNull(currentCsvFile)); + item.disableProperty().bind(isNull(file)); } } @@ -489,7 +565,9 @@ public class SmartCSVController extends FXMLController { private void resetContent() { model = csvLoader.getData(); if (model != null) { - model.setValidator(validationLoader.getValidator()); + model.getValidationError().addListener(weakErrorListListener); + model.setValidationConfiguration(validationLoader.getValidationConfiguration()); + validationEditorController.setValidationConfiguration(validationLoader.getValidationConfiguration()); tableView = new TableView<>(); bindMenuItemsToTableSelection(deleteRowMenuItem); @@ -521,6 +599,11 @@ public class SmartCSVController extends FXMLController { column.setCellValueFactory(new ObservableMapValueFactory(header)); column.setCellFactory(cellFactory); column.setEditable(true); + column.setSortable(false); + + ContextMenu contextMenu = contextMenuForColumn(header); + column.setContextMenu(contextMenu); + column.setOnEditCommit(new EventHandler>() { @Override public void handle(TableColumn.CellEditEvent event) { @@ -536,6 +619,15 @@ public class SmartCSVController extends FXMLController { tableView.getColumns().add(column); } + private ContextMenu contextMenuForColumn(String header) { + ContextMenu contextMenu = new ContextMenu(); + MenuItem editColumnRulesMenuItem = new MenuItem(resourceBundle.getString("context.menu.edit.column.rules")); + bindMenuItemsToFileExistence(currentConfigFile, editColumnRulesMenuItem); + editColumnRulesMenuItem.setOnAction(e -> showValidationEditor(header)); + contextMenu.getItems().addAll(editColumnRulesMenuItem); + return contextMenu; + } + private void scrollToError(ValidationError entry) { if (entry != null) { if (entry.getLineNumber() != null) { diff --git a/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java b/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java index 01ad86b..d5f6304 100644 --- a/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java +++ b/src/main/java/ninja/javafx/smartcsv/fx/preferences/PreferencesController.java @@ -26,12 +26,8 @@ package ninja.javafx.smartcsv.fx.preferences; -import javafx.beans.InvalidationListener; -import javafx.beans.Observable; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; import javafx.scene.control.ComboBox; 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 ba0d489..079609f 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,6 +28,7 @@ package ninja.javafx.smartcsv.fx.table.model; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import ninja.javafx.smartcsv.validation.ValidationConfiguration; import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.Validator; @@ -43,11 +44,11 @@ public class CSVModel { private ObservableList validationError = FXCollections.observableArrayList(); /** - * sets the validator for the data revalidates - * @param validator the validator for this data + * sets the validator configuration for the data revalidates + * @param validationConfiguration the validator configuration for this data */ - public void setValidator(Validator validator) { - this.validator = validator; + public void setValidationConfiguration(ValidationConfiguration validationConfiguration) { + this.validator = new Validator(validationConfiguration); revalidate(); } diff --git a/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java b/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java new file mode 100644 index 0000000..9cbdbc7 --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/fx/validation/ValidationEditorController.java @@ -0,0 +1,348 @@ +/* + 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.validation; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import ninja.javafx.smartcsv.fx.FXMLController; +import ninja.javafx.smartcsv.validation.ValidationConfiguration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.net.URL; +import java.util.List; +import java.util.ResourceBundle; + +import static java.util.Arrays.asList; +import static java.util.stream.Collectors.joining; + +/** + * controller for editing column validations + */ +@Component +public class ValidationEditorController extends FXMLController { + + private StringProperty selectedColumn = new SimpleStringProperty(); + private ValidationConfiguration validationConfiguration; + + @FXML + private CheckBox notEmptyRuleCheckBox; + + @FXML + private CheckBox integerRuleCheckBox; + + @FXML + private CheckBox doublerRuleCheckBox; + + @FXML + private CheckBox alphanumericRuleCheckBox; + + @FXML + private Spinner minLengthSpinner; + + @FXML + private Spinner maxLengthSpinner; + + @FXML + private TextField dateformatRuleTextField; + + @FXML + private TextField regexpRuleTextField; + + @FXML + private TextField valueOfRuleTextField; + + @FXML + private TextArea groovyRuleTextArea; + + @FXML + private CheckBox enableNotEmptyRule; + + @FXML + private CheckBox enableIntegerRule; + + @FXML + private CheckBox enableDoubleRule; + + @FXML + private CheckBox enableAlphanumericRule; + + @FXML + private CheckBox enableMinLengthRule; + + @FXML + private CheckBox enableMaxLengthRule; + + @FXML + private CheckBox enableDateRule; + + @FXML + private CheckBox enableRegexpRule; + + @FXML + private CheckBox enableValueOfRule; + + @FXML + private CheckBox enableGroovyRule; + + + @Value("${fxml.smartcvs.validation.editor.view}") + @Override + public void setFxmlFilePath(String filePath) { + this.fxmlFilePath = filePath; + } + + @Override + public void initialize(URL location, ResourceBundle resources) { + + minLengthSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0)); + maxLengthSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0)); + + initCheckBox(notEmptyRuleCheckBox, enableNotEmptyRule); + initCheckBox(integerRuleCheckBox, enableIntegerRule); + initCheckBox(doublerRuleCheckBox, enableDoubleRule); + initCheckBox(alphanumericRuleCheckBox, enableAlphanumericRule); + initSpinner(minLengthSpinner, enableMinLengthRule); + initSpinner(maxLengthSpinner, enableMaxLengthRule); + initTextInputControl(dateformatRuleTextField, enableDateRule); + initTextInputControl(regexpRuleTextField, enableRegexpRule); + initTextInputControl(valueOfRuleTextField, enableValueOfRule); + initTextInputControl(groovyRuleTextArea, enableGroovyRule); + + selectedColumn.addListener(observable -> { + updateForm(); + }); + } + + public String getSelectedColumn() { + return selectedColumn.get(); + } + + public StringProperty selectedColumnProperty() { + return selectedColumn; + } + + public void setSelectedColumn(String selectedColumn) { + this.selectedColumn.set(selectedColumn); + } + + public void setValidationConfiguration(ValidationConfiguration validationConfiguration) { + this.validationConfiguration = validationConfiguration; + } + + public void updateConfiguration() { + + if (enableIntegerRule.isSelected()) { + validationConfiguration.setIntegerRuleFor(selectedColumn.getValue(), integerRuleCheckBox.isSelected()); + } else { + validationConfiguration.setIntegerRuleFor(selectedColumn.getValue(), null); + } + + if (enableNotEmptyRule.isSelected()) { + validationConfiguration.setNotEmptyRuleFor(selectedColumn.getValue(), notEmptyRuleCheckBox.isSelected()); + } else { + validationConfiguration.setNotEmptyRuleFor(selectedColumn.getValue(), null); + } + + if (enableDoubleRule.isSelected()) { + validationConfiguration.setDoubleRuleFor(selectedColumn.getValue(), doublerRuleCheckBox.isSelected()); + } else { + validationConfiguration.setDoubleRuleFor(selectedColumn.getValue(), null); + } + + if (enableAlphanumericRule.isSelected()) { + validationConfiguration.setAlphanumericRuleFor(selectedColumn.getValue(), alphanumericRuleCheckBox.isSelected()); + } else { + validationConfiguration.setAlphanumericRuleFor(selectedColumn.getValue(), null); + } + + if (enableDateRule.isSelected()) { + validationConfiguration.setDateRuleFor(selectedColumn.getValue(), dateformatRuleTextField.getText()); + } else { + validationConfiguration.setDateRuleFor(selectedColumn.getValue(), null); + } + + if (enableGroovyRule.isSelected()) { + validationConfiguration.setGroovyRuleFor(selectedColumn.getValue(), groovyRuleTextArea.getText()); + } else { + validationConfiguration.setGroovyRuleFor(selectedColumn.getValue(), null); + } + + if (enableMinLengthRule.isSelected()) { + validationConfiguration.setMinLengthRuleFor(selectedColumn.getValue(), minLengthSpinner.getValue()); + } else { + validationConfiguration.setMinLengthRuleFor(selectedColumn.getValue(), null); + } + + if (enableMaxLengthRule.isSelected()) { + validationConfiguration.setMaxLengthRuleFor(selectedColumn.getValue(), maxLengthSpinner.getValue()); + } else { + validationConfiguration.setMaxLengthRuleFor(selectedColumn.getValue(), null); + } + + if (enableRegexpRule.isSelected()) { + validationConfiguration.setRegexpRuleFor(selectedColumn.getValue(), regexpRuleTextField.getText()); + } else { + validationConfiguration.setRegexpRuleFor(selectedColumn.getValue(), null); + } + + if (enableValueOfRule.isSelected()) { + validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), asList(valueOfRuleTextField.getText().split(", "))); + } else { + validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), null); + } + } + + private void updateForm() { + + updateCheckBox( + notEmptyRuleCheckBox, + validationConfiguration.getNotEmptyRuleFor(getSelectedColumn()), + enableNotEmptyRule + ); + + updateCheckBox( + integerRuleCheckBox, + validationConfiguration.getIntegerRuleFor(getSelectedColumn()), + enableIntegerRule + ); + + updateCheckBox( + doublerRuleCheckBox, + validationConfiguration.getDoubleRuleFor(getSelectedColumn()), + enableDoubleRule + ); + + updateCheckBox( + alphanumericRuleCheckBox, + validationConfiguration.getAlphanumericRuleFor(getSelectedColumn()), + enableAlphanumericRule + ); + + updateSpinner( + minLengthSpinner, + validationConfiguration.getMinLengthRuleFor(getSelectedColumn()), + enableMinLengthRule + ); + + updateSpinner( + maxLengthSpinner, + validationConfiguration.getMaxLengthRuleFor(getSelectedColumn()), + enableMaxLengthRule + ); + + updateTextInputControl( + dateformatRuleTextField, + validationConfiguration.getDateRuleFor(getSelectedColumn()), + enableDateRule + ); + + updateTextInputControl( + regexpRuleTextField, + validationConfiguration.getRegexpRuleFor(getSelectedColumn()), + enableRegexpRule + ); + + updateTextInputControl( + valueOfRuleTextField, + validationConfiguration.getValueOfRuleFor(getSelectedColumn()), + enableValueOfRule + ); + + updateTextInputControl( + groovyRuleTextArea, + validationConfiguration.getGroovyRuleFor(getSelectedColumn()), + enableGroovyRule + ); + } + + private void updateCheckBox(CheckBox rule, Boolean value, CheckBox ruleEnabled) { + if (value == null) { + ruleEnabled.setSelected(false); + } else { + rule.setSelected(value); + ruleEnabled.setSelected(true); + } + } + + private void updateSpinner(Spinner rule, Integer value, CheckBox ruleEnabled) { + if (value == null) { + ruleEnabled.setSelected(false); + } else { + ruleEnabled.setSelected(true); + rule.getValueFactory().setValue(value); + } + } + + private void updateTextInputControl(TextInputControl rule, String value, CheckBox ruleEnabled) { + if (value == null) { + ruleEnabled.setSelected(false); + } else { + ruleEnabled.setSelected(true); + rule.setText(value); + } + } + + private void updateTextInputControl(TextInputControl rule, List values, CheckBox ruleEnabled) { + if (values == null || values.isEmpty()) { + ruleEnabled.setSelected(false); + } else { + ruleEnabled.setSelected(true); + rule.setText(values.stream().collect(joining(", "))); + } + } + + private void initCheckBox(CheckBox rule, CheckBox ruleEnabled) { + rule.disableProperty().bind(ruleEnabled.selectedProperty().not()); + ruleEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + rule.setSelected(false); + } + }); + } + + private void initSpinner(Spinner rule, CheckBox ruleEnabled) { + rule.disableProperty().bind(ruleEnabled.selectedProperty().not()); + ruleEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + rule.getValueFactory().setValue(0); + } + }); + } + + private void initTextInputControl(TextInputControl rule, CheckBox ruleEnabled) { + rule.disableProperty().bind(ruleEnabled.selectedProperty().not()); + ruleEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + rule.setText(""); + } + }); + } + +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java index 586a3bc..b951a75 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationConfiguration.java @@ -50,54 +50,107 @@ public class ValidationConfiguration { return headerConfiguration.getNames(); } - public Boolean integerRuleFor(String column) { - if (noRulesFor(column)) return FALSE; - return defaultValue((Boolean)columnConfigurations.get(column).get("integer"), FALSE); + public Boolean getIntegerRuleFor(String column) { + return (Boolean)getValue(column, "integer"); } - public Boolean doubleRuleFor(String column) { - if (noRulesFor(column)) return FALSE; - return defaultValue((Boolean)columnConfigurations.get(column).get("double"), FALSE); + public Boolean getDoubleRuleFor(String column) { + return (Boolean)getValue(column, "double"); } - public Boolean notEmptyRuleFor(String column) { - if (noRulesFor(column)) return FALSE; - return defaultValue((Boolean)columnConfigurations.get(column).get("not empty"), FALSE); + public Boolean getNotEmptyRuleFor(String column) { + return (Boolean)getValue(column, "not empty"); } - public Integer minLengthRuleFor(String column) { + public Integer getMinLengthRuleFor(String column) { + return doubleToInteger((Double)getValue(column, "minlength")); + } + + public Integer getMaxLengthRuleFor(String column) { if (noRulesFor(column)) return null; - return doubleToInteger((Double)columnConfigurations.get(column).get("minlength")); + return doubleToInteger((Double)getValue(column, "maxlength")); } - public Integer maxLengthRuleFor(String column) { + public String getDateRuleFor(String column) { if (noRulesFor(column)) return null; - return doubleToInteger((Double)columnConfigurations.get(column).get("maxlength")); + return (String)getValue(column, "date"); } - public String dateRuleFor(String column) { + public Boolean getAlphanumericRuleFor(String column) { if (noRulesFor(column)) return null; - return (String)columnConfigurations.get(column).get("date"); + return (Boolean)getValue(column, "alphanumeric"); } - public Boolean alphanumericRuleFor(String column) { - if (noRulesFor(column)) return FALSE; - return defaultValue((Boolean)columnConfigurations.get(column).get("alphanumeric"), FALSE); - } - - public String regexpRuleFor(String column) { + public String getRegexpRuleFor(String column) { if (noRulesFor(column)) return null; - return (String)columnConfigurations.get(column).get("regexp"); + return (String)getValue(column, "regexp"); } - public List valueOfRuleFor(String column) { + public List getValueOfRuleFor(String column) { if (noRulesFor(column)) return null; - return (List)columnConfigurations.get(column).get("value of"); + return (List)getValue(column, "value of"); } - public String groovyRuleFor(String column) { + public String getGroovyRuleFor(String column) { if (noRulesFor(column)) return null; - return (String)columnConfigurations.get(column).get("groovy"); + return (String)getValue(column, "groovy"); + } + + public void setIntegerRuleFor(String column, Boolean value) { + setValue(column, value, "integer"); + } + + public void setDoubleRuleFor(String column, Boolean value) { + setValue(column, value, "double"); + } + + public void setNotEmptyRuleFor(String column, Boolean value) { + setValue(column, value, "not empty"); + } + + public void setMinLengthRuleFor(String column, Integer value) { + setValue(column, value, "minlength"); + } + + public void setMaxLengthRuleFor(String column, Integer value) { + setValue(column, value, "maxlength"); + } + + public void setDateRuleFor(String column, String value) { + setValue(column, value, "date"); + } + + public void setAlphanumericRuleFor(String column, Boolean value) { + setValue(column, value, "alphanumeric"); + } + + public void setRegexpRuleFor(String column, String value) { + setValue(column, value, "regexp"); + } + + public void setValueOfRuleFor(String column, List value) { + setValue(column, value, "value of"); + } + + public void setGroovyRuleFor(String column, String value) { + setValue(column, value, "groovy"); + } + + private void setValue(String column, Object value, String key) { + if (!columnConfigurations.containsKey(column)) { + columnConfigurations.put(column, new HashMap<>()); + } + + if (value == null && columnConfigurations.get(column).containsKey(key)) { + columnConfigurations.get(column).remove(key); + } else { + columnConfigurations.get(column).put(key, value); + } + } + + private Object getValue(String column, String key) { + if (noRulesFor(column)) return null; + return columnConfigurations.get(column).get(key); } private boolean noHeader() { @@ -108,11 +161,6 @@ public class ValidationConfiguration { return columnConfigurations == null || columnConfigurations.get(column) == null; } - private T defaultValue(T value, T defaultValue) { - if (value == null) return defaultValue; - return value; - } - private Integer doubleToInteger(Double value) { if (value == null) return null; return (int)Math.round(value); diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java index 4f53b3a..fdd1acd 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileReader.java @@ -46,7 +46,7 @@ public class ValidationFileReader implements FileReader { config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class); } - public Validator getValidator() { - return new Validator(config); + public ValidationConfiguration getValidationConfiguration() { + return config; } } diff --git a/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java new file mode 100644 index 0000000..7bcdf6d --- /dev/null +++ b/src/main/java/ninja/javafx/smartcsv/validation/ValidationFileWriter.java @@ -0,0 +1,55 @@ +/* + The MIT License (MIT) + ----------------------------------------------------------------------------- + + Copyright (c) 2015 javafx.ninja + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +*/ + +package ninja.javafx.smartcsv.validation; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import ninja.javafx.smartcsv.FileWriter; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +/** + * file writer for the validation configuration + */ +@Service +public class ValidationFileWriter implements FileWriter { + + private ValidationConfiguration validationConfiguration; + + public void setValidationConfiguration(ValidationConfiguration validationConfiguration) { + this.validationConfiguration = validationConfiguration; + } + + @Override + public void write(File file) throws IOException { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + Files.write(file.toPath(), gson.toJson(validationConfiguration).getBytes()); + } +} diff --git a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java index ab8da26..bdb466a 100644 --- a/src/main/java/ninja/javafx/smartcsv/validation/Validator.java +++ b/src/main/java/ninja/javafx/smartcsv/validation/Validator.java @@ -107,7 +107,7 @@ public class Validator { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void checkGroovy(String column, String value, ValidationError error) { - String groovyScript = validationConfig.groovyRuleFor(column); + String groovyScript = validationConfig.getGroovyRuleFor(column); if (groovyScript != null) { Script script = scriptCache.get(column); @@ -143,7 +143,7 @@ public class Validator { } private void checkValueOf(String column, String value, ValidationError error) { - List values = validationConfig.valueOfRuleFor(column); + List values = validationConfig.getValueOfRuleFor(column); if (values != null) { if (!values.contains(value)) { String commaSeparated = values.stream().collect(joining(", ")); @@ -153,7 +153,7 @@ public class Validator { } private void checkBlankOrNull(String column, String value, ValidationError error) { - if (validationConfig.notEmptyRuleFor(column)) { + if (validationConfig.getNotEmptyRuleFor(column) != null && validationConfig.getNotEmptyRuleFor(column)) { if (isBlankOrNull(value)) { error.add("validation.message.not.empty"); } @@ -161,7 +161,7 @@ public class Validator { } private void checkInteger(String column, String value, ValidationError error) { - if (validationConfig.integerRuleFor(column)) { + if (validationConfig.getIntegerRuleFor(column) != null && validationConfig.getIntegerRuleFor(column)) { if (!isInt(value)) { error.add("validation.message.integer"); } @@ -169,7 +169,7 @@ public class Validator { } private void checkDouble(String column, String value, ValidationError error) { - if (validationConfig.doubleRuleFor(column)) { + if (validationConfig.getDoubleRuleFor(column) != null && validationConfig.getDoubleRuleFor(column)) { if (!isDouble(value)) { error.add("validation.message.double"); } @@ -177,7 +177,7 @@ public class Validator { } private void checkMinLength(String column, String value, ValidationError error) { - Integer minLength = validationConfig.minLengthRuleFor(column); + Integer minLength = validationConfig.getMinLengthRuleFor(column); if (minLength != null) { if (!minLength(value, minLength)) { error.add("validation.message.min.length", minLength.toString()); @@ -186,7 +186,7 @@ public class Validator { } private void checkMaxLength(String column, String value, ValidationError error) { - Integer maxLength = validationConfig.maxLengthRuleFor(column); + Integer maxLength = validationConfig.getMaxLengthRuleFor(column); if (maxLength != null) { if (!maxLength(value, maxLength)) { error.add("validation.message.max.length", maxLength.toString()); @@ -195,7 +195,7 @@ public class Validator { } private void checkDate(String column, String value, ValidationError error) { - String dateformat = validationConfig.dateRuleFor(column); + String dateformat = validationConfig.getDateRuleFor(column); if (dateformat != null && !dateformat.trim().isEmpty()) { if (!isDate(value, dateformat, true)) { error.add("validation.message.date.format", dateformat); @@ -204,7 +204,7 @@ public class Validator { } private void checkAlphaNumeric(String column, String value, ValidationError error) { - if (validationConfig.alphanumericRuleFor(column)) { + if (validationConfig.getAlphanumericRuleFor(column) != null && validationConfig.getAlphanumericRuleFor(column)) { if (!matchRegexp(value, "[0-9a-zA-Z]*")) { error.add("validation.message.alphanumeric"); } @@ -212,7 +212,7 @@ public class Validator { } private void checkRegularExpression(String column, String value, ValidationError error) { - String regexp = validationConfig.regexpRuleFor(column); + String regexp = validationConfig.getRegexpRuleFor(column); if (regexp != null && !regexp.trim().isEmpty()) { if (!matchRegexp(value, regexp)) { error.add("validation.message.regexp", regexp); diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/application.properties b/src/main/resources/ninja/javafx/smartcsv/fx/application.properties index 49cddba..86ee117 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/application.properties +++ b/src/main/resources/ninja/javafx/smartcsv/fx/application.properties @@ -5,6 +5,7 @@ application.version = 0.3 fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml fxml.smartcvs.about.view = /ninja/javafx/smartcsv/fx/about/about.fxml fxml.smartcvs.preferences.view = /ninja/javafx/smartcsv/fx/preferences/preferences.fxml +fxml.smartcvs.validation.editor.view = /ninja/javafx/smartcsv/fx/validation/validationEditor.fxml # resources resource.main = ninja.javafx.smartcsv.fx.smartcsv \ No newline at end of file diff --git a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.fxml b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.fxml index 5e7b92f..98e9da2 100644 --- a/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.fxml +++ b/src/main/resources/ninja/javafx/smartcsv/fx/smartcsv.fxml @@ -25,6 +25,7 @@ + @@ -38,12 +39,6 @@ - - - - - - @@ -54,6 +49,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -103,14 +126,6 @@ - + + + + + +