validation rules are now editable through context menu

This commit is contained in:
Andreas Billmann
2016-02-05 08:00:32 +01:00
parent 10c2592510
commit fc26dcc9aa
14 changed files with 787 additions and 101 deletions

View File

@@ -30,6 +30,8 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ListChangeListener;
import javafx.collections.WeakListChangeListener;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; 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.table.model.CSVValue;
import ninja.javafx.smartcsv.fx.util.LoadFileService; import ninja.javafx.smartcsv.fx.util.LoadFileService;
import ninja.javafx.smartcsv.fx.util.SaveFileService; 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.PreferencesFileReader;
import ninja.javafx.smartcsv.preferences.PreferencesFileWriter; import ninja.javafx.smartcsv.preferences.PreferencesFileWriter;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.ValidationFileReader; 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.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -69,6 +73,7 @@ import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.text.MessageFormat.format;
import static javafx.application.Platform.exit; import static javafx.application.Platform.exit;
import static javafx.application.Platform.runLater; import static javafx.application.Platform.runLater;
import static javafx.beans.binding.Bindings.*; import static javafx.beans.binding.Bindings.*;
@@ -89,6 +94,10 @@ public class SmartCSVController extends FXMLController {
".SmartCSV.fx" + ".SmartCSV.fx" +
File.separator + "" + File.separator + "" +
"preferences.json"); "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 // injections
@@ -109,12 +118,18 @@ public class SmartCSVController extends FXMLController {
@Autowired @Autowired
private CSVFileWriter csvFileWriter; private CSVFileWriter csvFileWriter;
@Autowired
private ValidationFileWriter validationFileWriter;
@Autowired @Autowired
private AboutController aboutController; private AboutController aboutController;
@Autowired @Autowired
private PreferencesController preferencesController; private PreferencesController preferencesController;
@Autowired
private ValidationEditorController validationEditorController;
@Autowired @Autowired
private LoadFileService loadFileService; private LoadFileService loadFileService;
@@ -142,6 +157,15 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
private MenuItem saveAsMenuItem; private MenuItem saveAsMenuItem;
@FXML
private MenuItem loadConfigMenuItem;
@FXML
private MenuItem saveConfigMenuItem;
@FXML
private MenuItem saveAsConfigMenuItem;
@FXML @FXML
private MenuItem deleteRowMenuItem; private MenuItem deleteRowMenuItem;
@@ -154,14 +178,21 @@ public class SmartCSVController extends FXMLController {
@FXML @FXML
private Button saveAsButton; private Button saveAsButton;
@FXML
private Button loadConfigButton;
@FXML
private Button saveConfigButton;
@FXML
private Button saveAsConfigButton;
@FXML @FXML
private Button deleteRowButton; private Button deleteRowButton;
@FXML @FXML
private Button addRowButton; private Button addRowButton;
private ErrorSideBar errorSideBar;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// members // members
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -170,11 +201,14 @@ public class SmartCSVController extends FXMLController {
private CSVModel model; private CSVModel model;
private TableView<CSVRow> tableView; private TableView<CSVRow> tableView;
private ErrorSideBar errorSideBar;
private BooleanProperty fileChanged = new SimpleBooleanProperty(true); private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
private ObjectProperty<File> currentCsvFile = new SimpleObjectProperty<>(); private ObjectProperty<File> currentCsvFile = new SimpleObjectProperty<>();
private ObjectProperty<File> currentConfigFile= new SimpleObjectProperty<>(); private ObjectProperty<File> currentConfigFile= new SimpleObjectProperty<>();
private ListChangeListener<ValidationError> errorListListener = c -> tableView.refresh();
private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init // init
@@ -185,22 +219,28 @@ public class SmartCSVController extends FXMLController {
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
setupTableCellFactory(); 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) -> { bindMenuItemsToFileExistence(currentConfigFile, saveConfigMenuItem, saveAsConfigMenuItem);
scrollToError(newValue); bindButtonsToFileExistence(currentConfigFile, saveAsConfigButton, saveConfigButton);
});
applicationPane.setRight(errorSideBar);
bindMenuItemsToCsvFileExtistence(saveMenuItem, saveAsMenuItem, addRowMenuItem);
bindButtonsToCsvFileExistence(saveButton, saveAsButton, addRowButton);
bindCsvFileName(); bindCsvFileName();
bindConfigFileName(); bindConfigFileName();
loadCsvPreferencesFromFile(); loadCsvPreferencesFromFile();
} }
private void setupErrorSideBar(ResourceBundle resourceBundle) {
errorSideBar = new ErrorSideBar(resourceBundle);
errorSideBar.selectedValidationErrorProperty().addListener((observable, oldValue, newValue) -> {
scrollToError(newValue);
});
applicationPane.setRight(errorSideBar);
}
private void setupTableCellFactory() { private void setupTableCellFactory() {
cellFactory = new ValidationCellFactory(resourceBundle); cellFactory = new ValidationCellFactory(resourceBundle);
} }
@@ -226,8 +266,8 @@ public class SmartCSVController extends FXMLController {
currentCsvFile.setValue( currentCsvFile.setValue(
loadFile( loadFile(
csvLoader, csvLoader,
"CSV files (*.csv)", CSV_FILTER_TEXT,
"*.csv", CSV_FILTER_EXTENSION,
"Open CSV", "Open CSV",
currentCsvFile.getValue())); currentCsvFile.getValue()));
} }
@@ -237,8 +277,8 @@ public class SmartCSVController extends FXMLController {
currentConfigFile.setValue( currentConfigFile.setValue(
loadFile( loadFile(
validationLoader, validationLoader,
"JSON files (*.json)", JSON_FILTER_TEXT,
"*.json", JSON_FILTER_EXTENSION,
"Open Validation Configuration", "Open Validation Configuration",
currentConfigFile.getValue())); currentConfigFile.getValue()));
} }
@@ -255,11 +295,28 @@ public class SmartCSVController extends FXMLController {
currentCsvFile.setValue( currentCsvFile.setValue(
saveFile( saveFile(
csvFileWriter, csvFileWriter,
"CSV files (*.csv)", CSV_FILTER_TEXT,
"*.csv", CSV_FILTER_EXTENSION,
currentCsvFile.getValue())); 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 @FXML
public void close(ActionEvent actionEvent) { public void close(ActionEvent actionEvent) {
if (canExit()) { if (canExit()) {
@@ -334,6 +391,25 @@ public class SmartCSVController extends FXMLController {
return canExit; 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<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
runLater(() -> {
validationEditorController.updateConfiguration();
fileChanged.setValue(true);
model.revalidate();
});
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// private methods // private methods
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -345,15 +421,15 @@ public class SmartCSVController extends FXMLController {
tableView.getSelectionModel().select(lastRow); tableView.getSelectionModel().select(lastRow);
} }
private void bindMenuItemsToCsvFileExtistence(MenuItem... items) { private void bindMenuItemsToFileExistence(ObjectProperty<File> file, MenuItem... items) {
for (MenuItem item: 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> file, Button... items) {
for (Button item: 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() { private void resetContent() {
model = csvLoader.getData(); model = csvLoader.getData();
if (model != null) { if (model != null) {
model.setValidator(validationLoader.getValidator()); model.getValidationError().addListener(weakErrorListListener);
model.setValidationConfiguration(validationLoader.getValidationConfiguration());
validationEditorController.setValidationConfiguration(validationLoader.getValidationConfiguration());
tableView = new TableView<>(); tableView = new TableView<>();
bindMenuItemsToTableSelection(deleteRowMenuItem); bindMenuItemsToTableSelection(deleteRowMenuItem);
@@ -521,6 +599,11 @@ public class SmartCSVController extends FXMLController {
column.setCellValueFactory(new ObservableMapValueFactory(header)); column.setCellValueFactory(new ObservableMapValueFactory(header));
column.setCellFactory(cellFactory); column.setCellFactory(cellFactory);
column.setEditable(true); column.setEditable(true);
column.setSortable(false);
ContextMenu contextMenu = contextMenuForColumn(header);
column.setContextMenu(contextMenu);
column.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<CSVRow, CSVValue>>() { column.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<CSVRow, CSVValue>>() {
@Override @Override
public void handle(TableColumn.CellEditEvent<CSVRow, CSVValue> event) { public void handle(TableColumn.CellEditEvent<CSVRow, CSVValue> event) {
@@ -536,6 +619,15 @@ public class SmartCSVController extends FXMLController {
tableView.getColumns().add(column); 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) { private void scrollToError(ValidationError entry) {
if (entry != null) { if (entry != null) {
if (entry.getLineNumber() != null) { if (entry.getLineNumber() != null) {

View File

@@ -26,12 +26,8 @@
package ninja.javafx.smartcsv.fx.preferences; package ninja.javafx.smartcsv.fx.preferences;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox; import javafx.scene.control.ComboBox;

View File

@@ -28,6 +28,7 @@ package ninja.javafx.smartcsv.fx.table.model;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.Validator; import ninja.javafx.smartcsv.validation.Validator;
@@ -43,11 +44,11 @@ public class CSVModel {
private ObservableList<ValidationError> validationError = FXCollections.observableArrayList(); private ObservableList<ValidationError> validationError = FXCollections.observableArrayList();
/** /**
* sets the validator for the data revalidates * sets the validator configuration for the data revalidates
* @param validator the validator for this data * @param validationConfiguration the validator configuration for this data
*/ */
public void setValidator(Validator validator) { public void setValidationConfiguration(ValidationConfiguration validationConfiguration) {
this.validator = validator; this.validator = new Validator(validationConfiguration);
revalidate(); revalidate();
} }

View File

@@ -0,0 +1,348 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015 javafx.ninja <info@javafx.ninja>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package ninja.javafx.smartcsv.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<Integer> minLengthSpinner;
@FXML
private Spinner<Integer> 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<String> 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("");
}
});
}
}

View File

@@ -50,54 +50,107 @@ public class ValidationConfiguration {
return headerConfiguration.getNames(); return headerConfiguration.getNames();
} }
public Boolean integerRuleFor(String column) { public Boolean getIntegerRuleFor(String column) {
if (noRulesFor(column)) return FALSE; return (Boolean)getValue(column, "integer");
return defaultValue((Boolean)columnConfigurations.get(column).get("integer"), FALSE);
} }
public Boolean doubleRuleFor(String column) { public Boolean getDoubleRuleFor(String column) {
if (noRulesFor(column)) return FALSE; return (Boolean)getValue(column, "double");
return defaultValue((Boolean)columnConfigurations.get(column).get("double"), FALSE);
} }
public Boolean notEmptyRuleFor(String column) { public Boolean getNotEmptyRuleFor(String column) {
if (noRulesFor(column)) return FALSE; return (Boolean)getValue(column, "not empty");
return defaultValue((Boolean)columnConfigurations.get(column).get("not empty"), FALSE);
} }
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; 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; 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; if (noRulesFor(column)) return null;
return (String)columnConfigurations.get(column).get("date"); return (Boolean)getValue(column, "alphanumeric");
} }
public Boolean alphanumericRuleFor(String column) { public String getRegexpRuleFor(String column) {
if (noRulesFor(column)) return FALSE;
return defaultValue((Boolean)columnConfigurations.get(column).get("alphanumeric"), FALSE);
}
public String regexpRuleFor(String column) {
if (noRulesFor(column)) return null; if (noRulesFor(column)) return null;
return (String)columnConfigurations.get(column).get("regexp"); return (String)getValue(column, "regexp");
} }
public List<String> valueOfRuleFor(String column) { public List<String> getValueOfRuleFor(String column) {
if (noRulesFor(column)) return null; if (noRulesFor(column)) return null;
return (List<String>)columnConfigurations.get(column).get("value of"); return (List<String>)getValue(column, "value of");
} }
public String groovyRuleFor(String column) { public String getGroovyRuleFor(String column) {
if (noRulesFor(column)) return null; 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<String> 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() { private boolean noHeader() {
@@ -108,11 +161,6 @@ public class ValidationConfiguration {
return columnConfigurations == null || columnConfigurations.get(column) == null; return columnConfigurations == null || columnConfigurations.get(column) == null;
} }
private <T> T defaultValue(T value, T defaultValue) {
if (value == null) return defaultValue;
return value;
}
private Integer doubleToInteger(Double value) { private Integer doubleToInteger(Double value) {
if (value == null) return null; if (value == null) return null;
return (int)Math.round(value); return (int)Math.round(value);

View File

@@ -46,7 +46,7 @@ public class ValidationFileReader implements FileReader {
config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class); config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class);
} }
public Validator getValidator() { public ValidationConfiguration getValidationConfiguration() {
return new Validator(config); return config;
} }
} }

View File

@@ -0,0 +1,55 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015 javafx.ninja <info@javafx.ninja>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package ninja.javafx.smartcsv.validation;
import com.google.gson.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());
}
}

View File

@@ -107,7 +107,7 @@ public class Validator {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void checkGroovy(String column, String value, ValidationError error) { private void checkGroovy(String column, String value, ValidationError error) {
String groovyScript = validationConfig.groovyRuleFor(column); String groovyScript = validationConfig.getGroovyRuleFor(column);
if (groovyScript != null) { if (groovyScript != null) {
Script script = scriptCache.get(column); Script script = scriptCache.get(column);
@@ -143,7 +143,7 @@ public class Validator {
} }
private void checkValueOf(String column, String value, ValidationError error) { private void checkValueOf(String column, String value, ValidationError error) {
List<String> values = validationConfig.valueOfRuleFor(column); List<String> values = validationConfig.getValueOfRuleFor(column);
if (values != null) { if (values != null) {
if (!values.contains(value)) { if (!values.contains(value)) {
String commaSeparated = values.stream().collect(joining(", ")); String commaSeparated = values.stream().collect(joining(", "));
@@ -153,7 +153,7 @@ public class Validator {
} }
private void checkBlankOrNull(String column, String value, ValidationError error) { private void checkBlankOrNull(String column, String value, ValidationError error) {
if (validationConfig.notEmptyRuleFor(column)) { if (validationConfig.getNotEmptyRuleFor(column) != null && validationConfig.getNotEmptyRuleFor(column)) {
if (isBlankOrNull(value)) { if (isBlankOrNull(value)) {
error.add("validation.message.not.empty"); error.add("validation.message.not.empty");
} }
@@ -161,7 +161,7 @@ public class Validator {
} }
private void checkInteger(String column, String value, ValidationError error) { private void checkInteger(String column, String value, ValidationError error) {
if (validationConfig.integerRuleFor(column)) { if (validationConfig.getIntegerRuleFor(column) != null && validationConfig.getIntegerRuleFor(column)) {
if (!isInt(value)) { if (!isInt(value)) {
error.add("validation.message.integer"); error.add("validation.message.integer");
} }
@@ -169,7 +169,7 @@ public class Validator {
} }
private void checkDouble(String column, String value, ValidationError error) { private void checkDouble(String column, String value, ValidationError error) {
if (validationConfig.doubleRuleFor(column)) { if (validationConfig.getDoubleRuleFor(column) != null && validationConfig.getDoubleRuleFor(column)) {
if (!isDouble(value)) { if (!isDouble(value)) {
error.add("validation.message.double"); error.add("validation.message.double");
} }
@@ -177,7 +177,7 @@ public class Validator {
} }
private void checkMinLength(String column, String value, ValidationError error) { private void checkMinLength(String column, String value, ValidationError error) {
Integer minLength = validationConfig.minLengthRuleFor(column); Integer minLength = validationConfig.getMinLengthRuleFor(column);
if (minLength != null) { if (minLength != null) {
if (!minLength(value, minLength)) { if (!minLength(value, minLength)) {
error.add("validation.message.min.length", minLength.toString()); error.add("validation.message.min.length", minLength.toString());
@@ -186,7 +186,7 @@ public class Validator {
} }
private void checkMaxLength(String column, String value, ValidationError error) { private void checkMaxLength(String column, String value, ValidationError error) {
Integer maxLength = validationConfig.maxLengthRuleFor(column); Integer maxLength = validationConfig.getMaxLengthRuleFor(column);
if (maxLength != null) { if (maxLength != null) {
if (!maxLength(value, maxLength)) { if (!maxLength(value, maxLength)) {
error.add("validation.message.max.length", maxLength.toString()); error.add("validation.message.max.length", maxLength.toString());
@@ -195,7 +195,7 @@ public class Validator {
} }
private void checkDate(String column, String value, ValidationError error) { 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 (dateformat != null && !dateformat.trim().isEmpty()) {
if (!isDate(value, dateformat, true)) { if (!isDate(value, dateformat, true)) {
error.add("validation.message.date.format", dateformat); error.add("validation.message.date.format", dateformat);
@@ -204,7 +204,7 @@ public class Validator {
} }
private void checkAlphaNumeric(String column, String value, ValidationError error) { 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]*")) { if (!matchRegexp(value, "[0-9a-zA-Z]*")) {
error.add("validation.message.alphanumeric"); error.add("validation.message.alphanumeric");
} }
@@ -212,7 +212,7 @@ public class Validator {
} }
private void checkRegularExpression(String column, String value, ValidationError error) { 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 (regexp != null && !regexp.trim().isEmpty()) {
if (!matchRegexp(value, regexp)) { if (!matchRegexp(value, regexp)) {
error.add("validation.message.regexp", regexp); error.add("validation.message.regexp", regexp);

View File

@@ -5,6 +5,7 @@ application.version = 0.3
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml
fxml.smartcvs.about.view = /ninja/javafx/smartcsv/fx/about/about.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.preferences.view = /ninja/javafx/smartcsv/fx/preferences/preferences.fxml
fxml.smartcvs.validation.editor.view = /ninja/javafx/smartcsv/fx/validation/validationEditor.fxml
# resources # resources
resource.main = ninja.javafx.smartcsv.fx.smartcsv resource.main = ninja.javafx.smartcsv.fx.smartcsv

View File

@@ -25,6 +25,7 @@
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?> <?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?>
<?import ninja.javafx.smartcsv.fx.list.ErrorSideBar?> <?import ninja.javafx.smartcsv.fx.list.ErrorSideBar?>
<?import de.jensd.fx.glyphs.GlyphsStack?>
<BorderPane fx:id="applicationPane" maxHeight="-Infinity" maxWidth="1000.0" minHeight="700.0" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"> <BorderPane fx:id="applicationPane" maxHeight="-Infinity" maxWidth="1000.0" minHeight="700.0" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
<top> <top>
<VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER"> <VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER">
@@ -38,12 +39,6 @@
<FontAwesomeIconView styleClass="open-icon" /> <FontAwesomeIconView styleClass="open-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<MenuItem mnemonicParsing="false" onAction="#openConfig" text="%menu.open.config">
<graphic>
<FontAwesomeIconView styleClass="config-icon" />
</graphic>
</MenuItem>
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="saveMenuItem" disable="true" mnemonicParsing="false" onAction="#saveCsv" text="%menu.save"> <MenuItem fx:id="saveMenuItem" disable="true" mnemonicParsing="false" onAction="#saveCsv" text="%menu.save">
<graphic> <graphic>
<FontAwesomeIconView styleClass="save-icon" /> <FontAwesomeIconView styleClass="save-icon" />
@@ -54,6 +49,34 @@
<FontAwesomeIconView styleClass="save-icon" /> <FontAwesomeIconView styleClass="save-icon" />
</graphic> </graphic>
</MenuItem> </MenuItem>
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="loadConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#openConfig" text="%menu.open.config">
<graphic>
<FontAwesomeIconView styleClass="config-icon" />
</graphic>
</MenuItem>
<MenuItem fx:id="saveConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#saveConfig" text="%menu.save.config">
<graphic>
<GlyphsStack>
<children>
<FontAwesomeIconView styleClass="save-icon" style="-fx-opacity: 0.7;" />
<FontAwesomeIconView styleClass="config-icon" />
</children>
</GlyphsStack>
</graphic>
</MenuItem>
<MenuItem fx:id="saveAsConfigMenuItem" disable="true" mnemonicParsing="false" onAction="#saveAsConfig" text="%menu.save.as.config">
<graphic>
<GlyphsStack>
<children>
<FontAwesomeIconView styleClass="save-icon" style="-fx-opacity: 0.7;" />
<FontAwesomeIconView styleClass="config-icon" />
</children>
</GlyphsStack>
</graphic>
</MenuItem>
<SeparatorMenuItem mnemonicParsing="false" /> <SeparatorMenuItem mnemonicParsing="false" />
<MenuItem mnemonicParsing="false" onAction="#preferences" text="%menu.preferences"> <MenuItem mnemonicParsing="false" onAction="#preferences" text="%menu.preferences">
<graphic> <graphic>
@@ -102,14 +125,6 @@
<graphic> <graphic>
<FontAwesomeIconView styleClass="open-icon" /> <FontAwesomeIconView styleClass="open-icon" />
</graphic> </graphic>
</Button>
<Button mnemonicParsing="false" onAction="#openConfig">
<tooltip>
<Tooltip text="%menu.open.config" />
</tooltip>
<graphic>
<FontAwesomeIconView styleClass="config-icon" />
</graphic>
</Button> </Button>
<Button fx:id="saveButton" disable="true" mnemonicParsing="false" onAction="#saveCsv"> <Button fx:id="saveButton" disable="true" mnemonicParsing="false" onAction="#saveCsv">
<tooltip> <tooltip>
@@ -127,6 +142,44 @@
<FontAwesomeIconView styleClass="save-icon" /> <FontAwesomeIconView styleClass="save-icon" />
</graphic> </graphic>
</Button> </Button>
</HBox>
<Region styleClass="spacer" />
<HBox styleClass="segmented-button-bar">
<Button fx:id="loadConfigButton" mnemonicParsing="false" disable="true" onAction="#openConfig">
<tooltip>
<Tooltip text="%menu.open.config" />
</tooltip>
<graphic>
<FontAwesomeIconView styleClass="config-icon" />
</graphic>
</Button>
<Button fx:id="saveConfigButton" disable="true" mnemonicParsing="false" onAction="#saveConfig">
<tooltip>
<Tooltip text="%menu.save.config" />
</tooltip>
<graphic>
<GlyphsStack>
<children>
<FontAwesomeIconView styleClass="save-icon" style="-fx-opacity: 0.7;" />
<FontAwesomeIconView styleClass="config-icon" />
</children>
</GlyphsStack>
</graphic>
</Button>
<Button fx:id="saveAsConfigButton" disable="true" mnemonicParsing="false" onAction="#saveAsConfig" styleClass="last" text="...">
<tooltip>
<Tooltip text="%menu.save.as.config" />
</tooltip>
<graphic>
<GlyphsStack>
<children>
<FontAwesomeIconView styleClass="save-icon" style="-fx-opacity: 0.7;" />
<FontAwesomeIconView styleClass="config-icon" />
</children>
</GlyphsStack>
</graphic>
</Button>
</HBox> </HBox>
<Region styleClass="spacer" /> <Region styleClass="spacer" />
<HBox styleClass="segmented-button-bar"> <HBox styleClass="segmented-button-bar">

View File

@@ -48,3 +48,19 @@ 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.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}" validation.message.header.match = header number {0} does not match "{1}" should be "{3}"
validation.message.value.of = Value {0} is not part of this list {1} validation.message.value.of = Value {0} is not part of this list {1}
validation.rule.label.not_empty = not empty:
validation.rule.label.integer = integer:
validation.rule.label.double = double:
validation.rule.label.minlength = minimum length:
validation.rule.label.maxlength = maximum length:
validation.rule.label.dateformat = date format:
validation.rule.label.alphanumeric = alphanumeric:
validation.rule.label.regexp = regular expression:
validation.rule.label.value_of = value in list:
validation.rule.label.groovy = groovy:
validation.rules.active = active
dialog.validation.rules.title = Validation rules
dialog.validation.rules.header = Validation rules of column "{0}"
context.menu.edit.column.rules = Edit rules

View File

@@ -10,6 +10,9 @@ menu.open.csv = CSV Datei \u00f6ffnen
menu.open.config = Pr\u00fcfkonfiguration \u00f6ffnen menu.open.config = Pr\u00fcfkonfiguration \u00f6ffnen
menu.save = Speichern menu.save = Speichern
menu.save.as = Speichern als ... menu.save.as = Speichern als ...
menu.save.config = Pr\u00fcfkonfiguration speichern
menu.save.as.config = Pr\u00fcfkonfiguration speichern als ...
menu.close = Beenden menu.close = Beenden
menu.about = \u00dcber ... menu.about = \u00dcber ...
menu.file = Datei menu.file = Datei
@@ -56,3 +59,20 @@ validation.message.regexp = entspricht nicht dem regul\u00e4ren Ausdruck {0}
validation.message.header.length = Anzahl der \u00dcberschriften ist nicht korrekt! Es sind {0} aber es sollten {1} sein 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 validation.message.header.match = \u00dcberschrift in Spalte {0} stimmt nicht. "{1}" sollte "{3}" sein
validation.message.value.of = Der Wert {0} ist nicht in der Liste {1} enthalten validation.message.value.of = Der Wert {0} ist nicht in der Liste {1} enthalten
validation.rule.label.not_empty = Nicht leer:
validation.rule.label.integer = Zahl:
validation.rule.label.double = Gleitkommazahl:
validation.rule.label.minlength = Minimale L\u00e4nge:
validation.rule.label.maxlength = Maximale L\u00e4nge:
validation.rule.label.dateformat = Datumsformat:
validation.rule.label.alphanumeric = Nur Zahlen und Buchstaben:
validation.rule.label.regexp = Regul\u00e4rer Ausdruck:
validation.rule.label.value_of = In der Liste:
validation.rule.label.groovy = groovy:
validation.rules.active = Aktiv
dialog.validation.rules.title = Pr\u00fcfregeln
dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"
context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane hgap="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="600.0" vgap="10.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.65">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints halignment="CENTER" hgrow="NEVER" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="%validation.rule.label.not_empty" GridPane.rowIndex="1" />
<Label text="%validation.rule.label.integer" GridPane.rowIndex="2" />
<Label text="%validation.rule.label.double" GridPane.rowIndex="3" />
<Label text="%validation.rule.label.minlength" GridPane.rowIndex="5" />
<Label text="%validation.rule.label.maxlength" GridPane.rowIndex="6" />
<Label text="%validation.rule.label.dateformat" GridPane.rowIndex="7" />
<Label text="%validation.rule.label.alphanumeric" GridPane.rowIndex="4" />
<Label text="%validation.rule.label.regexp" GridPane.rowIndex="8" />
<Label text="%validation.rule.label.value_of" GridPane.rowIndex="9" />
<Label text="%validation.rule.label.groovy" GridPane.rowIndex="10" />
<CheckBox fx:id="notEmptyRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<CheckBox fx:id="integerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<CheckBox fx:id="doublerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<CheckBox fx:id="alphanumericRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Spinner fx:id="minLengthSpinner" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Spinner fx:id="maxLengthSpinner" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<TextField fx:id="dateformatRuleTextField" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<TextField fx:id="regexpRuleTextField" GridPane.columnIndex="1" GridPane.rowIndex="8" />
<TextField fx:id="valueOfRuleTextField" GridPane.columnIndex="1" GridPane.rowIndex="9" />
<TextArea fx:id="groovyRuleTextArea" prefHeight="300.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="10" GridPane.rowSpan="2" />
<CheckBox fx:id="enableNotEmptyRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<CheckBox fx:id="enableIntegerRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<CheckBox fx:id="enableDoubleRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<CheckBox fx:id="enableAlphanumericRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<CheckBox fx:id="enableMinLengthRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<CheckBox fx:id="enableMaxLengthRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<CheckBox fx:id="enableDateRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="7" />
<CheckBox fx:id="enableRegexpRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="8" />
<CheckBox fx:id="enableValueOfRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="9" />
<CheckBox fx:id="enableGroovyRule" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="10" />
<Label text="%validation.rules.active" GridPane.columnIndex="2" />
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</GridPane>

View File

@@ -26,6 +26,7 @@
package ninja.javafx.smartcsv.fx.table.model; package ninja.javafx.smartcsv.fx.table.model;
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
import ninja.javafx.smartcsv.validation.Validator; import ninja.javafx.smartcsv.validation.Validator;
import org.junit.Test; import org.junit.Test;
@@ -77,20 +78,6 @@ public class CSVModelTest {
assertThat(sut.getRows().indexOf(newRow), is(newRow.getRowNumber())); assertThat(sut.getRows().indexOf(newRow), is(newRow.getRowNumber()));
} }
@Test
public void set_validator_calls_when_model_has_data() {
// setup
Validator validator = mock(Validator.class);
setup_model_with_one_row_one_column_and_value();
// execution
sut.setValidator(validator);
// assertion
verify(validator).isValid(TESTHEADER, TESTVALUE, 0);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// private methods // private methods
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////