9 Commits
0.5 ... 0.6

46 changed files with 932 additions and 443 deletions

View File

@@ -1,5 +1,5 @@
group 'ninja.javafx' group 'ninja.javafx'
version '0.5-SNAPSHOT' version '0.6-SNAPSHOT'
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'groovy' apply plugin: 'groovy'

View File

@@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.csv;
import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.fx.table.model.CSVModel; import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.table.model.CSVRow; import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import org.springframework.stereotype.Service;
import org.supercsv.io.CsvMapReader; import org.supercsv.io.CsvMapReader;
import org.supercsv.io.ICsvMapReader; import org.supercsv.io.ICsvMapReader;
@@ -60,7 +59,7 @@ public class CSVFileReader extends CSVConfigurable implements FileReader<CSVMode
while ((customerMap = mapReader.read(header)) != null) { while ((customerMap = mapReader.read(header)) != null) {
CSVRow row = model.addRow(); CSVRow row = model.addRow();
for (String column : header) { for (String column : header) {
row.addValue(column, customerMap.get(column)); model.addValue(row, column, customerMap.get(column));
} }
} }

View File

@@ -28,7 +28,6 @@ package ninja.javafx.smartcsv.csv;
import ninja.javafx.smartcsv.fx.table.model.CSVModel; import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.table.model.CSVRow; import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import org.springframework.stereotype.Service;
import org.supercsv.io.CsvMapWriter; import org.supercsv.io.CsvMapWriter;
import org.supercsv.io.ICsvMapWriter; import org.supercsv.io.ICsvMapWriter;

View File

@@ -28,11 +28,9 @@ package ninja.javafx.smartcsv.fx;
import javafx.application.Application; import javafx.application.Application;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import ninja.javafx.smartcsv.fx.about.AboutController; import ninja.javafx.smartcsv.fx.about.AboutController;
import org.springframework.context.annotation.*; import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

View File

@@ -26,10 +26,6 @@
package ninja.javafx.smartcsv.fx; package ninja.javafx.smartcsv.fx;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.WeakListChangeListener; import javafx.collections.WeakListChangeListener;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;
@@ -41,7 +37,6 @@ import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import javafx.util.converter.NumberStringConverter;
import ninja.javafx.smartcsv.csv.CSVFileReader; import ninja.javafx.smartcsv.csv.CSVFileReader;
import ninja.javafx.smartcsv.csv.CSVFileWriter; import ninja.javafx.smartcsv.csv.CSVFileWriter;
import ninja.javafx.smartcsv.files.FileStorage; import ninja.javafx.smartcsv.files.FileStorage;
@@ -71,11 +66,9 @@ import org.supercsv.prefs.CsvPreference;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.text.MessageFormat;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import static java.lang.Integer.parseInt;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.text.MessageFormat.format; import static java.text.MessageFormat.format;
import static javafx.application.Platform.exit; import static javafx.application.Platform.exit;
@@ -352,7 +345,7 @@ public class SmartCSVController extends FXMLController {
public void addRow(ActionEvent actionEvent) { public void addRow(ActionEvent actionEvent) {
CSVRow row = currentCsvFile.getContent().addRow(); CSVRow row = currentCsvFile.getContent().addRow();
for (String column : currentCsvFile.getContent().getHeader()) { for (String column : currentCsvFile.getContent().getHeader()) {
row.addValue(column, ""); currentCsvFile.getContent().addValue(row, column, "");
} }
currentCsvFile.setFileChanged(true); currentCsvFile.setFileChanged(true);
resetContent(); resetContent();
@@ -408,7 +401,7 @@ public class SmartCSVController extends FXMLController {
runLater(() -> { runLater(() -> {
validationEditorController.updateConfiguration(); validationEditorController.updateConfiguration();
currentCsvFile.setFileChanged(true); currentCsvFile.setFileChanged(true);
currentCsvFile.getContent().revalidate(); currentCsvFile.getContent().revalidate(column);
}); });
} }
} }
@@ -590,7 +583,7 @@ public class SmartCSVController extends FXMLController {
* @param header name of the column header * @param header name of the column header
* @param tableView the tableview * @param tableView the tableview
*/ */
private void addColumn(String header, TableView tableView) { private void addColumn(final String header, TableView tableView) {
TableColumn column = new TableColumn(header); TableColumn column = new TableColumn(header);
column.setCellValueFactory(new ObservableMapValueFactory(header)); column.setCellValueFactory(new ObservableMapValueFactory(header));
column.setCellFactory(cellFactory); column.setCellFactory(cellFactory);
@@ -607,7 +600,6 @@ public class SmartCSVController extends FXMLController {
getColumns().get(header).setValue(event.getNewValue()); getColumns().get(header).setValue(event.getNewValue());
runLater(() -> { runLater(() -> {
currentCsvFile.setFileChanged(true); currentCsvFile.setFileChanged(true);
currentCsvFile.getContent().revalidate();
}); });
} }
}); });

View File

@@ -36,7 +36,6 @@ import javafx.scene.layout.Region;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import ninja.javafx.smartcsv.fx.table.model.CSVModel; import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.util.ColorConstants;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;

View File

@@ -1,6 +1,5 @@
package ninja.javafx.smartcsv.fx.list; package ninja.javafx.smartcsv.fx.list;
import com.sun.javafx.scene.control.skin.resources.ControlResources;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.*; import javafx.scene.control.*;

View File

@@ -33,7 +33,6 @@ import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import ninja.javafx.smartcsv.fx.table.model.CSVRow; 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.ColorConstants;
import java.util.ResourceBundle; import java.util.ResourceBundle;

View File

@@ -28,22 +28,18 @@ package ninja.javafx.smartcsv.fx.table.model;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.concurrent.Service; import ninja.javafx.smartcsv.validation.RevalidationService;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.validation.ValidationConfiguration; 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;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
/** /**
* The CSVModel is the client representation for the csv filepath. * The CSVModel is the client representation for the csv filepath.
* It holds the data in rows, stores the header and manages the validator. * It holds the data in rows, stores the header and manages the validator.
*/ */
public class CSVModel { public final class CSVModel {
private static final Logger logger = LogManager.getLogger(CSVModel.class); private static final Logger logger = LogManager.getLogger(CSVModel.class);
@@ -55,6 +51,7 @@ public class CSVModel {
/** /**
* sets the validator configuration for the data revalidates * sets the validator configuration for the data revalidates
*
* @param validationConfiguration the validator configuration for this data * @param validationConfiguration the validator configuration for this data
*/ */
public void setValidationConfiguration(ValidationConfiguration validationConfiguration) { public void setValidationConfiguration(ValidationConfiguration validationConfiguration) {
@@ -64,6 +61,7 @@ public class CSVModel {
/** /**
* returns the data as a list of rows of the * returns the data as a list of rows of the
*
* @return list of rows * @return list of rows
*/ */
public ObservableList<CSVRow> getRows() { public ObservableList<CSVRow> getRows() {
@@ -76,18 +74,30 @@ public class CSVModel {
/** /**
* adds a new and empty row * adds a new and empty row
*
* @return the new row * @return the new row
*/ */
public CSVRow addRow() { public CSVRow addRow() {
CSVRow row = new CSVRow(); CSVRow row = new CSVRow();
row.setValidator(validator);
row.setRowNumber(rows.size()); row.setRowNumber(rows.size());
rows.add(row); rows.add(row);
return row; return row;
} }
public void addValue(final CSVRow row, final String column, final String value) {
final CSVValue csvValue = row.addValue(column, value);
csvValue.valueProperty().addListener(observable -> {
if (validator.needsColumnValidation(column)) {
revalidate();
} else {
csvValue.setValidationError(validator.isValid(row.getRowNumber(), column, csvValue.getValue()));
}
});
}
/** /**
* sets the column headers as string array * sets the column headers as string array
*
* @param header the headers of the columns * @param header the headers of the columns
*/ */
public void setHeader(String[] header) { public void setHeader(String[] header) {
@@ -97,6 +107,7 @@ public class CSVModel {
/** /**
* returns the column headers * returns the column headers
*
* @return the column headers * @return the column headers
*/ */
public String[] getHeader() { public String[] getHeader() {
@@ -104,6 +115,12 @@ public class CSVModel {
} }
public void revalidate(String column) {
if (!hasValidator()) return;
validator.reinitializeColumn(column);
revalidate();
}
/** /**
* walks through the data and validates each value * walks through the data and validates each value
*/ */
@@ -113,8 +130,6 @@ public class CSVModel {
logger.info("revalidate: hasValidator -> {}", hasValidator()); logger.info("revalidate: hasValidator -> {}", hasValidator());
if (!hasValidator()) return; if (!hasValidator()) return;
validator.clearScriptCache();
revalidationService.setHeader(header); revalidationService.setHeader(header);
revalidationService.setRows(rows); revalidationService.setRows(rows);
revalidationService.setValidator(validator); revalidationService.setValidator(validator);
@@ -135,66 +150,6 @@ public class CSVModel {
return newValidationConfiguration; return newValidationConfiguration;
} }
private static class RevalidationService extends Service<List<ValidationError>> {
private Validator validator;
private List<CSVRow> rows;
private String[] header;
public void setValidator(Validator validator) {
this.validator = validator;
}
public void setRows(List<CSVRow> rows) {
this.rows = rows;
}
public void setHeader(String[] header) {
this.header = header;
}
@Override
protected Task<List<ValidationError>> createTask() {
return new Task<List<ValidationError>>() {
@Override
protected List<ValidationError> call() throws Exception {
List<ValidationError> errors = new ArrayList<>();
try {
if (header != null) {
ValidationError headerError = validator.isHeaderValid(header);
if (headerError != null) {
logger.info("revalidate: header error found");
errors.add(headerError);
}
}
for (int lineNumber = 0; lineNumber < rows.size(); lineNumber++) {
CSVRow row = rows.get(lineNumber);
row.setValidator(validator);
for (String column : row.getColumns().keySet()) {
CSVValue value = row.getColumns().get(column).getValue();
value.setValidator(validator);
if (validator != null) {
ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber);
if (validationError != null) {
logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber);
errors.add(validationError);
value.setValidationError(validationError);
} else {
value.setValidationError(null);
}
} else {
value.setValidationError(null);
}
}
}
} catch (Throwable t) {
logger.error("validation error", t);
}
return errors;
}
};
}
}
} }

View File

@@ -30,24 +30,14 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableMap; import javafx.collections.ObservableMap;
import ninja.javafx.smartcsv.validation.Validator;
/** /**
* This class represents a single row in the csv file. * This class represents a single row in the csv file.
*/ */
public class CSVRow { public class CSVRow {
private Validator validator;
private ObservableMap<String, ObjectProperty<CSVValue>> columns = FXCollections.observableHashMap(); private ObservableMap<String, ObjectProperty<CSVValue>> columns = FXCollections.observableHashMap();
private int rowNumber; private int rowNumber;
/**
* single row
* @param validator the reference to the validator
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/** /**
* sets the row number * sets the row number
* @param rowNumber * @param rowNumber
@@ -78,13 +68,11 @@ public class CSVRow {
* @param column column name * @param column column name
* @param value the value to store * @param value the value to store
*/ */
public void addValue(String column, String value) { CSVValue addValue(String column, String value) {
CSVValue v = new CSVValue(); CSVValue v = new CSVValue();
v.setValidator(validator);
v.setColumn(column);
v.setRowNumber(rowNumber);
v.setValue(value); v.setValue(value);
columns.put(column, new SimpleObjectProperty<>(v)); columns.put(column, new SimpleObjectProperty<>(v));
return v;
} }
} }

View File

@@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.fx.table.model;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.Validator;
/** /**
* The csv value represents the value of a single cell. * The csv value represents the value of a single cell.
@@ -37,36 +36,9 @@ import ninja.javafx.smartcsv.validation.Validator;
* and if the value is valid based on the validator. * and if the value is valid based on the validator.
*/ */
public class CSVValue { public class CSVValue {
private Validator validator;
private int rowNumber;
private String column;
private StringProperty value = new SimpleStringProperty(); private StringProperty value = new SimpleStringProperty();
private ValidationError valid; private ValidationError valid;
/**
* single value of a cell
* @param validator the reference to the validator
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/**
* the row number this value is stored in
* @param row row number
*/
public void setRowNumber(int row) {
this.rowNumber = row;
}
/**
* the column this value is stored in
* @param column header name of the column
*/
public void setColumn(String column) {
this.column = column;
}
/** /**
* returns the real value * returns the real value
* @return the real value * @return the real value
@@ -88,9 +60,6 @@ public class CSVValue {
* @param value the real value * @param value the real value
*/ */
public void setValue(String value) { public void setValue(String value) {
if (validator != null) {
valid = validator.isValid(column, value, rowNumber);
}
this.value.set(value); this.value.set(value);
} }
@@ -106,7 +75,7 @@ public class CSVValue {
* sets the state if a value is valid or not * sets the state if a value is valid or not
* @param valid the validation state * @param valid the validation state
*/ */
protected void setValidationError(ValidationError valid) { public void setValidationError(ValidationError valid) {
this.valid = valid; this.valid = valid;
} }
} }

View File

@@ -31,5 +31,5 @@ package ninja.javafx.smartcsv.fx.util;
*/ */
public class ColorConstants { public class ColorConstants {
public static final String OK_COLOR = "#22aa22"; public static final String OK_COLOR = "#22aa22";
public static final String ERROR_COLOR = "#ff6622"; public static final String ERROR_COLOR = "#ff3333";
} }

View File

@@ -62,7 +62,7 @@ public class I18nValidationUtil {
if (resourceBundle.containsKey(validationMessage.getKey())) { if (resourceBundle.containsKey(validationMessage.getKey())) {
String resourceText = resourceBundle.getString(validationMessage.getKey()); String resourceText = resourceBundle.getString(validationMessage.getKey());
if (validationMessage.getParameters().length > 0) { if (validationMessage.getParameters().length > 0) {
message.append(format(resourceText, validationMessage.getParameters())).append("\n"); message.append(format(resourceText, (Object[]) validationMessage.getParameters())).append("\n");
} else { } else {
message.append(resourceText).append("\n"); message.append(resourceText).append("\n");
} }

View File

@@ -28,11 +28,8 @@ package ninja.javafx.smartcsv.fx.util;
import javafx.concurrent.Service; import javafx.concurrent.Service;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.files.FileStorage; import ninja.javafx.smartcsv.files.FileStorage;
import java.io.File;
/** /**
* Service class for async load of a csv file * Service class for async load of a csv file
*/ */

View File

@@ -28,14 +28,8 @@ package ninja.javafx.smartcsv.fx.util;
import javafx.concurrent.Service; import javafx.concurrent.Service;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import ninja.javafx.smartcsv.FileWriter;
import ninja.javafx.smartcsv.csv.CSVFileWriter;
import ninja.javafx.smartcsv.files.FileStorage; import ninja.javafx.smartcsv.files.FileStorage;
import java.io.File;
import static javafx.application.Platform.runLater;
/** /**
* Service class for async load of a csv file * Service class for async load of a csv file
*/ */

View File

@@ -107,6 +107,9 @@ public class ValidationEditorController extends FXMLController {
@FXML @FXML
private CheckBox alphanumericRuleCheckBox; private CheckBox alphanumericRuleCheckBox;
@FXML
private CheckBox uniqueRuleCheckBox;
@FXML @FXML
private Spinner<Integer> minLengthSpinner; private Spinner<Integer> minLengthSpinner;
@@ -155,6 +158,9 @@ public class ValidationEditorController extends FXMLController {
@FXML @FXML
private CheckBox enableGroovyRule; private CheckBox enableGroovyRule;
@FXML
private CheckBox enableUniqueRule;
@Value("${fxml.smartcvs.validation.editor.view}") @Value("${fxml.smartcvs.validation.editor.view}")
@Override @Override
@@ -172,6 +178,7 @@ public class ValidationEditorController extends FXMLController {
initCheckBox(integerRuleCheckBox, enableIntegerRule); initCheckBox(integerRuleCheckBox, enableIntegerRule);
initCheckBox(doublerRuleCheckBox, enableDoubleRule); initCheckBox(doublerRuleCheckBox, enableDoubleRule);
initCheckBox(alphanumericRuleCheckBox, enableAlphanumericRule); initCheckBox(alphanumericRuleCheckBox, enableAlphanumericRule);
initCheckBox(uniqueRuleCheckBox, enableUniqueRule);
initSpinner(minLengthSpinner, enableMinLengthRule); initSpinner(minLengthSpinner, enableMinLengthRule);
initSpinner(maxLengthSpinner, enableMaxLengthRule); initSpinner(maxLengthSpinner, enableMaxLengthRule);
initTextInputControl(dateformatRuleTextField, enableDateRule); initTextInputControl(dateformatRuleTextField, enableDateRule);
@@ -214,6 +221,12 @@ public class ValidationEditorController extends FXMLController {
validationConfiguration.setNotEmptyRuleFor(selectedColumn.getValue(), null); validationConfiguration.setNotEmptyRuleFor(selectedColumn.getValue(), null);
} }
if (enableUniqueRule.isSelected()) {
validationConfiguration.setUniqueRuleFor(selectedColumn.getValue(), uniqueRuleCheckBox.isSelected());
} else {
validationConfiguration.setUniqueRuleFor(selectedColumn.getValue(), null);
}
if (enableDoubleRule.isSelected()) { if (enableDoubleRule.isSelected()) {
validationConfiguration.setDoubleRuleFor(selectedColumn.getValue(), doublerRuleCheckBox.isSelected()); validationConfiguration.setDoubleRuleFor(selectedColumn.getValue(), doublerRuleCheckBox.isSelected());
} else { } else {
@@ -261,6 +274,8 @@ public class ValidationEditorController extends FXMLController {
} else { } else {
validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), null); validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), null);
} }
} }
private void updateForm() { private void updateForm() {
@@ -289,6 +304,12 @@ public class ValidationEditorController extends FXMLController {
enableAlphanumericRule enableAlphanumericRule
); );
updateCheckBox(
uniqueRuleCheckBox,
validationConfiguration.getUniqueRuleFor(getSelectedColumn()),
enableUniqueRule
);
updateSpinner( updateSpinner(
minLengthSpinner, minLengthSpinner,
validationConfiguration.getMinLengthRuleFor(getSelectedColumn()), validationConfiguration.getMinLengthRuleFor(getSelectedColumn()),

View File

@@ -28,7 +28,6 @@ package ninja.javafx.smartcsv.preferences;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.FileReader;
import org.springframework.stereotype.Service;
import org.supercsv.prefs.CsvPreference; import org.supercsv.prefs.CsvPreference;
import org.supercsv.quote.AlwaysQuoteMode; import org.supercsv.quote.AlwaysQuoteMode;

View File

@@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.preferences;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileWriter; import ninja.javafx.smartcsv.FileWriter;
import org.springframework.stereotype.Service;
import org.supercsv.prefs.CsvPreference; import org.supercsv.prefs.CsvPreference;
import java.io.File; import java.io.File;

View File

@@ -0,0 +1,45 @@
/*
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 static org.apache.commons.validator.GenericValidator.matchRegexp;
/**
* Checks if the value is alpha numeric
*/
public class AlphaNumericValidation implements Validation {
@Override
public void check(int row, String value, ValidationError error) {
if (!matchRegexp(value, "[0-9a-zA-Z]*")) {
error.add("validation.message.alphanumeric");
}
}
@Override
public Type getType() {
return Type.ALPHANUMERIC;
}
}

View File

@@ -0,0 +1,53 @@
/*
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 static org.apache.commons.validator.GenericValidator.isDate;
/**
* Checks if the date has the right format
*/
public class DateValidation implements Validation {
private String dateformat;
public DateValidation(String dateformat) {
assert dateformat != null && !dateformat.trim().isEmpty() : "empty date format for date validation";
this.dateformat = dateformat;
}
@Override
public void check(int row, String value, ValidationError error) {
if (!isDate(value, dateformat, true)) {
error.add("validation.message.date.format", dateformat);
}
}
@Override
public Type getType() {
return Type.DATE;
}
}

View File

@@ -0,0 +1,46 @@
/*
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 static org.apache.commons.validator.GenericValidator.isDouble;
/**
* Checks if the value is a double
*/
public class DoubleValidation implements Validation {
@Override
public void check(int row, String value, ValidationError error) {
if (!isDouble(value)) {
error.add("validation.message.double");
}
}
@Override
public Type getType() {
return Type.DOUBLE;
}
}

View File

@@ -0,0 +1,78 @@
/*
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 groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilationFailedException;
/**
* Executes the given groovy as check
*/
public class GroovyValidation implements Validation {
private String groovyScript;
private GroovyShell shell = new GroovyShell();
private Script script;
public GroovyValidation(String groovyScript) {
this.groovyScript = groovyScript;
script = shell.parse(groovyScript);
}
@Override
public void check(int row, String value, ValidationError error) {
Binding binding = new Binding();
binding.setVariable("value", value);
script.setBinding(binding);
Object groovyResult = null;
try {
groovyResult = script.run();
} catch (CompilationFailedException e) {
error.add("validation.message.groovy.exception", groovyScript, e.getMessage());
e.printStackTrace();
}
if (groovyResult == null) {
error.add("validation.message.groovy.return.null", groovyScript);
}
if (!isScriptResultTrue(groovyResult)) {
error.add(groovyResult.toString());
}
}
@Override
public Type getType() {
return Type.GROOVY;
}
private boolean isScriptResultTrue(Object groovyResult) {
return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true");
}
}

View File

@@ -0,0 +1,46 @@
/*
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 static org.apache.commons.validator.GenericValidator.isInt;
/**
* Checks if the value is an integer
*/
public class IntegerValidation implements Validation {
@Override
public void check(int row, String value, ValidationError error) {
if (!isInt(value)) {
error.add("validation.message.integer");
}
}
@Override
public Type getType() {
return Type.INTEGER;
}
}

View File

@@ -0,0 +1,52 @@
/*
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 static org.apache.commons.validator.GenericValidator.maxLength;
/**
* Checks if the value is shorter or exactly as long as the given max length
*/
public class MaxLengthValidation implements Validation {
private int maxLength;
public MaxLengthValidation(int maxLength) {
this.maxLength = maxLength;
}
@Override
public void check(int row, String value, ValidationError error) {
if (!maxLength(value, maxLength)) {
error.add("validation.message.max.length", Integer.toString(maxLength));
}
}
@Override
public Type getType() {
return Type.MAX_LENGTH;
}
}

View File

@@ -0,0 +1,52 @@
/*
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 static org.apache.commons.validator.GenericValidator.minLength;
/**
* Checks if the value is at minimum long as the given min length
*/
public class MinLengthValidation implements Validation {
private int minLength;
public MinLengthValidation(int minLength) {
this.minLength = minLength;
}
@Override
public void check(int row, String value, ValidationError error) {
if (!minLength(value, minLength)) {
error.add("validation.message.min.length", Integer.toString(minLength));
}
}
@Override
public Type getType() {
return Type.MIN_LENGTH;
}
}

View File

@@ -0,0 +1,46 @@
/*
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 static org.apache.commons.validator.GenericValidator.isBlankOrNull;
/**
* Checks if the value is not empty
*/
public class NotEmptyValidation implements Validation {
@Override
public void check(int row, String value, ValidationError error) {
if (isBlankOrNull(value)) {
error.add("validation.message.not.empty");
}
}
@Override
public Type getType() {
return Type.NOT_EMPTY;
}
}

View File

@@ -0,0 +1,52 @@
/*
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 static org.apache.commons.validator.GenericValidator.matchRegexp;
/**
* Checks the value against the given reg exp
*/
public class RegExpValidation implements Validation {
private String regexp;
public RegExpValidation(String regexp) {
this.regexp = regexp;
}
@Override
public void check(int row, String value, ValidationError error) {
if (!matchRegexp(value, regexp)) {
error.add("validation.message.regexp", regexp);
}
}
@Override
public Type getType() {
return Type.REGEXP;
}
}

View File

@@ -0,0 +1,110 @@
/*
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 javafx.beans.property.ObjectProperty;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Service for running the validation async of the ui thread
*/
public class RevalidationService extends Service<List<ValidationError>> {
private static final Logger logger = LogManager.getLogger(RevalidationService.class);
private Validator validator;
private List<CSVRow> rows;
private String[] header;
public void setValidator(Validator validator) {
this.validator = validator;
}
public void setRows(List<CSVRow> rows) {
this.rows = rows;
}
public void setHeader(String[] header) {
this.header = header;
}
@Override
protected Task<List<ValidationError>> createTask() {
return new Task<List<ValidationError>>() {
@Override
protected List<ValidationError> call() throws Exception {
List<ValidationError> errors = new ArrayList<>();
try {
if (header != null) {
ValidationError headerError = validator.isHeaderValid(header);
if (headerError != null) {
logger.info("revalidate: header error found");
errors.add(headerError);
}
}
int maxRows = rows.size();
for (int lineNumber = 0; lineNumber < maxRows; lineNumber++) {
CSVRow row = rows.get(lineNumber);
Map<String, ObjectProperty<CSVValue>> table = row.getColumns();
Set<String> columns = table.keySet();
for (String column : columns) {
CSVValue value = table.get(column).getValue();
if (validator != null) {
ValidationError validationError = validator.isValid(lineNumber, column, value.getValue());
if (validationError != null) {
logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber);
errors.add(validationError);
value.setValidationError(validationError);
} else {
value.setValidationError(null);
}
} else {
value.setValidationError(null);
}
}
}
} catch (Throwable t) {
logger.error("validation error", t);
}
return errors;
}
};
}
}

View File

@@ -0,0 +1,54 @@
/*
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 java.util.HashMap;
/**
* Checks if the value is unique in the column
*/
public class UniqueValidation implements Validation {
private HashMap<String, Integer> columnValueMap = new HashMap<>();
@Override
public void check(int row, String value, ValidationError error) {
Integer valueInLineNumber = columnValueMap.get(value);
if (valueInLineNumber != null) {
if (!valueInLineNumber.equals(row)) {
valueInLineNumber += 1; // show not 0 based line numbers to user
error.add("validation.message.uniqueness", value, valueInLineNumber.toString());
}
} else {
columnValueMap.put(value, row);
}
}
@Override
public Type getType() {
return Type.UNIQUE;
}
}

View File

@@ -0,0 +1,36 @@
/*
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;
/**
* Interface for all validations
*/
public interface Validation {
enum Type { NOT_EMPTY, UNIQUE, DOUBLE, INTEGER, MIN_LENGTH, MAX_LENGTH, DATE, ALPHANUMERIC, REGEXP, VALUE_OF, GROOVY }
void check(int row, String value, ValidationError error);
Type getType();
}

View File

@@ -52,7 +52,7 @@ public class ValidationConfiguration {
headerConfiguration.setNames(headerNames); headerConfiguration.setNames(headerNames);
} }
public Boolean getUniquenessRuleFor(String column) { public Boolean getUniqueRuleFor(String column) {
return (Boolean)getValue(column, "unique"); return (Boolean)getValue(column, "unique");
} }
@@ -73,32 +73,27 @@ public class ValidationConfiguration {
} }
public Integer getMaxLengthRuleFor(String column) { public Integer getMaxLengthRuleFor(String column) {
if (noRulesFor(column)) return null; Double value = (Double)getValue(column, "maxlength");
return doubleToInteger((Double)getValue(column, "maxlength")); return value != null ? doubleToInteger(value) : null;
} }
public String getDateRuleFor(String column) { public String getDateRuleFor(String column) {
if (noRulesFor(column)) return null;
return (String)getValue(column, "date"); return (String)getValue(column, "date");
} }
public Boolean getAlphanumericRuleFor(String column) { public Boolean getAlphanumericRuleFor(String column) {
if (noRulesFor(column)) return null;
return (Boolean)getValue(column, "alphanumeric"); return (Boolean)getValue(column, "alphanumeric");
} }
public String getRegexpRuleFor(String column) { public String getRegexpRuleFor(String column) {
if (noRulesFor(column)) return null;
return (String)getValue(column, "regexp"); return (String)getValue(column, "regexp");
} }
public List<String> getValueOfRuleFor(String column) { public List<String> getValueOfRuleFor(String column) {
if (noRulesFor(column)) return null;
return (List<String>)getValue(column, "value of"); return (List<String>)getValue(column, "value of");
} }
public String getGroovyRuleFor(String column) { public String getGroovyRuleFor(String column) {
if (noRulesFor(column)) return null;
return (String)getValue(column, "groovy"); return (String)getValue(column, "groovy");
} }
@@ -114,6 +109,11 @@ public class ValidationConfiguration {
setValue(column, value, "not empty"); setValue(column, value, "not empty");
} }
public void setUniqueRuleFor(String column, Boolean value) {
setValue(column, value, "unique");
}
public void setMinLengthRuleFor(String column, Integer value) { public void setMinLengthRuleFor(String column, Integer value) {
setValue(column, value == null ? null : value.doubleValue(), "minlength"); setValue(column, value == null ? null : value.doubleValue(), "minlength");
} }
@@ -155,18 +155,19 @@ public class ValidationConfiguration {
} }
private Object getValue(String column, String key) { private Object getValue(String column, String key) {
if (noRulesFor(column)) return null; if (columnConfigurations != null) {
Map rulesForColumn = columnConfigurations.get(column);
if (rulesForColumn != null) {
return columnConfigurations.get(column).get(key); return columnConfigurations.get(column).get(key);
} }
}
return null;
}
private boolean noHeader() { private boolean noHeader() {
return headerConfiguration == null; return headerConfiguration == null;
} }
private boolean noRulesFor(String column) {
return columnConfigurations == null || columnConfigurations.get(column) == null;
}
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

@@ -28,7 +28,6 @@ package ninja.javafx.smartcsv.validation;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileReader; import ninja.javafx.smartcsv.FileReader;
import org.springframework.stereotype.Service;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;

View File

@@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.validation;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileWriter; import ninja.javafx.smartcsv.FileWriter;
import org.springframework.stereotype.Service;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;

View File

@@ -26,19 +26,10 @@
package ninja.javafx.smartcsv.validation; package ninja.javafx.smartcsv.validation;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilationFailedException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.validator.GenericValidator.*;
/** /**
* This class checks all the validations defined in the * This class checks all the validations defined in the
* Config against a given value * Config against a given value
@@ -50,9 +41,7 @@ public class Validator {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private ValidationConfiguration validationConfig; private ValidationConfiguration validationConfig;
private GroovyShell shell = new GroovyShell(); private Map<String, Map<Validation.Type, Validation>> columnValidationMap = new HashMap<>();
private Map<String, Script> scriptCache = new HashMap<>();
private Map<String, HashMap<String, Integer>> uniquenessLookupTable = new HashMap<>();
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// constructors // constructors
@@ -60,10 +49,12 @@ public class Validator {
/** /**
* JSON configuration for this validator * JSON configuration for this validator
*
* @param validationConfig * @param validationConfig
*/ */
public Validator(ValidationConfiguration validationConfig) { public Validator(ValidationConfiguration validationConfig) {
this.validationConfig = validationConfig; this.validationConfig = validationConfig;
initColumnValidations();
} }
@@ -71,31 +62,40 @@ public class Validator {
// public methods // public methods
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public boolean needsColumnValidation(String column) {
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap != null) {
return validationMap.containsKey(Validation.Type.UNIQUE);
}
return false;
}
/** /**
* checks if the value is valid for the column configuration * checks if the value is valid for the column configuration
*
* @param column the column name * @param column the column name
* @param value the value to check * @param value the value to check
* @return ValidationError with information if valid and if not which getMessage happened * @return ValidationError with information if valid and if not which getMessage happened
*/ */
public ValidationError isValid(String column, String value, Integer lineNumber) { public ValidationError isValid(Integer row, String column, String value) {
ValidationError result = null; ValidationError result = null;
if (hasConfig()) { if (hasConfig()) {
ValidationError error = ValidationError.withLineNumber(row);
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap != null) {
for (Validation validation: validationMap.values()) {
ValidationError error = ValidationError.withLineNumber(lineNumber); if (validation.getType() == Validation.Type.NOT_EMPTY) {
checkBlankOrNull(column, value, error); validation.check(row, value, error);
} else {
if (value != null && !value.isEmpty()) { if (value != null && !value.isEmpty()) {
checkRegularExpression(column, value, error); validation.check(row, value, error);
checkAlphaNumeric(column, value, error); }
checkDate(column, value, error); }
checkMaxLength(column, value, error); }
checkMinLength(column, value, error);
checkInteger(column, value, error);
checkGroovy(column, value, error);
checkValueOf(column, value, error);
checkDouble(column, value, error);
checkUniqueness(column, value, lineNumber, error);
} }
if (!error.isEmpty()) { if (!error.isEmpty()) {
result = error; result = error;
} }
@@ -103,151 +103,102 @@ public class Validator {
return result; return result;
} }
public boolean hasConfig() { public boolean hasConfig() {
return validationConfig != null; return validationConfig != null;
} }
public void reinitializeColumn(String column) {
clear(column);
initializeColumnWithRules(column);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// private methods // private methods
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void checkUniqueness(String column, String value, Integer lineNumber, ValidationError error) { private void add(String column, Validation validation) {
if (validationConfig.getUniquenessRuleFor(column) != null && validationConfig.getUniquenessRuleFor(column)) { Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
HashMap<String, Integer> columnValueMap = uniquenessLookupTable.get(column); if (validationMap == null) {
columnValueMap = getColumnValueMap(column, columnValueMap); validationMap = new HashMap<>();
Integer valueInLineNumber = columnValueMap.get(value); columnValidationMap.put(column, validationMap);
if (valueInLineNumber != null) {
if (!valueInLineNumber.equals(lineNumber)) {
error.add("validation.message.uniqueness", value, valueInLineNumber.toString());
} }
} else { validationMap.put(validation.getType(), validation);
columnValueMap.put(value, lineNumber); }
private void clear(String column) {
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap != null) {
validationMap.clear();
}
}
private void initColumnValidations() {
if (hasConfig()) {
String[] columns = validationConfig.headerNames();
for (String column : columns) {
initializeColumnWithRules(column);
} }
} }
} }
private HashMap<String, Integer> getColumnValueMap(String column, HashMap<String, Integer> valueLineNumber) { private void initializeColumnWithRules(String column) {
if (valueLineNumber == null) { Boolean alphaNumeric = validationConfig.getAlphanumericRuleFor(column);
valueLineNumber = new HashMap<>(); if (alphaNumeric != null && alphaNumeric) {
uniquenessLookupTable.put(column, valueLineNumber); add(column, new AlphaNumericValidation());
}
return valueLineNumber;
} }
private void checkGroovy(String column, String value, ValidationError error) { Boolean doubleRule = validationConfig.getDoubleRuleFor(column);
String groovyScript = validationConfig.getGroovyRuleFor(column); if (doubleRule != null && doubleRule) {
if (groovyScript != null) { add(column, new DoubleValidation());
Script script = scriptCache.get(column);
if (script == null) {
script = shell.parse(groovyScript);
scriptCache.put(column, script);
} }
Binding binding = new Binding(); Boolean integerRule = validationConfig.getIntegerRuleFor(column);
binding.setVariable("value", value); if (integerRule != null && integerRule) {
script.setBinding(binding); add(column, new IntegerValidation());
Object groovyResult = null;
try {
groovyResult = script.run();
} catch (CompilationFailedException e) {
error.add("validation.message.groovy.exception", groovyScript, e.getMessage());
e.printStackTrace();
}
if (groovyResult == null) {
error.add("validation.message.groovy.return.null", groovyScript);
} }
if (!isScriptResultTrue(groovyResult)) { Boolean notEmptyRule = validationConfig.getNotEmptyRuleFor(column);
error.add(groovyResult.toString()); if (notEmptyRule != null && notEmptyRule) {
add(column, new NotEmptyValidation());
} }
} Boolean uniqueRule = validationConfig.getUniqueRuleFor(column);
if (uniqueRule != null && uniqueRule) {
add(column, new UniqueValidation());
} }
private boolean isScriptResultTrue(Object groovyResult) { String dateRule = validationConfig.getDateRuleFor(column);
return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true"); if (dateRule != null && !dateRule.trim().isEmpty()) {
add(column, new DateValidation(dateRule));
} }
private void checkValueOf(String column, String value, ValidationError error) {
List<String> values = validationConfig.getValueOfRuleFor(column);
if (values != null) {
if (!values.contains(value)) {
String commaSeparated = values.stream().collect(joining(", "));
error.add("validation.message.value.of", value, commaSeparated);
}
}
}
private void checkBlankOrNull(String column, String value, ValidationError error) {
if (validationConfig.getNotEmptyRuleFor(column) != null && validationConfig.getNotEmptyRuleFor(column)) {
if (isBlankOrNull(value)) {
error.add("validation.message.not.empty");
}
}
}
private void checkInteger(String column, String value, ValidationError error) {
if (validationConfig.getIntegerRuleFor(column) != null && validationConfig.getIntegerRuleFor(column)) {
if (!isInt(value)) {
error.add("validation.message.integer");
}
}
}
private void checkDouble(String column, String value, ValidationError error) {
if (validationConfig.getDoubleRuleFor(column) != null && validationConfig.getDoubleRuleFor(column)) {
if (!isDouble(value)) {
error.add("validation.message.double");
}
}
}
private void checkMinLength(String column, String value, ValidationError error) {
Integer minLength = validationConfig.getMinLengthRuleFor(column); Integer minLength = validationConfig.getMinLengthRuleFor(column);
if (minLength != null) { if (minLength != null) {
if (!minLength(value, minLength)) { add(column, new MinLengthValidation(minLength));
error.add("validation.message.min.length", minLength.toString());
}
}
} }
private void checkMaxLength(String column, String value, ValidationError error) {
Integer maxLength = validationConfig.getMaxLengthRuleFor(column); Integer maxLength = validationConfig.getMaxLengthRuleFor(column);
if (maxLength != null) { if (maxLength != null) {
if (!maxLength(value, maxLength)) { add(column, new MaxLengthValidation(maxLength));
error.add("validation.message.max.length", maxLength.toString());
}
}
} }
private void checkDate(String column, String value, ValidationError error) {
String dateformat = validationConfig.getDateRuleFor(column);
if (dateformat != null && !dateformat.trim().isEmpty()) {
if (!isDate(value, dateformat, true)) {
error.add("validation.message.date.format", dateformat);
}
}
}
private void checkAlphaNumeric(String column, String value, ValidationError error) {
if (validationConfig.getAlphanumericRuleFor(column) != null && validationConfig.getAlphanumericRuleFor(column)) {
if (!matchRegexp(value, "[0-9a-zA-Z]*")) {
error.add("validation.message.alphanumeric");
}
}
}
private void checkRegularExpression(String column, String value, ValidationError error) {
String regexp = validationConfig.getRegexpRuleFor(column); String regexp = validationConfig.getRegexpRuleFor(column);
if (regexp != null && !regexp.trim().isEmpty()) { if (regexp != null && !regexp.trim().isEmpty()) {
if (!matchRegexp(value, regexp)) { add(column, new RegExpValidation(regexp));
error.add("validation.message.regexp", regexp); }
}
String groovy = validationConfig.getGroovyRuleFor(column);
if (groovy != null && !groovy.trim().isEmpty()) {
add(column, new GroovyValidation(groovy));
}
List<String> valueOfRule = validationConfig.getValueOfRuleFor(column);
if (valueOfRule != null && !valueOfRule.isEmpty()) {
add(column, new ValueOfValidation(valueOfRule));
} }
} }
public ValidationError isHeaderValid(String[] headerNames) { public ValidationError isHeaderValid(String[] headerNames) {
ValidationError result = null; ValidationError result = null;
if (validationConfig != null) { if (validationConfig != null) {
@@ -262,7 +213,7 @@ public class Validator {
ValidationError error = ValidationError.withoutLineNumber(); ValidationError error = ValidationError.withoutLineNumber();
for(int i=0; i<headerNamesConfig.length; i++) { for (int i = 0; i < headerNamesConfig.length; i++) {
if (!headerNamesConfig[i].equals(headerNames[i])) { if (!headerNamesConfig[i].equals(headerNames[i])) {
error.add("validation.message.header.match", error.add("validation.message.header.match",
Integer.toString(i), Integer.toString(i),
@@ -277,8 +228,4 @@ public class Validator {
} }
return result; return result;
} }
public void clearScriptCache() {
scriptCache.clear();
}
} }

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 java.util.List;
import static java.util.stream.Collectors.joining;
/**
* Checks if the value is part of a list of values
*/
public class ValueOfValidation implements Validation {
private List<String> values;
public ValueOfValidation(List<String> values) {
this.values = values;
}
@Override
public void check(int row, String value, ValidationError error) {
if (!values.contains(value)) {
String commaSeparated = values.stream().collect(joining(", "));
error.add("validation.message.value.of", value, commaSeparated);
}
}
@Override
public Type getType() {
return Type.VALUE_OF;
}
}

View File

@@ -1,16 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.*?>
<?import javafx.scene.control.Hyperlink?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.Label?> <?import javafx.scene.layout.*?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" spacing="4.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1"> <VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" spacing="4.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<Label text="SmartCSV.fx"> <Label text="SmartCSV.fx">

View File

@@ -1,5 +1,5 @@
application.name = SmartCSV.fx application.name = SmartCSV.fx
application.version = 0.5 application.version = 0.6
# fxml views # fxml views
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml

View File

@@ -1,10 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<GridPane hgap="8.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="8.0" xmlns="http://javafx.com/javafx/8.0.66" xmlns:fx="http://javafx.com/fxml/1"> <GridPane hgap="8.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="8.0" xmlns="http://javafx.com/javafx/8.0.66" xmlns:fx="http://javafx.com/fxml/1">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />

View File

@@ -1,27 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import de.jensd.fx.glyphs.GlyphsStack?> <?import de.jensd.fx.glyphs.*?>
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?> <?import de.jensd.fx.glyphs.materialdesignicons.*?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.Label?> <?import javafx.scene.layout.*?>
<?import javafx.scene.control.Menu?> <?import java.net.URL?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<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.101" 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.101" 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">

View File

@@ -71,6 +71,7 @@ validation.rule.label.groovy = groovy:
validation.rules.active = active validation.rules.active = active
validation.rules.name = rule validation.rules.name = rule
validation.rules.value = value validation.rules.value = value
validation.rule.label.unique = Unique in column:
dialog.validation.rules.title = Validation rules dialog.validation.rules.title = Validation rules
dialog.validation.rules.header = Validation rules of column "{0}" dialog.validation.rules.header = Validation rules of column "{0}"

View File

@@ -80,6 +80,7 @@ validation.rule.label.groovy = groovy:
validation.rules.active = Aktiv validation.rules.active = Aktiv
validation.rules.name = Regel validation.rules.name = Regel
validation.rules.value = Wert validation.rules.value = Wert
validation.rule.label.unique = Einmalig in Spalte:
dialog.validation.rules.title = Pr\u00fcfregeln dialog.validation.rules.title = Pr\u00fcfregeln
dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}" dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"

View File

@@ -1,15 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.CheckBox?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.Label?> <?import javafx.scene.layout.*?>
<?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?>
<?import org.fxmisc.richtext.CodeArea?> <?import org.fxmisc.richtext.CodeArea?>
<?import java.net.URL?> <?import java.net.URL?>
<GridPane hgap="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="600.0" vgap="10.0" xmlns="http://javafx.com/javafx/8.0.101" xmlns:fx="http://javafx.com/fxml/1"> <GridPane hgap="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="600.0" vgap="10.0" xmlns="http://javafx.com/javafx/8.0.101" xmlns:fx="http://javafx.com/fxml/1">
@@ -31,41 +24,46 @@
<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> </rowConstraints>
<children> <children>
<Label text="%validation.rule.label.not_empty" GridPane.columnIndex="1" GridPane.rowIndex="1" /> <Label text="%validation.rule.label.not_empty" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label text="%validation.rule.label.integer" GridPane.columnIndex="1" GridPane.rowIndex="2" /> <Label text="%validation.rule.label.integer" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="%validation.rule.label.double" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <Label text="%validation.rule.label.double" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="%validation.rule.label.minlength" GridPane.columnIndex="1" GridPane.rowIndex="5" /> <Label text="%validation.rule.label.minlength" GridPane.columnIndex="1" GridPane.rowIndex="6" />
<Label text="%validation.rule.label.maxlength" GridPane.columnIndex="1" GridPane.rowIndex="6" /> <Label text="%validation.rule.label.maxlength" GridPane.columnIndex="1" GridPane.rowIndex="7" />
<Label text="%validation.rule.label.dateformat" GridPane.columnIndex="1" GridPane.rowIndex="7" /> <Label text="%validation.rule.label.dateformat" GridPane.columnIndex="1" GridPane.rowIndex="8" />
<Label text="%validation.rule.label.alphanumeric" GridPane.columnIndex="1" GridPane.rowIndex="4" /> <Label text="%validation.rule.label.alphanumeric" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label text="%validation.rule.label.regexp" GridPane.columnIndex="1" GridPane.rowIndex="8" /> <Label text="%validation.rule.label.regexp" GridPane.columnIndex="1" GridPane.rowIndex="9" />
<Label text="%validation.rule.label.value_of" GridPane.columnIndex="1" GridPane.rowIndex="9" /> <Label text="%validation.rule.label.value_of" GridPane.columnIndex="1" GridPane.rowIndex="10" />
<Label text="%validation.rule.label.groovy" GridPane.columnIndex="1" GridPane.rowIndex="10" /> <Label text="%validation.rule.label.groovy" GridPane.columnIndex="1" GridPane.rowIndex="11" />
<CheckBox fx:id="notEmptyRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="1" /> <Label text="%validation.rule.label.unique" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<CheckBox fx:id="integerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<CheckBox fx:id="doublerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<CheckBox fx:id="alphanumericRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<Spinner fx:id="minLengthSpinner" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<Spinner fx:id="maxLengthSpinner" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<TextField fx:id="dateformatRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="7" />
<TextField fx:id="regexpRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="8" />
<TextField fx:id="valueOfRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="9" />
<CodeArea fx:id="groovyRuleTextArea" prefHeight="300.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="10" GridPane.rowSpan="2" />
<CheckBox fx:id="enableNotEmptyRule" mnemonicParsing="false" GridPane.rowIndex="1" /> <CheckBox fx:id="enableNotEmptyRule" mnemonicParsing="false" GridPane.rowIndex="1" />
<CheckBox fx:id="notEmptyRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<CheckBox fx:id="enableIntegerRule" mnemonicParsing="false" GridPane.rowIndex="2" /> <CheckBox fx:id="enableIntegerRule" mnemonicParsing="false" GridPane.rowIndex="2" />
<CheckBox fx:id="integerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<CheckBox fx:id="enableDoubleRule" mnemonicParsing="false" GridPane.rowIndex="3" /> <CheckBox fx:id="enableDoubleRule" mnemonicParsing="false" GridPane.rowIndex="3" />
<CheckBox fx:id="doublerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<CheckBox fx:id="enableAlphanumericRule" mnemonicParsing="false" GridPane.rowIndex="4" /> <CheckBox fx:id="enableAlphanumericRule" mnemonicParsing="false" GridPane.rowIndex="4" />
<CheckBox fx:id="enableMinLengthRule" mnemonicParsing="false" GridPane.rowIndex="5" /> <CheckBox fx:id="alphanumericRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="4" />
<CheckBox fx:id="enableMaxLengthRule" mnemonicParsing="false" GridPane.rowIndex="6" /> <CheckBox fx:id="enableUniqueRule" mnemonicParsing="false" GridPane.rowIndex="5" />
<CheckBox fx:id="enableDateRule" mnemonicParsing="false" GridPane.rowIndex="7" /> <CheckBox fx:id="uniqueRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="5" />
<CheckBox fx:id="enableRegexpRule" mnemonicParsing="false" GridPane.rowIndex="8" /> <CheckBox fx:id="enableMinLengthRule" mnemonicParsing="false" GridPane.rowIndex="6" />
<CheckBox fx:id="enableValueOfRule" mnemonicParsing="false" GridPane.rowIndex="9" /> <Spinner fx:id="minLengthSpinner" GridPane.columnIndex="2" GridPane.rowIndex="6" />
<CheckBox fx:id="enableGroovyRule" mnemonicParsing="false" GridPane.rowIndex="10" /> <CheckBox fx:id="enableMaxLengthRule" mnemonicParsing="false" GridPane.rowIndex="7" />
<Spinner fx:id="maxLengthSpinner" GridPane.columnIndex="2" GridPane.rowIndex="7" />
<CheckBox fx:id="enableDateRule" mnemonicParsing="false" GridPane.rowIndex="8" />
<TextField fx:id="dateformatRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="8" />
<CheckBox fx:id="enableRegexpRule" mnemonicParsing="false" GridPane.rowIndex="9" />
<TextField fx:id="regexpRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="9" />
<CheckBox fx:id="enableValueOfRule" mnemonicParsing="false" GridPane.rowIndex="10" />
<TextField fx:id="valueOfRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="10" />
<CheckBox fx:id="enableGroovyRule" mnemonicParsing="false" GridPane.rowIndex="11" />
<CodeArea fx:id="groovyRuleTextArea" prefHeight="300.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="11" GridPane.rowSpan="2" />
<Label style="-fx-font-weight: bold;" text="%validation.rules.active" /> <Label style="-fx-font-weight: bold;" text="%validation.rules.active" />
<Label style="-fx-font-weight: bold;" text="%validation.rules.name" GridPane.columnIndex="1" /> <Label style="-fx-font-weight: bold;" text="%validation.rules.name" GridPane.columnIndex="1" />
<Label style="-fx-font-weight: bold;" text="%validation.rules.value" GridPane.columnIndex="2" /> <Label style="-fx-font-weight: bold;" text="%validation.rules.value" GridPane.columnIndex="2" />
</children> </children>
<padding> <padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />

View File

@@ -26,13 +26,10 @@
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 org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
/** /**
* unit test for the csv model * unit test for the csv model

View File

@@ -1,13 +1,10 @@
package ninja.javafx.smartcsv.fx.table.model; package ninja.javafx.smartcsv.fx.table.model;
import ninja.javafx.smartcsv.validation.Validator;
import org.hamcrest.Matchers;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*; import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* unit test for row class * unit test for row class

View File

@@ -1,60 +0,0 @@
package ninja.javafx.smartcsv.fx.table.model;
import ninja.javafx.smartcsv.validation.Validator;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* unit test for the value class
*/
public class CSVValueTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// constants
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static final String COLUMN = "COLUMN";
static final String VALUE = "VALUE";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// mocks
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Validator validator = mock(Validator.class);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// subject under test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CSVValue sut;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Before
public void initialize() {
sut = new CSVValue();
sut.setValidator(validator);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Test
public void set_value_calls_validation() {
//setup
sut.setColumn(COLUMN);
// execution
sut.setValue(VALUE);
// assertion
verify(validator).isValid(eq(COLUMN), eq(VALUE), anyInt());
}
}

View File

@@ -70,8 +70,10 @@ public class ValidatorTest {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Test @Test
public void validation() { public void validation() {
System.out.println(column + " " + value + " " + expectedResult + " " + expectedError);
// execution // execution
ValidationError result = sut.isValid(column, value, 0); ValidationError result = sut.isValid(0, column, value);
// assertion // assertion
assertThat(result == null, is(expectedResult)); assertThat(result == null, is(expectedResult));
@@ -112,7 +114,7 @@ public class ValidatorTest {
} }
public static String json(String column, String rule, Object value) { public static String json(String column, String rule, Object value) {
String json = "{\"columns\":{\"" + column + "\":{\"" + rule + "\":"; String json = "{\"headers\": { \"list\": [\""+column+"\"]},\"columns\":{\"" + column + "\":{\"" + rule + "\":";
if (value instanceof String) { if (value instanceof String) {
json += "\""+ value + "\""; json += "\""+ value + "\"";
} else if (value instanceof List) { } else if (value instanceof List) {