25 Commits
0.8 ... 0.9.3

Author SHA1 Message Date
Andreas Billmann
cf9203549b Merge pull request #17 from aoetk/fileencoding
Add the setting changes encoding for CSV file to the preference dialog
2019-10-22 22:36:26 +02:00
AOE Takashi
02b102cfb2 Add the setting changes encoding for CSV file to the preference dialog
(cherry picked from commit 11210b6d8b4584621ef02e7356854ffa9f7f2647)
2019-10-19 23:16:09 +09:00
8e0e1c41c3 update the README.md with the 0.9.2 download link 2019-10-03 21:18:16 +02:00
3ce9ae8edd fixed the main javafx application problem 2019-10-03 21:08:29 +02:00
7c12b7506f upgrade to javafx 13 2019-10-03 18:03:01 +02:00
6fc62006fa upgrade to javafx 12 2019-07-08 20:11:50 +02:00
fdc4f99fd5 updated dependencies 2018-07-08 14:01:13 +02:00
e29d60b9b8 upgraded gradle wrapper 2018-07-08 13:42:43 +02:00
0a4e86c160 fixed the markdown 2018-04-22 09:27:20 +02:00
c07dde8e19 updated the version number and link to the distribution 2018-04-22 09:25:50 +02:00
9b0e3707b7 updated libs and removed fxlauncher as it is not used by customers 2018-04-22 09:18:01 +02:00
a1f6c24bae updatet libraries to the newest versions 2017-03-22 12:00:35 +01:00
c1a671504e added fxlauncher to about dialog 2016-10-06 21:27:09 +02:00
7c3f140491 Merge remote-tracking branch 'remotes/origin/fxlauncher' 2016-10-06 21:07:42 +02:00
16373a033a change updating text in fxlauncher 2016-10-06 21:07:01 +02:00
e9e71b5474 gradle task to rename the fxlauncher.jar and launcher without own ui 2016-10-06 15:33:00 +02:00
48c657b648 fxlauncher without customization 2016-10-06 14:01:52 +02:00
8bd90b47e1 renamed license file 2016-10-06 07:09:50 +02:00
44f36759a6 thx for contribution: Hasan Kara 2016-10-05 15:43:36 +02:00
Andreas Billmann
326e4d954b Merge pull request #14 from haisi/master
Fix typo
2016-10-05 15:35:56 +02:00
Hasan Kara
96446e4e75 Fix typo 2016-10-05 14:51:05 +02:00
Andreas Billmann
5eaf021632 fixed broken tests 2016-09-23 11:14:45 +02:00
Andreas Billmann
ef376d6c61 set constraints when created 2016-09-22 22:09:56 +02:00
Andreas Billmann
2676b523d3 clear groovy field if there is some text in it 2016-09-22 21:49:30 +02:00
Andreas Billmann
7e34ff8c59 fixed NPE when string has no format 2016-09-22 21:35:40 +02:00
29 changed files with 595 additions and 191 deletions

View File

@@ -1,7 +1,7 @@
The MIT License (MIT) The MIT License (MIT)
------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------
Copyright (c) 2015-2016 Andreas Billmann <andreas.billmann@javafx.ninja> Copyright (c) 2015-2019 Andreas Billmann <andreas.billmann@javafx.ninja>

View File

@@ -14,7 +14,7 @@ even in a "normal" CSV editor. So I decided to write this simple JavaFX applicat
[Wiki & Documentation](https://github.com/frosch95/SmartCSV.fx/wiki) [Wiki & Documentation](https://github.com/frosch95/SmartCSV.fx/wiki)
binary distribution of the [latest release (0.8)](https://github.com/frosch95/SmartCSV.fx/releases/download/0.8/SmartCSV.fx-0.8-SNAPSHOT.zip) binary distribution of the [latest release (0.9.2)](https://github.com/frosch95/SmartCSV.fx/releases/download/0.9.2/SmartCSV.fx-0.9.2-SNAPSHOT.zip)
## Talks ## Talks
[Introduction](http://javafx.ninja/talks/introduction/) [Introduction](http://javafx.ninja/talks/introduction/)
@@ -23,7 +23,7 @@ binary distribution of the [latest release (0.8)](https://github.com/frosch95/Sm
### The MIT License (MIT) ### The MIT License (MIT)
Copyright (c) 2015-2016 Andreas Billmann <andreas.billmann@javafx.ninja> Copyright (c) 2015-2019 Andreas Billmann <andreas.billmann@javafx.ninja>

View File

@@ -1,38 +1,39 @@
group 'ninja.javafx' plugins {
version '0.8-SNAPSHOT' id 'idea'
id 'java'
apply plugin: 'java' id 'groovy'
apply plugin: 'groovy' id 'application'
apply plugin:'application' id 'org.openjfx.javafxplugin' version '0.0.8'
apply plugin: 'idea' }
sourceCompatibility = 1.8
mainClassName = 'ninja.javafx.smartcsv.fx.SmartCSV'
repositories { repositories {
mavenCentral() mavenCentral()
jcenter() jcenter()
} }
javafx {
version = "13"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
dependencies { dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12' testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3' testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
testCompile group: 'org.mockito', name: 'mockito-all', version: '1.10.19' compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '3.0.0-beta-3'
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.7' compile group: 'org.springframework', name:'spring-context', version: '5.2.0.RELEASE'
compile group: 'org.springframework', name:'spring-context', version: '4.3.1.RELEASE'
compile group: 'net.sf.supercsv', name: 'super-csv', version: '2.4.0' compile group: 'net.sf.supercsv', name: 'super-csv', version: '2.4.0'
compile group: 'commons-validator', name: 'commons-validator', version: '1.5.1' compile group: 'commons-validator', name: 'commons-validator', version: '1.6'
compile group: 'de.jensd', name: 'fontawesomefx-commons', version: '8.12' compile group: 'de.jensd', name: 'fontawesomefx-commons', version: '11.0'
compile group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.6.3' compile group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.7.0-11'
compile group: 'de.jensd', name: 'fontawesomefx-materialdesignfont', version: '1.6.50' compile group: 'de.jensd', name: 'fontawesomefx-materialdesignfont', version: '1.7.22-11'
compile group: 'de.jensd', name: 'fontawesomefx-materialicons', version: '2.2.0' compile group: 'de.jensd', name: 'fontawesomefx-materialicons', version: '2.2.0-11'
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.11' compile group: 'org.controlsfx', name: 'controlsfx', version: '11.0.0'
compile group: 'com.google.code.gson', name: 'gson', version: '2.7' compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2' compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.0'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2' compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.0'
compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.6.10' compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.10.2'
} }
task wrapper(type: Wrapper) { group 'ninja.javafx'
gradleVersion = '2.14.1' //version required version '0.9.2-SNAPSHOT'
} mainClassName = 'ninja.javafx.smartcsv.Main'

Binary file not shown.

View File

@@ -1,6 +1,5 @@
#Sat Jul 23 09:35:51 CEST 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip

68
gradlew vendored
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env sh
############################################################################## ##############################################################################
## ##
@@ -6,12 +6,30 @@
## ##
############################################################################## ##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Attempt to set APP_HOME
DEFAULT_JVM_OPTS="" # Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@@ -30,6 +48,7 @@ die ( ) {
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false
case "`uname`" in case "`uname`" in
CYGWIN* ) CYGWIN* )
cygwin=true cygwin=true
@@ -40,26 +59,11 @@ case "`uname`" in
MINGW* ) MINGW* )
msys=true msys=true
;; ;;
NONSTOP* )
nonstop=true
;;
esac esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n` MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -150,11 +154,19 @@ if $cygwin ; then
esac esac
fi fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules # Escape application args
function splitJvmOpts() { save () {
JVM_OPTS=("$@") for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
} }
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS APP_ARGS=$(save "$@")
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" # Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

12
gradlew.bat vendored
View File

@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
@@ -49,7 +49,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants @rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%* set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute :execute
@rem Setup the command line @rem Setup the command line

View File

@@ -0,0 +1,10 @@
package ninja.javafx.smartcsv;
import ninja.javafx.smartcsv.fx.SmartCSV;
public class Main {
public static void main(String[] args) {
// workaround for module problem
SmartCSV.main(args);
}
}

View File

@@ -35,6 +35,8 @@ public class CSVConfigurable {
protected CsvPreference csvPreference; protected CsvPreference csvPreference;
protected String fileEncoding;
public CSVConfigurable() { public CSVConfigurable() {
csvPreference = CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE; csvPreference = CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE;
} }
@@ -42,4 +44,9 @@ public class CSVConfigurable {
public void setCsvPreference(CsvPreference csvPreference) { public void setCsvPreference(CsvPreference csvPreference) {
this.csvPreference = csvPreference; this.csvPreference = csvPreference;
} }
public void setFileEncoding(String fileEncoding) {
this.fileEncoding = fileEncoding;
}
} }

View File

@@ -34,6 +34,7 @@ import org.supercsv.io.ICsvMapReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map; import java.util.Map;
/** /**
@@ -48,7 +49,8 @@ public class CSVFileReader extends CSVConfigurable implements FileReader<CSVMode
ICsvMapReader mapReader = null; ICsvMapReader mapReader = null;
try { try {
mapReader = new CsvMapReader(new java.io.FileReader(file.getAbsoluteFile()), csvPreference); mapReader = new CsvMapReader(new java.io.FileReader(file.getAbsoluteFile(), Charset.forName(fileEncoding)),
csvPreference);
model = new CSVModel(); model = new CSVModel();
// the header columns are used as the keys to the Map // the header columns are used as the keys to the Map

View File

@@ -34,6 +34,7 @@ import org.supercsv.io.ICsvMapWriter;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Map; import java.util.Map;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
@@ -53,7 +54,8 @@ public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smart
public void write(File filename) throws IOException { public void write(File filename) throws IOException {
ICsvMapWriter mapWriter = null; ICsvMapWriter mapWriter = null;
try { try {
mapWriter = new CsvMapWriter(new FileWriter(filename.getAbsolutePath()), csvPreference); mapWriter = new CsvMapWriter(new FileWriter(filename.getAbsolutePath(), Charset.forName(fileEncoding)),
csvPreference);
mapWriter.writeHeader(model.getHeader()); mapWriter.writeHeader(model.getHeader());
for(CSVRow row: model.getRows()) { for(CSVRow row: model.getRows()) {

View File

@@ -11,7 +11,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
/** /**
* This class stores files and there state * This class stores files and their state
* @author abi * @author abi
*/ */
public class FileStorage<E> { public class FileStorage<E> {
@@ -26,7 +26,7 @@ public class FileStorage<E> {
private BooleanProperty fileChanged = new SimpleBooleanProperty(true); private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
private ObjectProperty<File> file = new SimpleObjectProperty<>(); private ObjectProperty<File> file = new SimpleObjectProperty<>();
private ObjectProperty<E> content = new SimpleObjectProperty<E>(); private ObjectProperty<E> content = new SimpleObjectProperty<>();
public boolean isFileChanged() { public boolean isFileChanged() {
return fileChanged.get(); return fileChanged.get();

View File

@@ -54,8 +54,7 @@ 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.fx.validation.ValidationEditorController;
import ninja.javafx.smartcsv.preferences.PreferencesFileReader; import ninja.javafx.smartcsv.preferences.*;
import ninja.javafx.smartcsv.preferences.PreferencesFileWriter;
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration; import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
import ninja.javafx.smartcsv.validation.ValidationError; import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.ValidationFileReader; import ninja.javafx.smartcsv.validation.ValidationFileReader;
@@ -68,6 +67,7 @@ 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.nio.charset.Charset;
import java.util.Optional; import java.util.Optional;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@@ -93,6 +93,13 @@ public class SmartCSVController extends FXMLController {
".SmartCSV.fx" + ".SmartCSV.fx" +
File.separator + "" + File.separator + "" +
"preferences.json"); "preferences.json");
private static final File ENCODING_FILE = new File(System.getProperty("user.home") +
File.separator +
".SmartCSV.fx" +
File.separator +
"encoding.json");
public static final String CSV_FILTER_TEXT = "CSV files (*.csv)"; public static final String CSV_FILTER_TEXT = "CSV files (*.csv)";
public static final String CSV_FILTER_EXTENSION = "*.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_TEXT = "JSON files (*.json)";
@@ -213,6 +220,7 @@ public class SmartCSVController extends FXMLController {
private FileStorage<CSVModel> currentCsvFile = new FileStorage<>(csvFileReader, csvFileWriter); private FileStorage<CSVModel> currentCsvFile = new FileStorage<>(csvFileReader, csvFileWriter);
private FileStorage<ValidationConfiguration> currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter()); private FileStorage<ValidationConfiguration> currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter());
private FileStorage<CsvPreference> csvPreferenceFile = new FileStorage<>(new PreferencesFileReader(), new PreferencesFileWriter()); private FileStorage<CsvPreference> csvPreferenceFile = new FileStorage<>(new PreferencesFileReader(), new PreferencesFileWriter());
private FileStorage<String> fileEncodingFile = new FileStorage<>(new EncodingFileReader(), new EncodingFileWriter());
private ListChangeListener<ValidationError> errorListListener = c -> tableView.refresh(); private ListChangeListener<ValidationError> errorListListener = c -> tableView.refresh();
private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener); private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener);
@@ -238,10 +246,25 @@ public class SmartCSVController extends FXMLController {
bindConfigFileName(); bindConfigFileName();
csvPreferenceFile.setFile(PREFERENCES_FILE); csvPreferenceFile.setFile(PREFERENCES_FILE);
fileEncodingFile.setFile(ENCODING_FILE);
loadCsvPreferencesFromFile(); loadCsvPreferencesFromFile();
} }
private void loadEncodingFromFile() {
if (fileEncodingFile.getFile().exists()) {
useLoadFileService(fileEncodingFile, event -> setFileEncoding(fileEncodingFile.getContent()));
} else {
setFileEncoding(Charset.defaultCharset().name());
}
}
private void setFileEncoding(String content) {
preferencesController.setFileEncoding(content);
csvFileReader.setFileEncoding(content);
csvFileWriter.setFileEncoding(content);
}
private void setupErrorSideBar(ResourceBundle resourceBundle) { private void setupErrorSideBar(ResourceBundle resourceBundle) {
errorSideBar = new ErrorSideBar(resourceBundle); errorSideBar = new ErrorSideBar(resourceBundle);
errorSideBar.selectedValidationErrorProperty().addListener((observable, oldValue, newValue) -> { errorSideBar.selectedValidationErrorProperty().addListener((observable, oldValue, newValue) -> {
@@ -345,8 +368,29 @@ public class SmartCSVController extends FXMLController {
CsvPreference csvPreference = preferencesController.getCsvPreference(); CsvPreference csvPreference = preferencesController.getCsvPreference();
setCsvPreference(csvPreference); setCsvPreference(csvPreference);
saveCsvPreferences(csvPreference); saveCsvPreferences(csvPreference);
String fileEncoding = CharsetHelper.getCharsetName(preferencesController.getFileEncoding());
setFileEncoding(fileEncoding);
saveFileEncoding(fileEncoding);
} else { } else {
preferencesController.setCsvPreference(csvPreferenceFile.getContent()); preferencesController.setCsvPreference(csvPreferenceFile.getContent());
preferencesController.setFileEncoding(fileEncodingFile.getContent());
}
}
private void saveFileEncoding(String fileEncoding) {
try {
createFileEncodingFile();
fileEncodingFile.setContent(fileEncoding);
useSaveFileService(fileEncodingFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private void createFileEncodingFile() throws IOException {
if (!fileEncodingFile.getFile().exists()) {
createPreferencesFileFolder();
fileEncodingFile.getFile().createNewFile();
} }
} }
@@ -492,9 +536,13 @@ public class SmartCSVController extends FXMLController {
private void loadCsvPreferencesFromFile() { private void loadCsvPreferencesFromFile() {
if (csvPreferenceFile.getFile().exists()) { if (csvPreferenceFile.getFile().exists()) {
useLoadFileService(csvPreferenceFile, event -> setCsvPreference(csvPreferenceFile.getContent())); useLoadFileService(csvPreferenceFile, event -> {
setCsvPreference(csvPreferenceFile.getContent());
loadEncodingFromFile();
});
} else { } else {
setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE); setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
loadEncodingFromFile();
} }
} }

View File

@@ -39,6 +39,7 @@ import org.springframework.stereotype.Component;
import org.supercsv.prefs.CsvPreference; import org.supercsv.prefs.CsvPreference;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
@@ -66,6 +67,9 @@ public class PreferencesController extends FXMLController {
@FXML @FXML
private ComboBox<String> quoteMode; private ComboBox<String> quoteMode;
@FXML
private ComboBox<String> fileEncoding;
private String endOfLineSymbols; private String endOfLineSymbols;
private BooleanProperty valid = new SimpleBooleanProperty(true); private BooleanProperty valid = new SimpleBooleanProperty(true);
@@ -80,6 +84,7 @@ public class PreferencesController extends FXMLController {
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
quoteMode.getItems().addAll("normal", "always", "column"); quoteMode.getItems().addAll("normal", "always", "column");
fileEncoding.getItems().addAll(Charset.availableCharsets().keySet());
UnaryOperator<TextFormatter.Change> allowOnlyOneCharacter = change -> { UnaryOperator<TextFormatter.Change> allowOnlyOneCharacter = change -> {
if (change.isContentChange()) { if (change.isContentChange()) {
@@ -117,6 +122,14 @@ public class PreferencesController extends FXMLController {
.build(); .build();
} }
public void setFileEncoding(String fileEncoding) {
this.fileEncoding.setValue(fileEncoding);
}
public String getFileEncoding() {
return fileEncoding.getValue();
}
public boolean getValid() { public boolean getValid() {
return valid.get(); return valid.get();
} }

View File

@@ -35,8 +35,8 @@ import ninja.javafx.smartcsv.fx.FXMLController;
import ninja.javafx.smartcsv.validation.configuration.*; import ninja.javafx.smartcsv.validation.configuration.*;
import org.fxmisc.richtext.CodeArea; import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory; import org.fxmisc.richtext.LineNumberFactory;
import org.fxmisc.richtext.StyleSpans; import org.fxmisc.richtext.model.StyleSpans;
import org.fxmisc.richtext.StyleSpansBuilder; import org.fxmisc.richtext.model.StyleSpansBuilder;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -298,6 +298,7 @@ public class ValidationEditorController extends FXMLController {
Constraints constraints = config.getConstraints(); Constraints constraints = config.getConstraints();
if (constraints == null) { if (constraints == null) {
constraints = new Constraints(); constraints = new Constraints();
config.setConstraints(constraints);
} }
if (enableNotEmptyRule.isSelected()) { if (enableNotEmptyRule.isSelected()) {
@@ -442,7 +443,7 @@ public class ValidationEditorController extends FXMLController {
ruleEnabled.setSelected(false); ruleEnabled.setSelected(false);
} else { } else {
ruleEnabled.setSelected(true); ruleEnabled.setSelected(true);
rule.replaceText(0, 0, value); rule.replaceText(0, rule.getLength(), value);
} }
} }

View File

@@ -0,0 +1,44 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 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.preferences;
import java.nio.charset.Charset;
/**
* Helper class for getting charset's name
*/
public class CharsetHelper {
public static String getCharsetName(String name) {
try {
return Charset.forName(name).name();
} catch (Exception e) {
return Charset.defaultCharset().name();
}
}
}

View File

@@ -0,0 +1,62 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 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.preferences;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
* file reader for the file encoding
*/
public class EncodingFileReader implements FileReader<String> {
private String fileEncoding;
public EncodingFileReader() {
fileEncoding = Charset.defaultCharset().name();
}
@Override
public String getContent() {
return fileEncoding;
}
@Override
public void read(File filename) throws IOException {
Map settings = new GsonBuilder().create().fromJson(new java.io.FileReader(filename), HashMap.class);
if (settings != null) {
fileEncoding = CharsetHelper.getCharsetName(settings.get("fileEncoding").toString());
}
}
}

View File

@@ -0,0 +1,59 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 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.preferences;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileWriter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
/**
* Save the file encoding to configuration file
*/
public class EncodingFileWriter implements FileWriter<String> {
private String fileEncoding;
@Override
public void setContent(String fileEncoding) {
this.fileEncoding = fileEncoding;
}
@Override
public void write(File filename) throws IOException {
Map<String, String> encodings = new HashMap<>();
encodings.put("fileEncoding", CharsetHelper.getCharsetName(fileEncoding));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Files.write(filename.toPath(), gson.toJson(encodings).getBytes());
}
}

View File

@@ -1,5 +1,7 @@
package ninja.javafx.smartcsv.validation; package ninja.javafx.smartcsv.validation;
import java.text.SimpleDateFormat;
/** /**
* @author abi * @author abi
*/ */
@@ -31,6 +33,13 @@ public class ValidationFormatHelper {
format = format.replace("%j", "DDD"); format = format.replace("%j", "DDD");
format = format.replace("%U", "ww"); format = format.replace("%U", "ww");
return format; return format;
} else {
try {
new SimpleDateFormat(format);
return format;
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
} }
} }
return defaultFormat; return defaultFormat;

View File

@@ -133,6 +133,15 @@ public class Validator {
validationMap.put(validation.getType(), validation); validationMap.put(validation.getType(), validation);
} }
private void remove(String column, Validation.Type type) {
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap == null) {
validationMap = new HashMap<>();
columnValidationMap.put(column, validationMap);
}
validationMap.remove(type);
}
private void clear(String column) { private void clear(String column) {
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column); Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap != null) { if (validationMap != null) {
@@ -172,12 +181,12 @@ public class Validator {
} }
if (column.getType() == DATE) { if (column.getType() == DATE) {
String format = dateFormat(column.getFormat(), "YYYY-MM-DD"); String format = dateFormat(column.getFormat(), "yyyy-MM-dd");
add(column.getName(), new DateValidation(format)); add(column.getName(), new DateValidation(format));
} }
if (column.getType() == DATETIME) { if (column.getType() == DATETIME) {
String format = dateFormat(column.getFormat(), "YYYY-MM-DDThh:mm:ssZ"); String format = dateFormat(column.getFormat(), "yyyy-MM-ddThh:mm:ssZ");
add(column.getName(), new DateValidation(format)); add(column.getName(), new DateValidation(format));
} }
@@ -186,6 +195,10 @@ public class Validator {
add(column.getName(), new DateValidation(format)); add(column.getName(), new DateValidation(format));
} }
if (column.getType() == STRING && column.getFormat() == null) {
remove(column.getName(), Validation.Type.STRING);
} else {
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(EMAIL.getExternalValue())) { if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(EMAIL.getExternalValue())) {
add(column.getName(), new EmailValidation()); add(column.getName(), new EmailValidation());
} }
@@ -202,8 +215,6 @@ public class Validator {
add(column.getName(), new BinaryValidation()); add(column.getName(), new BinaryValidation());
} }
if (column.getType() == STRING && column.getFormat() == null) {
columnValidationMap.get(column).remove(Validation.Type.STRING);
} }
} }

View File

@@ -1,21 +1,18 @@
<?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.Hyperlink?>
<?import javafx.scene.layout.*?> <?import javafx.scene.control.Label?>
<?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.76-ea" xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<Label text="SmartCSV.fx">
<font>
<Font size="18.0" />
</font>
<VBox.margin>
<Insets top="8.0" />
</VBox.margin>
</Label>
<Label text="A simple JavaFX application to load, save and edit a CSV file and provide a JSON configuration for columns " wrapText="true" />
<Label text="to check the values in the columns." />
<Label text="Thanks for contributions:"> <Label text="Thanks for contributions:">
<font> <font>
<Font size="18.0" /> <Font size="18.0" />
@@ -25,6 +22,7 @@
</VBox.margin> </VBox.margin>
</Label> </Label>
<Label text="AOE Takashi (https://github.com/aoetk)" /> <Label text="AOE Takashi (https://github.com/aoetk)" />
<Label text="Hasan Kara (https://github.com/haisi)" />
<Label text="3rd party software"> <Label text="3rd party software">
<VBox.margin> <VBox.margin>
<Insets top="8.0" /> <Insets top="8.0" />
@@ -41,17 +39,17 @@
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" /> <ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" /> <RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="junit" /> <Label text="junit" />
@@ -91,7 +89,7 @@
<Font size="18.0" /> <Font size="18.0" />
</font> </font>
</Label> </Label>
<TextArea editable="false" prefHeight="200.0" prefWidth="200.0" text="Copyright (c) 2015-2016 Andreas Billmann &lt;andreas.billmann@javafx.ninja&gt;&#10;&#10;Permission is hereby granted, free of charge, to any person obtaining a copy&#10;of this software and associated documentation files (the &quot;Software&quot;), to deal&#10;in the Software without restriction, including without limitation the rights&#10;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#10;copies of the Software, and to permit persons to whom the Software is&#10;furnished to do so, subject to the following conditions:&#10;&#10;The above copyright notice and this permission notice shall be included in&#10;all copies or substantial portions of the Software.&#10;&#10;&#10;&#10;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#10;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#10;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#10;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#10;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#10;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#10;THE SOFTWARE." wrapText="true" /> <TextArea editable="false" prefHeight="200.0" prefWidth="200.0" text="Copyright (c) 2015-2019 Andreas Billmann &lt;andreas.billmann@javafx.ninja&gt;&#10;&#10;Permission is hereby granted, free of charge, to any person obtaining a copy&#10;of this software and associated documentation files (the &quot;Software&quot;), to deal&#10;in the Software without restriction, including without limitation the rights&#10;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#10;copies of the Software, and to permit persons to whom the Software is&#10;furnished to do so, subject to the following conditions:&#10;&#10;The above copyright notice and this permission notice shall be included in&#10;all copies or substantial portions of the Software.&#10;&#10;&#10;&#10;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#10;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#10;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#10;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#10;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#10;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#10;THE SOFTWARE." wrapText="true" />
</children> </children>
<opaqueInsets> <opaqueInsets>
<Insets /> <Insets />

View File

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

View File

@@ -14,6 +14,7 @@
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" /> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label text="%preferences.quoteChar" /> <Label text="%preferences.quoteChar" />
@@ -26,6 +27,8 @@
<CheckBox fx:id="ignoreEmptyLines" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="3" /> <CheckBox fx:id="ignoreEmptyLines" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="%preferences.quoteMode" GridPane.rowIndex="4" /> <Label text="%preferences.quoteMode" GridPane.rowIndex="4" />
<ComboBox fx:id="quoteMode" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" /> <ComboBox fx:id="quoteMode" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label text="%preferences.fileEncoding" GridPane.rowIndex="5" />
<ComboBox fx:id="fileEncoding" editable="true" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="5" />
</children> </children>
<padding> <padding>
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" /> <Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />

View File

@@ -41,6 +41,7 @@ preferences.delimiterChar = Delimiter character:
preferences.ignoreEmptyLines = Ignore empty lines: preferences.ignoreEmptyLines = Ignore empty lines:
preferences.surroundingSpacesNeedQuotes = Surrounding spaces need quotes: preferences.surroundingSpacesNeedQuotes = Surrounding spaces need quotes:
preferences.quoteMode = Quote mode: preferences.quoteMode = Quote mode:
preferences.fileEncoding = File encoding:
# validaton messages # validaton messages
validation.message.not.empty = should not be empty validation.message.not.empty = should not be empty

View File

@@ -50,6 +50,7 @@ preferences.delimiterChar = Trennzeichen:
preferences.ignoreEmptyLines = Leere Zeilen ignorieren: preferences.ignoreEmptyLines = Leere Zeilen ignorieren:
preferences.surroundingSpacesNeedQuotes = Leerzeichen einfassen: preferences.surroundingSpacesNeedQuotes = Leerzeichen einfassen:
preferences.quoteMode = Einfassungsmodus: preferences.quoteMode = Einfassungsmodus:
preferences.fileEncoding = Dateicodierung:
# validaton messages # validaton messages
validation.message.not.empty = Darf nicht leer sein. validation.message.not.empty = Darf nicht leer sein.

View File

@@ -0,0 +1,56 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 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.preferences;
import org.junit.jupiter.api.Test;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.*;
public class CharsetHelperTest {
@Test
public void getCharsetName_known_charset() {
String result = CharsetHelper.getCharsetName("UTF-16");
assertEquals(StandardCharsets.UTF_16.name(), result);
}
@Test
public void getCharsetName_unknown_charset() {
String result = CharsetHelper.getCharsetName("foobar");
assertEquals(StandardCharsets.UTF_8.name(), result);
}
@Test
public void getCharsetName_null_charset() {
String result = CharsetHelper.getCharsetName(null);
assertEquals(StandardCharsets.UTF_8.name(), result);
}
}

View File

@@ -82,7 +82,7 @@ public class HeaderValidationTest {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Before @Before
public void initialize() { public void initialize() {
sut = new Validator(config); sut = new Validator(config, new TestColumnValueProvider());
} }
@@ -116,7 +116,21 @@ public class HeaderValidationTest {
} }
public static String json(String... headerNames) { public static String json(String... headerNames) {
return "{\"headers\":{\"list\":[" + asList(headerNames).stream().collect(joining(", ")) + "]}}";
String json = "{ \"fields\": [";
for (String headerName: headerNames) {
json += "{\"name\" : \""+headerName+"\" },";
}
if (headerNames != null && headerNames.length > 0) {
json = json.substring(0, json.length() - 1);
}
json += "]}";
return json;
} }
} }

View File

@@ -0,0 +1,18 @@
package ninja.javafx.smartcsv.validation;
import ninja.javafx.smartcsv.fx.table.model.ColumnValueProvider;
/**
* @author abi
*/
public class TestColumnValueProvider implements ColumnValueProvider {
@Override
public String getValue(int row, String column) {
return null;
}
@Override
public int getNumberOfRows() {
return 0;
}
}

View File

@@ -26,8 +26,7 @@ public class ValidatorTest {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameters // parameters
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private ValidationConfiguration config; private String config;
private String column;
private String value; private String value;
private Boolean expectedResult; private Boolean expectedResult;
private ValidationMessage expectedError; private ValidationMessage expectedError;
@@ -43,14 +42,10 @@ public class ValidatorTest {
// parameterized constructor // parameterized constructor
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public ValidatorTest(String config, public ValidatorTest(String config,
String column,
String value, String value,
Boolean expectedResult, Boolean expectedResult,
ValidationMessage expectedError) { ValidationMessage expectedError) {
System.out.println(config); this.config = config;
Gson gson = new GsonBuilder().create();
this.config = gson.fromJson(config, ValidationConfiguration.class);
this.column = column;
this.value = value; this.value = value;
this.expectedResult = expectedResult; this.expectedResult = expectedResult;
this.expectedError = expectedError; this.expectedError = expectedError;
@@ -62,7 +57,9 @@ public class ValidatorTest {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Before @Before
public void initialize() { public void initialize() {
sut = new Validator(config); Gson gson = new GsonBuilder().create();
ValidationConfiguration validationConfiguration = gson.fromJson(config, ValidationConfiguration.class);
sut = new Validator(validationConfiguration, new TestColumnValueProvider());
} }
@@ -71,10 +68,14 @@ public class ValidatorTest {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Test @Test
public void validation() { public void validation() {
System.out.println(column + " " + value + " " + expectedResult + " " + expectedError); System.out.println("===================================================");
System.out.println(config);
System.out.println(value + " " + expectedResult + " " + expectedError);
System.out.println("===================================================\n");
// execution // execution
ValidationError result = sut.isValid(0, column, value); ValidationError result = sut.isValid(0, "column", value);
// assertion // assertion
assertThat(result == null, is(expectedResult)); assertThat(result == null, is(expectedResult));
@@ -89,33 +90,49 @@ public class ValidatorTest {
@Parameterized.Parameters @Parameterized.Parameters
public static Collection validationConfigurations() { public static Collection validationConfigurations() {
return asList(new Object[][] { return asList(new Object[][] {
{ json("column", "not empty", true), "column", "value", true, null }, { constraintsJSON("string", "required", true), "value", true, null },
{ json("column", "not empty", true), "column", "", false, new ValidationMessage("validation.message.not.empty") }, { constraintsJSON("string", "required", true), "", false, new ValidationMessage("validation.message.not.empty") },
{ json("column", "not empty", true), "column", null, false, new ValidationMessage("validation.message.not.empty") }, { constraintsJSON("string", "required", true), null, false, new ValidationMessage("validation.message.not.empty") },
{ json("column", "integer", true), "column", "999", true, null }, { constraintsJSON("integer", null, true), "999", true, null },
{ json("column", "integer", true), "column", "a", false, new ValidationMessage("validation.message.integer") }, { constraintsJSON("integer", null, true), "a", false, new ValidationMessage("validation.message.integer") },
{ json("column", "double", true), "column", "999", true, null }, { constraintsJSON("number", null, true), "999", true, null },
{ json("column", "double", true), "column", "999.000", true, null }, { constraintsJSON("number", null, true), "999.000", true, null },
{ json("column", "double", true), "column", "a", false, new ValidationMessage("validation.message.double") }, { constraintsJSON("number", null, true), "a", false, new ValidationMessage("validation.message.double") },
{ json("column", "minlength", 2), "column", "12", true, null }, { constraintsJSON("string", "minLength", 2), "12", true, null },
{ json("column", "minlength", 2), "column", "1", false, new ValidationMessage("validation.message.min.length", "2") }, { constraintsJSON("string", "minLength", 2), "1", false, new ValidationMessage("validation.message.min.length", "2") },
{ json("column", "maxlength", 2), "column", "12", true, null }, { constraintsJSON("string", "maxLength", 2), "12", true, null },
{ json("column", "maxlength", 2), "column", "123", false, new ValidationMessage("validation.message.max.length", "2") }, { constraintsJSON("string", "maxLength", 2), "123", false, new ValidationMessage("validation.message.max.length", "2") },
{ json("column", "date", "yyyyMMdd"), "column", "20151127", true, null }, { constraintsJSON("string", "pattern", "[a-z]*"), "abc", true, null },
{ json("column", "date", "yyyyMMdd"), "column", "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyyMMdd") }, { constraintsJSON("string", "pattern", "[a-z]*"), "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") },
{ json("column", "alphanumeric", true), "column", "abcABC123", true, null }, { constraintsJSON("string", "enum", asList("a","b","c","d","e")), "c", true, null },
{ json("column", "alphanumeric", true), "column", "-abcABC123", false, new ValidationMessage("validation.message.alphanumeric") }, { constraintsJSON("string", "enum", asList("a","b","c","d","e")), "f", false, new ValidationMessage("validation.message.value.of", "f", "a, b, c, d, e") },
{ json("column", "regexp", "[a-z]*"), "column", "abc", true, null },
{ json("column", "regexp", "[a-z]*"), "column", "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") }, { formatJSON("string", null), "some string", true, null },
{ json("column", "groovy", "value.contains('a')? 'true' : 'no a inside'"), "column", "abcdef", true, null }, { formatJSON("string", "email"), "test@javafx.ninja", true, null },
{ json("column", "groovy", "value.contains('a')? 'true' : 'no a inside'"), "column", "bcdefg", false, new ValidationMessage("no a inside") }, { formatJSON("string", "email"), "wrong email", false, new ValidationMessage("validation.message.email") },
{ json("column", "value of", asList("a","b","c","d","e")), "column", "c", true, null }, { formatJSON("string", "uri"), "http://www.javafx.ninja", true, null },
{ json("column", "value of", asList("a","b","c","d","e")), "column", "f", false, new ValidationMessage("validation.message.value.of", "f", "a, b, c, d, e") }, { formatJSON("string", "uri"), "!$%&/()", false, new ValidationMessage("validation.message.uri") },
{ formatJSON("string", "binary"), "dGVzdA==", true, null },
{ formatJSON("string", "binary"), "no binary", false, new ValidationMessage("validation.message.binary") },
{ formatJSON("string", "uuid"), "6ba7b810-9dad-11d1-80b4-00c04fd430c8", true, null },
{ formatJSON("string", "uuid"), "no uuid", false, new ValidationMessage("validation.message.uuid") },
{ formatJSON("date", null), "2015-11-27", true, null },
{ formatJSON("date", null), "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyy-MM-dd") },
{ formatJSON("date", "yyyyMMdd"), "20151127", true, null },
{ formatJSON("date", "yyyyMMdd"), "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyyMMdd") },
{ customAttributeJSON( "groovy", "value.contains('a')? 'true' : 'no a inside'"), "abcdef", true, null },
{ customAttributeJSON( "groovy", "value.contains('a')? 'true' : 'no a inside'"), "bcdefg", false, new ValidationMessage("no a inside") },
}); });
} }
public static String json(String column, String rule, Object value) { public static String constraintsJSON(String type, String constraint, Object value) {
String json = "{\"headers\": { \"list\": [\""+column+"\"]},\"columns\":{\"" + column + "\":{\"" + rule + "\":"; String json = "{\"fields\": [ { \"name\": \"column\", \"type\" : \"" + type +"\"";
if (constraint != null) {
json += ", \"constraints\": { \"" + constraint + "\":";
if (value instanceof String) { if (value instanceof String) {
json += "\"" + value + "\""; json += "\"" + value + "\"";
} else if (value instanceof List) { } else if (value instanceof List) {
@@ -124,7 +141,29 @@ public class ValidatorTest {
} else { } else {
json += value; json += value;
} }
json += "}}}"; json += "}";
}
json += "}]}";
return json;
}
public static String formatJSON(String type, String format) {
String json = "{\"fields\": [ { \"name\": \"column\", \"type\" : \"" + type +"\"";
if (format != null) {
json += ", \"format\": \"" + format + "\"";
}
json += "}]}";
return json;
}
public static String customAttributeJSON(String attribute, String value) {
String json = "{\"fields\": [ { \"name\": \"column\", \"type\" : \"string\"";
if (attribute != null) {
json += ", \""+attribute+"\": \"" + value + "\"";
}
json += "}]}";
return json; return json;
} }
} }