73 Commits
0.8 ... master

Author SHA1 Message Date
55ed382203 Update JDK version from 17 to 25 in workflow 2025-10-20 21:25:04 +02:00
81d75a995b Merge pull request #33 from frosch95/frosch95-patch-1
Update latest release version in README
2025-10-20 21:23:25 +02:00
f5ab096452 Update latest release version in README 2025-10-20 21:22:02 +02:00
18335b9280 Update dependencies and Gradle wrapper; bump JavaFX to 25 and Groovy to 5.0.2 2025-10-20 21:16:21 +02:00
4e216b4792 Merge pull request #32 from frosch95/fix_enter_bug
When pressing enter leave the editing mode
2022-10-22 21:27:37 +02:00
3980e2951f Version 1.4.0 2022-10-22 21:23:40 +02:00
1b39c9a08e When pressing enter leave the editing mode and commit the new value.
Also reset the value when cancel the edit mode.
2022-10-22 21:21:54 +02:00
0db16c0328 Merge pull request #30 from frosch95/file_has_changed_dialog
When a new file is opened check first if there are unsafed changes and show a warning dialog.
2022-10-19 13:51:30 +02:00
bec55b6119 When a new file is opened check first if there are unsafed changes and show a warning dialog. 2022-10-19 13:48:09 +02:00
7dac3ce011 Merge pull request #29 from frosch95/dragndrop
Support for Drag'n'Drop
2022-10-19 12:49:36 +02:00
449f929f08 Support for drag'n'drop 2022-10-19 12:34:55 +02:00
9e3561fedb fix release link 2022-10-15 13:59:48 +02:00
9c1b110bfd Merge pull request #28 from frosch95/total_number_of_lines
total number of lines
2022-10-15 13:47:55 +02:00
398219a897 total number of lines 2022-10-15 13:41:31 +02:00
Andreas Billmann
a79dde5421 Merge pull request #24 from frosch95/switch_to_fastcsv
switch to fastcsv
2021-12-10 00:54:12 +01:00
fb234fa50e fix tests 2021-12-10 00:51:38 +01:00
43856dffab switch to fastcsv as supercsv is not maintaned anymore 2021-12-10 00:30:59 +01:00
8cecca2172 update the thanks section 2021-11-23 06:19:33 +01:00
Andreas Billmann
35f395d44a Update README.md 2021-11-22 22:22:55 +01:00
Andreas Billmann
9961373d76 Update version 2021-11-22 22:11:04 +01:00
Andreas Billmann
fd6938fa80 Merge pull request #23 from apixandru/loader_exceptions
#22 don't ignore loading exceptions
2021-11-22 22:08:58 +01:00
Alexandru
78f3f5909e #22 don't ignore loading exceptions 2021-10-29 05:05:13 -07:00
Andreas Billmann
d572dcdeed JDK17 2021-10-02 09:26:59 +02:00
af6ce56f71 changed to jdk 17 LTS 2021-10-02 07:28:16 +02:00
2f692352b7 remove travis badge 2020-11-02 22:02:45 +01:00
5b59c76200 try to build on ubuntu 2020-11-02 22:00:20 +01:00
7e40daa1e5 remove branch dependencies 2020-11-02 21:54:59 +01:00
2da843e1e2 added gthub action badge 2020-11-02 21:45:28 +01:00
d1ffd09941 use github action 2020-11-02 21:42:57 +01:00
Andreas Billmann
4c29d29bf5 Update README.md 2020-10-06 02:19:28 +02:00
Andreas Billmann
c4f91d94f1 Merge pull request #18 from frosch95/update-dependencies
update the dependencies
2020-10-02 23:43:52 +02:00
8c43c5a1de update the dependencies 2020-10-02 23:40:31 +02:00
187002997c version 1.0.0 2019-10-24 21:55:05 +02:00
aa7e38c613 closes #10
logo for the app
2019-10-24 21:51:42 +02:00
13a41468d4 removed unused property 2019-10-23 06:03:55 +02:00
f41979960b migrated all test to junit 5 2019-10-23 05:57:06 +02:00
a7fce854ca file storage test 2019-10-23 05:08:49 +02:00
4f40418aea Merge remote-tracking branch 'origin/master' 2019-10-23 02:05:44 +02:00
d7c821d1fe removed some code smells 2019-10-23 02:04:57 +02:00
Andreas Billmann
49f8003f97 Update README.md 2019-10-23 01:23:20 +02:00
Andreas Billmann
5f8383c6a1 Update README.md 2019-10-23 01:09:46 +02:00
03dcf20229 permission access for travis 2019-10-23 00:55:21 +02:00
543125812a enable travis-ci 2019-10-23 00:50:43 +02:00
c52f6c0bc8 upgraded the test libraries 2019-10-23 00:36:08 +02:00
422bd73bad Merge branch 'master' of https://github.com/frosch95/SmartCSV.fx 2019-10-23 00:20:49 +02:00
e6672834fb allow redordering of columns 2019-10-23 00:10:19 +02:00
8e0ea66552 build for java 11 and updated license text 2019-10-22 23:19:51 +02:00
Andreas Billmann
bf476308a2 Update README.md 2019-10-22 23:11:48 +02:00
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
89 changed files with 1261 additions and 535 deletions

21
.github/workflows/build-and-test.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Build and Test with Gradle
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 25
uses: actions/setup-java@v1
with:
java-version: 25
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Test with Gradle
run: ./gradlew test

View File

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

View File

@@ -1,29 +1,30 @@
# SmartCSV.fx
##Description
![Build and Test](https://github.com/frosch95/SmartCSV.fx/workflows/Build%20and%20Test%20with%20Gradle/badge.svg) ![GitHub All Releases](https://img.shields.io/github/downloads/frosch95/SmartCSV.fx/total) ![GitHub](https://img.shields.io/github/license/frosch95/SmartCSV.fx) ![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/frosch95/SmartCSV.fx?label=version) ![GitHub Release Date](https://img.shields.io/github/release-date/frosch95/SmartCSV.fx)
## Description
A simple JavaFX application to load, save and edit a CSV file and provide a [JSON Table Schema](http://specs.frictionlessdata.io/json-table-schema/) for columns to check the values in the columns.
##Motivation
## Motivation
At work I have the need to fix wrong CSV files from customers. It is hard to find the errors and fix them in a texteditor,
even in a "normal" CSV editor. So I decided to write this simple JavaFX application.
##Video
## Video
[![short video about the application](http://img.youtube.com/vi/eUh_WLx1OwI/0.jpg)](https://youtu.be/eUh_WLx1OwI)
##Links
## Links
[GitHub Page](http://frosch95.github.io/SmartCSV.fx/)
[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 (1.5.0)](https://github.com/frosch95/SmartCSV.fx/releases/download/1.5.0/SmartCSV.fx-1.5.0.zip)
##Talks
## Talks
[Introduction](http://javafx.ninja/talks/introduction/)
##License
###The MIT License (MIT)
## License
### The MIT License (MIT)
Copyright (c) 2015-2016 Andreas Billmann <andreas.billmann@javafx.ninja>
Copyright (c) 2015-2020 Andreas Billmann <andreas.billmann@javafx.ninja>

View File

@@ -1,38 +1,63 @@
group 'ninja.javafx'
version '0.8-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'groovy'
apply plugin:'application'
apply plugin: 'idea'
sourceCompatibility = 1.8
mainClassName = 'ninja.javafx.smartcsv.fx.SmartCSV'
plugins {
id 'idea'
id 'java'
id 'groovy'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.14'
id 'com.github.ben-manes.versions' version '0.48.0'
}
repositories {
mavenCentral()
jcenter()
}
apply plugin: 'java'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(25)
}
}
javafx {
version = "25"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
testCompile group: 'org.mockito', name: 'mockito-all', version: '1.10.19'
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.7'
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: 'commons-validator', name: 'commons-validator', version: '1.5.1'
compile group: 'de.jensd', name: 'fontawesomefx-commons', version: '8.12'
compile group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.6.3'
compile group: 'de.jensd', name: 'fontawesomefx-materialdesignfont', version: '1.6.50'
compile group: 'de.jensd', name: 'fontawesomefx-materialicons', version: '2.2.0'
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.11'
compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2'
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2'
compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.6.10'
// updated testing libraries
testImplementation group: 'org.junit.platform', name: 'junit-platform-launcher', version: '6.0.0'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '6.0.0'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '6.0.0'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '6.0.0'
testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '3.0'
testImplementation group: 'org.mockito', name: 'mockito-core', version:'5.20.0'
// runtime libraries - bumped to recent stable versions where compatible
implementation group: 'org.apache.groovy', name: 'groovy', version: '5.0.2'
implementation group: 'org.springframework', name: 'spring-context', version: '6.2.12'
implementation group: 'de.siegmar', name: 'fastcsv', version: '4.1.0'
implementation group: 'commons-validator', name: 'commons-validator', version: '1.10.0'
implementation group: 'de.jensd', name: 'fontawesomefx-commons', version: '9.1.2'
implementation group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.7.0-9.1.2'
implementation group: 'de.jensd', name: 'fontawesomefx-materialdesignfont', version: '2.0.26-9.1.2'
implementation group: 'de.jensd', name: 'fontawesomefx-materialicons', version: '2.2.0-9.1.2'
implementation group: 'org.controlsfx', name: 'controlsfx', version: '11.2.2'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.13.2'
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.25.2'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.25.2'
implementation group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.11.6'
}
task wrapper(type: Wrapper) {
gradleVersion = '2.14.1' //version required
}
test {
useJUnitPlatform()
}
group 'ninja.javafx'
version '1.5.0'
application {
mainClass = 'ninja.javafx.smartcsv.Main'
applicationDefaultJvmArgs = ["--enable-native-access=javafx.graphics"]
}

Binary file not shown.

View File

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

100
gradlew vendored Normal file → Executable file
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
@@ -6,42 +6,6 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
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.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
fi
# 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`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -150,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
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
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
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
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
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -49,7 +49,6 @@ goto fail
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -0,0 +1,36 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 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;
import ninja.javafx.smartcsv.fx.SmartCSV;
public class Main {
public static void main(String[] args) {
// workaround for module problem
SmartCSV.main(args);
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -26,20 +26,29 @@
package ninja.javafx.smartcsv.csv;
import org.supercsv.prefs.CsvPreference;
import ninja.javafx.smartcsv.preferences.Preferences;
import static ninja.javafx.smartcsv.preferences.Preferences.defaultPreferences;
/**
*
*/
public class CSVConfigurable {
protected CsvPreference csvPreference;
protected Preferences csvPreference;
protected String fileEncoding;
public CSVConfigurable() {
csvPreference = CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE;
csvPreference = defaultPreferences();
}
public void setCsvPreference(CsvPreference csvPreference) {
public void setCsvPreference(Preferences csvPreference) {
this.csvPreference = csvPreference;
}
public void setFileEncoding(String fileEncoding) {
this.fileEncoding = fileEncoding;
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -26,15 +26,14 @@
package ninja.javafx.smartcsv.csv;
import de.siegmar.fastcsv.reader.CsvReader;
import de.siegmar.fastcsv.reader.NamedCsvRecord;
import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import org.supercsv.io.CsvMapReader;
import org.supercsv.io.ICsvMapReader;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.nio.charset.Charset;
/**
* reads the csv file and stores the values in csv model
@@ -46,30 +45,44 @@ public class CSVFileReader extends CSVConfigurable implements FileReader<CSVMode
@Override
public void read(File file) throws IOException {
ICsvMapReader mapReader = null;
try {
mapReader = new CsvMapReader(new java.io.FileReader(file.getAbsoluteFile()), csvPreference);
System.out.println(csvPreference);
try (var csv = getNamedCsvReader(file)) {
model = new CSVModel();
// the header columns are used as the keys to the Map
String[] header = mapReader.getHeader(true);
var firstRow = csv.stream().findFirst();
if (firstRow.isEmpty()) {
return;
}
var header = firstRow.get().getHeader().toArray(String[]::new);
model.setHeader(header);
Map<String, String> customerMap;
while ((customerMap = mapReader.read(header)) != null) {
CSVRow row = model.addRow();
csv.forEach(csvRow -> {
var row = model.addRow();
for (String column : header) {
model.addValue(row, column, customerMap.get(column));
model.addValue(row, column, csvRow.getField(column));
}
}
});
} finally {
if (mapReader != null) {
mapReader.close();
}
} catch (IOException ex) {
// TODO perhaps a custom NinjaException that can properly identify and localize the exception message
// is this a file not found? is this a corrupt csv? etc
throw new IOException("Failed to read " + file + ": " + ex.getMessage(), ex);
}
}
private CsvReader<NamedCsvRecord> getNamedCsvReader(File file) throws IOException {
var builder = CsvReader.builder()
.fieldSeparator(csvPreference.delimiterChar());
if (csvPreference.quoteChar() != null) {
builder.quoteCharacter(csvPreference.quoteChar());
}
return builder.ofNamedCsvRecord(file.toPath(), Charset.forName(fileEncoding));
}
public CSVModel getContent() {
return model;
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -26,17 +26,17 @@
package ninja.javafx.smartcsv.csv;
import de.siegmar.fastcsv.writer.CsvWriter;
import de.siegmar.fastcsv.writer.QuoteStrategies;
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import org.supercsv.io.CsvMapWriter;
import org.supercsv.io.ICsvMapWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import java.nio.charset.Charset;
import java.util.List;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toList;
/**
* filewriter for the csv
@@ -51,21 +51,22 @@ public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smart
@Override
public void write(File filename) throws IOException {
ICsvMapWriter mapWriter = null;
try {
mapWriter = new CsvMapWriter(new FileWriter(filename.getAbsolutePath()), csvPreference);
mapWriter.writeHeader(model.getHeader());
try (var writer = getCsvWriter(filename)){
writer.writeRecord(model.getHeader());
for(CSVRow row: model.getRows()) {
Map<String, String> columns = convertMapFromModel(row);
mapWriter.write(columns, model.getHeader());
writer.writeRecord(convertMapFromModel(row));
}
}
finally {
if( mapWriter != null ) {
mapWriter.close();
}
}
private CsvWriter getCsvWriter(File filename) throws IOException {
var writer = CsvWriter.builder().fieldSeparator(csvPreference.delimiterChar());
if (csvPreference.quoteChar() != null) {
writer.quoteCharacter(csvPreference.quoteChar());
writer.quoteStrategy(QuoteStrategies.ALWAYS);
}
return writer.build(filename.toPath(), Charset.forName(fileEncoding));
}
/**
@@ -73,13 +74,8 @@ public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smart
* @param row the row to convert
* @return a simple map for the supercvs writer
*/
private Map<String, String> convertMapFromModel(CSVRow row) {
return row.getColumns().entrySet().stream()
.collect(
toMap(
Map.Entry::getKey,
e -> e.getValue().getValue().getValue() != null ? e.getValue().getValue().getValue() : ""
)
);
private List<String> convertMapFromModel(CSVRow row) {
return row.getColumns().values().stream().map(v -> v.get().getValue())
.collect(toList());
}
}

View File

@@ -1,9 +1,34 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 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.export;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.validation.ValidationError;
import java.io.File;
import java.io.StringWriter;

View File

@@ -1,3 +1,29 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 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.files;
import javafx.beans.property.BooleanProperty;
@@ -11,7 +37,7 @@ import java.io.File;
import java.io.IOException;
/**
* This class stores files and there state
* This class stores files and their state
* @author abi
*/
public class FileStorage<E> {
@@ -26,7 +52,7 @@ public class FileStorage<E> {
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
private ObjectProperty<File> file = new SimpleObjectProperty<>();
private ObjectProperty<E> content = new SimpleObjectProperty<E>();
private ObjectProperty<E> content = new SimpleObjectProperty<>();
public boolean isFileChanged() {
return fileChanged.get();

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -30,6 +30,7 @@ import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import ninja.javafx.smartcsv.fx.about.AboutController;
import org.springframework.context.annotation.*;
@@ -84,9 +85,12 @@ public class SmartCSV extends Application {
private void showUI(Stage primaryStage, String name, String version) {
SmartCSVController smartCVSController = appContext.getBean(SmartCSVController.class);
Scene scene = new Scene((Parent) smartCVSController.getView());
var defaultThemeCss = getClass().getResource("/ninja/javafx/smartcsv/fx/smartcsv.css").toExternalForm();
scene.getRoot().getStylesheets().add(defaultThemeCss);
primaryStage.setScene(scene);
primaryStage.setTitle(String.format("%s %s", name, version));
primaryStage.getIcons().add(new Image(SmartCSV.class.getResourceAsStream("/ninja/javafx/smartcsv/icon/logo.png")));
primaryStage.show();
primaryStage.setMaximized(true);

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -26,6 +26,7 @@
package ninja.javafx.smartcsv.fx;
import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.collections.ListChangeListener;
import javafx.collections.WeakListChangeListener;
@@ -35,6 +36,8 @@ import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
@@ -51,23 +54,23 @@ import ninja.javafx.smartcsv.fx.table.ValidationCellFactory;
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
import ninja.javafx.smartcsv.fx.util.JavaFxUtils;
import ninja.javafx.smartcsv.fx.util.LoadFileService;
import ninja.javafx.smartcsv.fx.util.SaveFileService;
import ninja.javafx.smartcsv.fx.validation.ValidationEditorController;
import ninja.javafx.smartcsv.preferences.PreferencesFileReader;
import ninja.javafx.smartcsv.preferences.PreferencesFileWriter;
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
import ninja.javafx.smartcsv.preferences.*;
import ninja.javafx.smartcsv.validation.ValidationError;
import ninja.javafx.smartcsv.validation.ValidationFileReader;
import ninja.javafx.smartcsv.validation.ValidationFileWriter;
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.supercsv.prefs.CsvPreference;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.ResourceBundle;
@@ -77,6 +80,7 @@ import static javafx.application.Platform.exit;
import static javafx.application.Platform.runLater;
import static javafx.beans.binding.Bindings.*;
import static javafx.scene.layout.AnchorPane.*;
import static ninja.javafx.smartcsv.preferences.Preferences.defaultPreferences;
/**
* main controller of the application
@@ -84,6 +88,7 @@ import static javafx.scene.layout.AnchorPane.*;
@Component
public class SmartCSVController extends FXMLController {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// constants
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -93,6 +98,13 @@ public class SmartCSVController extends FXMLController {
".SmartCSV.fx" +
File.separator + "" +
"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_EXTENSION = "*.csv";
public static final String JSON_FILTER_TEXT = "JSON files (*.json)";
@@ -198,6 +210,9 @@ public class SmartCSVController extends FXMLController {
@FXML
private Label currentLineNumber;
@FXML
private Label totalNumberOfLines;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// members
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -212,7 +227,8 @@ public class SmartCSVController extends FXMLController {
private FileStorage<CSVModel> currentCsvFile = new FileStorage<>(csvFileReader, csvFileWriter);
private FileStorage<ValidationConfiguration> currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter());
private FileStorage<CsvPreference> csvPreferenceFile = new FileStorage<>(new PreferencesFileReader(), new PreferencesFileWriter());
private FileStorage<Preferences> 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 WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener);
@@ -238,8 +254,51 @@ public class SmartCSVController extends FXMLController {
bindConfigFileName();
csvPreferenceFile.setFile(PREFERENCES_FILE);
fileEncodingFile.setFile(ENCODING_FILE);
loadCsvPreferencesFromFile();
initDragAndDrop();
}
private void initDragAndDrop() {
tableWrapper.setOnDragOver(event -> {
Dragboard db = event.getDragboard();
if (event.getGestureSource() != tableWrapper
&& db.hasFiles()
&& db.getFiles().size() == 1
&& db.getFiles().get(0).getName().endsWith(".csv")) {
event.acceptTransferModes(TransferMode.COPY);
}
event.consume();
});
tableWrapper.setOnDragDropped(event -> {
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasFiles() && db.getFiles().size() == 1 && canOpen()) {
File file = db.getFiles().get(0);
openFile(currentCsvFile, file);
success = true;
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
});
}
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) {
@@ -342,11 +401,32 @@ public class SmartCSVController extends FXMLController {
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
CsvPreference csvPreference = preferencesController.getCsvPreference();
Preferences csvPreference = preferencesController.getCsvPreference();
setCsvPreference(csvPreference);
saveCsvPreferences(csvPreference);
String fileEncoding = CharsetHelper.getCharsetName(preferencesController.getFileEncoding());
setFileEncoding(fileEncoding);
saveFileEncoding(fileEncoding);
} else {
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();
}
}
@@ -423,6 +503,22 @@ public class SmartCSVController extends FXMLController {
return canExit;
}
private boolean canOpen() {
boolean canOpen = true;
if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle(resourceBundle.getString("dialog.changes.title"));
alert.setHeaderText(resourceBundle.getString("dialog.changes.header.text"));
alert.setContentText(resourceBundle.getString("dialog.changes.text"));
Optional<ButtonType> result = alert.showAndWait();
if (result.get() != ButtonType.OK){
canOpen = false;
}
}
return canOpen;
}
public void showValidationEditor(String column) {
validationEditorController.setSelectedColumn(column);
validationEditorController.updateForm();
@@ -492,13 +588,17 @@ public class SmartCSVController extends FXMLController {
private void loadCsvPreferencesFromFile() {
if (csvPreferenceFile.getFile().exists()) {
useLoadFileService(csvPreferenceFile, event -> setCsvPreference(csvPreferenceFile.getContent()));
useLoadFileService(csvPreferenceFile, event -> {
setCsvPreference(csvPreferenceFile.getContent());
loadEncodingFromFile();
});
} else {
setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
setCsvPreference(defaultPreferences());
loadEncodingFromFile();
}
}
private void saveCsvPreferences(CsvPreference csvPreference) {
private void saveCsvPreferences(Preferences csvPreference) {
try {
createPreferenceFile();
csvPreferenceFile.setContent(csvPreference);
@@ -521,7 +621,7 @@ public class SmartCSVController extends FXMLController {
}
}
private void setCsvPreference(CsvPreference csvPreference) {
private void setCsvPreference(Preferences csvPreference) {
preferencesController.setCsvPreference(csvPreference);
csvFileReader.setCsvPreference(csvPreference);
csvFileWriter.setCsvPreference(csvPreference);
@@ -545,9 +645,14 @@ public class SmartCSVController extends FXMLController {
//Show open file dialog
File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
openFile(storageFile, file);
}
private void openFile(FileStorage storageFile, File file) {
if (file != null) {
File previousFile = storageFile.getFile();
storageFile.setFile(file);
useLoadFileService(storageFile, t -> resetContent());
useLoadFileService(storageFile, t -> resetContent(), () -> storageFile.setFile(previousFile));
}
}
@@ -576,13 +681,20 @@ public class SmartCSVController extends FXMLController {
return file;
}
private void useLoadFileService(FileStorage fileStorage, EventHandler<WorkerStateEvent> onSucceededHandler) {
private void useLoadFileService(FileStorage<?> fileStorage, EventHandler<WorkerStateEvent> onSucceededHandler) {
useLoadFileService(fileStorage, onSucceededHandler, () -> {
// nothing to rollback
});
}
private void useLoadFileService(FileStorage<?> fileStorage, EventHandler<WorkerStateEvent> onSucceededHandler, Runnable rollbackAction) {
loadFileService.setFileStorage(fileStorage);
loadFileService.restart();
loadFileService.setOnSucceeded(onSucceededHandler);
loadFileService.setOnFailed(event -> JavaFxUtils.onServiceError(event, "LoadFileService Error", "Failed to load the file.", rollbackAction));
}
private void useSaveFileService(FileStorage fileStorage) {
private void useSaveFileService(FileStorage<?> fileStorage) {
saveFileService.setFileStorage(fileStorage);
saveFileService.restart();
saveFileService.setOnSucceeded(t -> resetContent());
@@ -608,9 +720,15 @@ public class SmartCSVController extends FXMLController {
addColumn(column, tableView);
}
tableView.getColumns().addListener(
(InvalidationListener) observable -> currentCsvFile.getContent().setHeader(
tableView.getColumns().stream().map((x) -> x.getText()).toArray(String[]::new)));
tableView.getItems().setAll(currentCsvFile.getContent().getRows());
tableView.setEditable(true);
totalNumberOfLines.textProperty().setValue("" + currentCsvFile.getContent().getRows().size());
setBottomAnchor(tableView, 0.0);
setTopAnchor(tableView, 0.0);
setLeftAnchor(tableView, 0.0);

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -1,3 +1,29 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 javafx.ninja <info@javafx.ninja>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package ninja.javafx.smartcsv.fx.list;
import javafx.application.Platform;
@@ -9,9 +35,6 @@ import javafx.scene.layout.Region;
import java.util.function.UnaryOperator;
/**
* Created by abi on 05.08.2016.
*/
public class GotoLineDialog extends Dialog<Integer> {
private final GridPane grid;

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -34,17 +34,15 @@ import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import ninja.javafx.smartcsv.fx.FXMLController;
import ninja.javafx.smartcsv.preferences.Preferences;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.supercsv.prefs.CsvPreference;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ResourceBundle;
import java.util.function.UnaryOperator;
import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteMode;
import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteModeName;
/**
* controller for preferences
*/
@@ -57,14 +55,11 @@ public class PreferencesController extends FXMLController {
@FXML
private TextField delimiterChar;
@FXML
private CheckBox surroundingSpacesNeedQuotes;
@FXML
private CheckBox ignoreEmptyLines;
@FXML
private ComboBox<String> quoteMode;
private ComboBox<String> fileEncoding;
private String endOfLineSymbols;
@@ -79,7 +74,7 @@ public class PreferencesController extends FXMLController {
@Override
public void initialize(URL location, ResourceBundle resources) {
quoteMode.getItems().addAll("normal", "always", "column");
fileEncoding.getItems().addAll(Charset.availableCharsets().keySet());
UnaryOperator<TextFormatter.Change> allowOnlyOneCharacter = change -> {
if (change.isContentChange()) {
@@ -97,24 +92,31 @@ public class PreferencesController extends FXMLController {
}
private void revalidate() {
valid.setValue(quoteChar.getText().length() == 1 && delimiterChar.getText().length() == 1);
valid.setValue(quoteChar.getText().length() <= 1 && delimiterChar.getText().length() == 1);
}
public void setCsvPreference(CsvPreference csvPreference) {
quoteChar.setText(Character.toString(csvPreference.getQuoteChar()));
delimiterChar.setText(Character.toString((char)csvPreference.getDelimiterChar()));
surroundingSpacesNeedQuotes.setSelected(csvPreference.isSurroundingSpacesNeedQuotes());
ignoreEmptyLines.setSelected(csvPreference.isIgnoreEmptyLines());
quoteMode.getSelectionModel().select(getQuoteModeName(csvPreference.getQuoteMode()));
endOfLineSymbols = csvPreference.getEndOfLineSymbols();
public void setCsvPreference(Preferences csvPreference) {
if (csvPreference.quoteChar() != null) {
quoteChar.setText(csvPreference.quoteChar().toString());
} else {
quoteChar.setText("");
}
delimiterChar.setText(Character.toString(csvPreference.delimiterChar()));
ignoreEmptyLines.setSelected(csvPreference.ignoreEmptyLines());
endOfLineSymbols = csvPreference.endOfLineSymbols();
}
public CsvPreference getCsvPreference() {
return new CsvPreference.Builder(quoteChar.getText().charAt(0), delimiterChar.getText().charAt(0), endOfLineSymbols)
.useQuoteMode(getQuoteMode(quoteMode.getSelectionModel().getSelectedItem()))
.surroundingSpacesNeedQuotes(surroundingSpacesNeedQuotes.isSelected())
.ignoreEmptyLines(ignoreEmptyLines.isSelected())
.build();
public Preferences getCsvPreference() {
var quote = quoteChar.getText().length() == 0 ? null : quoteChar.getText().charAt(0);
return new Preferences(quote, delimiterChar.getText().charAt(0), endOfLineSymbols, ignoreEmptyLines.isSelected());
}
public void setFileEncoding(String fileEncoding) {
this.fileEncoding.setValue(fileEncoding);
}
public String getFileEncoding() {
return fileEncoding.getValue();
}
public boolean getValid() {

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -65,8 +65,8 @@ public class EditableValidationCell extends TableCell<CSVRow, CSVValue> {
@Override
public void cancelEdit() {
super.cancelEdit();
setText(getItem().getValue());
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
@@ -113,19 +113,14 @@ public class EditableValidationCell extends TableCell<CSVRow, CSVValue> {
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.setOnKeyPressed(t -> {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getValue());
runLater(() -> commitEdit(textField.getValue()));
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
});
textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue && textField != null) {
commitEdit(textField.getValue());
}
});
}
private class ValueTextField extends TextField {
private static class ValueTextField extends TextField {
private CSVValue value;
public ValueTextField(CSVValue value) {

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -47,7 +47,6 @@ public class ObservableMapValueFactory implements
@Override
public ObjectProperty<CSVValue> call(TableColumn.CellDataFeatures<CSVRow, CSVValue> features) {
CSVRow row = features.getValue();
ObjectProperty<CSVValue> value = row.getColumns().get(key);
return value;
return row.getColumns().get(key);
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -0,0 +1,73 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2021 javafx.ninja <info@javafx.ninja>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package ninja.javafx.smartcsv.fx.util;
import javafx.concurrent.Worker;
import javafx.concurrent.WorkerStateEvent;
import javafx.scene.control.Alert;
import ninja.javafx.smartcsv.fx.SmartCSVController;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* This class helps extract useful messages from exceptions
* TODO: make I18n maybe?
*/
public final class JavaFxUtils {
private static final Logger logger = LogManager.getLogger(SmartCSVController.class);
private JavaFxUtils() {
}
public static void onServiceError(WorkerStateEvent event, String windowTitle, String errorHeader) {
onServiceError(event, windowTitle, errorHeader, () -> {
});
}
public static void onServiceError(WorkerStateEvent event, String windowTitle, String errorHeader, Runnable rollbackAction) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(windowTitle);
alert.setHeaderText(errorHeader);
alert.setContentText(findExceptionMessage(event.getSource()));
alert.showAndWait();
}
private static String findExceptionMessage(Worker<?> source) {
if (source == null) {
return "Cannot identify the source of the event!";
} else if (source.getException() == null) {
return "The event did not have an exception?";
}
Throwable exception = source.getException();
logger.error("Error in " + source.getClass().getSimpleName(), exception);
if (exception.getMessage() == null) {
return "Exception of type " + exception.getClass() + " had no message, check the logs.";
}
return exception.getMessage();
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -34,17 +34,17 @@ import ninja.javafx.smartcsv.files.FileStorage;
* Service class for async load of a csv file
*/
@org.springframework.stereotype.Service
public class LoadFileService extends Service {
public class LoadFileService extends Service<Void> {
private FileStorage file;
private FileStorage<?> file;
public void setFileStorage(FileStorage file) {
public void setFileStorage(FileStorage<?> file) {
this.file = file;
}
@Override
protected Task createTask() {
return new Task() {
protected Task<Void> createTask() {
return new Task<>() {
@Override
protected Void call() throws Exception {
if (file != null) {

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -31,22 +31,22 @@ import javafx.concurrent.Task;
import ninja.javafx.smartcsv.files.FileStorage;
/**
* Service class for async load of a csv file
* Service class for async save of a csv file
*/
@org.springframework.stereotype.Service
public class SaveFileService extends Service {
public class SaveFileService extends Service<Void> {
private FileStorage file;
private FileStorage<?> file;
public void setFileStorage(FileStorage value) {
public void setFileStorage(FileStorage<?> value) {
file = value;
}
@Override
protected Task createTask() {
return new Task() {
protected Task<Void> createTask() {
return new Task<>() {
@Override
protected Void call() throws Exception {
protected Void call() {
try {
file.save();
} catch (Throwable ex) {

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -35,8 +35,8 @@ import ninja.javafx.smartcsv.fx.FXMLController;
import ninja.javafx.smartcsv.validation.configuration.*;
import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory;
import org.fxmisc.richtext.StyleSpans;
import org.fxmisc.richtext.StyleSpansBuilder;
import org.fxmisc.richtext.model.StyleSpans;
import org.fxmisc.richtext.model.StyleSpansBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -298,6 +298,7 @@ public class ValidationEditorController extends FXMLController {
Constraints constraints = config.getConstraints();
if (constraints == null) {
constraints = new Constraints();
config.setConstraints(constraints);
}
if (enableNotEmptyRule.isSelected()) {
@@ -442,7 +443,7 @@ public class ValidationEditorController extends FXMLController {
ruleEnabled.setSelected(false);
} else {
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-2021 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

@@ -2,8 +2,8 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -21,36 +21,42 @@
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.supercsv.quote.AlwaysQuoteMode;
import org.supercsv.quote.ColumnQuoteMode;
import org.supercsv.quote.NormalQuoteMode;
import org.supercsv.quote.QuoteMode;
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;
/**
* Helper class for mapping quote quoteModeName
* file reader for the file encoding
*/
public class QuoteModeHelper {
public class EncodingFileReader implements FileReader<String> {
public static QuoteMode getQuoteMode(String quoteModeName) {
switch (quoteModeName) {
case "always": return new AlwaysQuoteMode();
case "column": return new ColumnQuoteMode();
default: return new NormalQuoteMode();
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());
}
}
public static String getQuoteModeName(QuoteMode quoteMode) {
if (quoteMode instanceof AlwaysQuoteMode) {
return "always";
} else if (quoteMode instanceof ColumnQuoteMode) {
return "column";
} else {
return "normal";
}
}
}

View File

@@ -0,0 +1,59 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 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

@@ -0,0 +1,38 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 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;
public record Preferences(
Character quoteChar,
char delimiterChar,
String endOfLineSymbols,
boolean ignoreEmptyLines) {
public static Preferences defaultPreferences() {
return new Preferences('\"',',', "\n", true);
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -28,51 +28,39 @@ package ninja.javafx.smartcsv.preferences;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileReader;
import org.supercsv.prefs.CsvPreference;
import org.supercsv.quote.AlwaysQuoteMode;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteMode;
import static ninja.javafx.smartcsv.preferences.Preferences.defaultPreferences;
/**
* file reader for the preferences
*/
public class PreferencesFileReader implements FileReader<CsvPreference> {
public class PreferencesFileReader implements FileReader<Preferences> {
private Map config;
private CsvPreference csvPreference;
private Preferences csvPreference;
public PreferencesFileReader() {
csvPreference = new CsvPreference.
Builder(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE).
useQuoteMode(new AlwaysQuoteMode()).build();
csvPreference = defaultPreferences();
}
@Override
public void read(File filename) throws IOException {
config = new GsonBuilder().create().fromJson(new java.io.FileReader(filename), HashMap.class);
Map config = new GsonBuilder().create().fromJson(new java.io.FileReader(filename), HashMap.class);
if (config != null) {
char quoteChar = config.get("quoteChar").toString().charAt(0);
Character quoteChar = config.get("quoteChar") == null ? null : config.get("quoteChar").toString().charAt(0);
char delimiterChar = config.get("delimiterChar").toString().charAt(0);
String endOfLineSymbols = config.get("endOfLineSymbols").toString();
boolean surroundingSpacesNeedQuotes = (Boolean)config.get("surroundingSpacesNeedQuotes");
boolean ignoreEmptyLines = (Boolean)config.get("ignoreEmptyLines");
String quoteMode = config.get("quoteMode").toString();
csvPreference = new CsvPreference.Builder(quoteChar, delimiterChar, endOfLineSymbols)
.useQuoteMode(getQuoteMode(quoteMode))
.surroundingSpacesNeedQuotes(surroundingSpacesNeedQuotes)
.ignoreEmptyLines(ignoreEmptyLines)
.build();
boolean ignoreEmptyLines = (Boolean) config.get("ignoreEmptyLines");
csvPreference = new Preferences(quoteChar, delimiterChar, endOfLineSymbols, ignoreEmptyLines);
}
}
public CsvPreference getContent() {
public Preferences getContent() {
return csvPreference;
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.preferences;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.FileWriter;
import org.supercsv.prefs.CsvPreference;
import java.io.File;
import java.io.IOException;
@@ -40,22 +39,20 @@ import java.util.Map;
/**
* Save preferences to configuration file
*/
public class PreferencesFileWriter implements FileWriter<CsvPreference> {
public class PreferencesFileWriter implements FileWriter<Preferences> {
private CsvPreference csvPreference;
private Preferences csvPreference;
public void setContent(CsvPreference csvPreference) {
public void setContent(Preferences csvPreference) {
this.csvPreference = csvPreference;
}
public void write(File file) throws IOException {
Map<String, Object> preferences = new HashMap<>();
preferences.put("quoteChar", Character.toString(csvPreference.getQuoteChar()));
preferences.put("delimiterChar", Character.toString((char)csvPreference.getDelimiterChar()));
preferences.put("endOfLineSymbols", csvPreference.getEndOfLineSymbols());
preferences.put("surroundingSpacesNeedQuotes", csvPreference.isSurroundingSpacesNeedQuotes());
preferences.put("ignoreEmptyLines", csvPreference.isIgnoreEmptyLines());
preferences.put("quoteMode", QuoteModeHelper.getQuoteModeName(csvPreference.getQuoteMode()));
preferences.put("quoteChar", csvPreference.quoteChar() == null ? null: csvPreference.quoteChar().toString());
preferences.put("delimiterChar", Character.toString((char)csvPreference.delimiterChar()));
preferences.put("endOfLineSymbols", csvPreference.endOfLineSymbols());
preferences.put("ignoreEmptyLines", csvPreference.ignoreEmptyLines());
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Files.write(file.toPath(), gson.toJson(preferences).getBytes());

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -133,6 +133,15 @@ public class Validator {
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) {
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
if (validationMap != null) {
@@ -172,12 +181,12 @@ public class Validator {
}
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));
}
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));
}
@@ -186,24 +195,26 @@ public class Validator {
add(column.getName(), new DateValidation(format));
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(EMAIL.getExternalValue())) {
add(column.getName(), new EmailValidation());
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(URI.getExternalValue())) {
add(column.getName(), new UriValidation());
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(UUID.getExternalValue())) {
add(column.getName(), new UuidValidation());
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(BINARY.getExternalValue())) {
add(column.getName(), new BinaryValidation());
}
if (column.getType() == STRING && column.getFormat() == null) {
columnValidationMap.get(column).remove(Validation.Type.STRING);
remove(column.getName(), Validation.Type.STRING);
} else {
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(EMAIL.getExternalValue())) {
add(column.getName(), new EmailValidation());
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(URI.getExternalValue())) {
add(column.getName(), new UriValidation());
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(UUID.getExternalValue())) {
add(column.getName(), new UuidValidation());
}
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(BINARY.getExternalValue())) {
add(column.getName(), new BinaryValidation());
}
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -37,11 +37,11 @@ import org.codehaus.groovy.control.CompilationFailedException;
public class GroovyValidation extends EmptyValueIsValid {
private String groovyScript;
private GroovyShell shell = new GroovyShell();
private Script script;
public GroovyValidation(String groovyScript) {
this.groovyScript = groovyScript;
GroovyShell shell = new GroovyShell();
script = shell.parse(groovyScript);
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -34,6 +34,7 @@ import java.util.UUID;
*/
public class UuidValidation extends EmptyValueIsValid {
@SuppressWarnings("ResultOfMethodCallIgnored")
@Override
public void check(int row, String value, ValidationError error) {
try {

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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

View File

@@ -1,21 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Hyperlink?>
<?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?>
<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>
<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:">
<font>
<Font size="18.0" />
@@ -25,6 +22,8 @@
</VBox.margin>
</Label>
<Label text="AOE Takashi (https://github.com/aoetk)" />
<Label text="Hasan Kara (https://github.com/haisi)" />
<Label text="apixandru (https://github.com/apixandru)" />
<Label text="3rd party software">
<VBox.margin>
<Insets top="8.0" />
@@ -41,17 +40,17 @@
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="junit" />
@@ -62,8 +61,8 @@
<Hyperlink onAction="#openLinkInBrowser" text="http://www.groovy-lang.org/" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="spring framework" GridPane.rowIndex="3" />
<Hyperlink onAction="#openLinkInBrowser" text="https://spring.io/" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="supercsv" GridPane.rowIndex="4" />
<Hyperlink onAction="#openLinkInBrowser" text="http://super-csv.github.io/super-csv/" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label text="FastCSV" GridPane.rowIndex="4" />
<Hyperlink onAction="#openLinkInBrowser" text="https://github.com/osiegmar/FastCSV" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label text="Gson" GridPane.rowIndex="5" />
<Hyperlink onAction="#openLinkInBrowser" text="https://github.com/google/gson/" GridPane.columnIndex="1" GridPane.rowIndex="5" />
<Label text="commons-validator" GridPane.rowIndex="6" />
@@ -91,7 +90,7 @@
<Font size="18.0" />
</font>
</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-2021 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>
<opaqueInsets>
<Insets />

View File

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

View File

@@ -12,20 +12,17 @@
<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>
<children>
<Label text="%preferences.quoteChar" />
<TextField fx:id="quoteChar" GridPane.columnIndex="1" />
<Label text="%preferences.delimiterChar" GridPane.rowIndex="1" />
<TextField fx:id="delimiterChar" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<Label text="%preferences.surroundingSpacesNeedQuotes" GridPane.rowIndex="2" />
<CheckBox fx:id="surroundingSpacesNeedQuotes" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="%preferences.ignoreEmptyLines" GridPane.rowIndex="3" />
<CheckBox fx:id="ignoreEmptyLines" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<Label text="%preferences.quoteMode" GridPane.rowIndex="4" />
<ComboBox fx:id="quoteMode" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
<Label text="%preferences.ignoreEmptyLines" GridPane.rowIndex="2" />
<CheckBox fx:id="ignoreEmptyLines" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="%preferences.fileEncoding" GridPane.rowIndex="3" />
<ComboBox fx:id="fileEncoding" editable="true" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="3" />
</children>
<padding>
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />

View File

@@ -5,7 +5,6 @@
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import java.net.URL?>
<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>
<VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER">
@@ -265,9 +264,6 @@
</center>
<left>
</left>
<stylesheets>
<URL value="@/ninja/javafx/smartcsv/fx/smartcsv.css" />
</stylesheets>
<bottom>
<GridPane hgap="8.0" BorderPane.alignment="CENTER">
<columnConstraints>
@@ -279,7 +275,9 @@
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
<ColumnConstraints fillWidth="false" halignment="RIGHT" hgrow="NEVER" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints fillWidth="false" halignment="RIGHT" hgrow="NEVER" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
@@ -293,6 +291,8 @@
<Label fx:id="configurationName" GridPane.columnIndex="5" GridPane.hgrow="ALWAYS" />
<Label text="%lineNumber" GridPane.columnIndex="7" />
<Label fx:id="currentLineNumber" text="" GridPane.columnIndex="8" />
<Label text="%totalNumberOfLines" GridPane.columnIndex="9" />
<Label fx:id="totalNumberOfLines" text="0" GridPane.columnIndex="10" />
</children>
<BorderPane.margin>
<Insets bottom="4.0" left="8.0" right="8.0" top="4.0" />

View File

@@ -29,6 +29,10 @@ dialog.exit.title = Close Application
dialog.exit.header.text = Do you want to close application?
dialog.exit.text = There are changes made to the csv file. If you close now, the changes are lost!
dialog.changes.title = Discard changes
dialog.changes.header.text = Do you want to discard changes?
dialog.changes.text = There are changes made to the csv file. If you open a new file, the changes are lost!
dialog.preferences.title = Preferences
dialog.preferences.header.text = Preferences
@@ -41,6 +45,7 @@ preferences.delimiterChar = Delimiter character:
preferences.ignoreEmptyLines = Ignore empty lines:
preferences.surroundingSpacesNeedQuotes = Surrounding spaces need quotes:
preferences.quoteMode = Quote mode:
preferences.fileEncoding = File encoding:
# validaton messages
validation.message.not.empty = should not be empty
@@ -86,6 +91,7 @@ dialog.validation.rules.header = Validation rules of column "{0}"
context.menu.edit.column.rules = Edit rules
lineNumber = Selected line:
totalNumberOfLines = Lines:
log.header.message = {0} has {1} errors
log.message = row {0} column {1} : {2}

View File

@@ -45,11 +45,16 @@ dialog.exit.title = Anwendung beenden
dialog.exit.header.text = M\u00f6chten Sie wirklich die Anwendung beenden?
dialog.exit.text = Es gibt noch ungespeicherte \u00c4nderungen, die verloren gehen, wenn Sie die Anwendung jetzt beenden.
dialog.changes.title = Änderungen verwerfen
dialog.changes.header.text = Wollen Sie Ihre Änderungen verwerfen?
dialog.changes.text = Es gibt noch ungespeicherte \u00c4nderungen, die verloren gehen, wenn Sie die Datei laden.
preferences.quoteChar = Einfassungszeichen:
preferences.delimiterChar = Trennzeichen:
preferences.ignoreEmptyLines = Leere Zeilen ignorieren:
preferences.surroundingSpacesNeedQuotes = Leerzeichen einfassen:
preferences.quoteMode = Einfassungsmodus:
preferences.fileEncoding = Dateicodierung:
# validaton messages
validation.message.not.empty = Darf nicht leer sein.
@@ -96,6 +101,7 @@ dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"
context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten
lineNumber = Ausgew\u00e4hlte Zeile:
totalNumberOfLines = Zeilen:
log.header.message = {0} hat {1} Fehler
log.message = Zeile {0} Spalte {1} : {2}

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,109 @@
package ninja.javafx.smartcsv.files;
import ninja.javafx.smartcsv.FileReader;
import ninja.javafx.smartcsv.FileWriter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mockito.Mockito.*;
public class FileStorageTest {
private FileReader<String> reader;
private FileWriter<String> writer;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// subject under test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private FileStorage<String> sut;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@BeforeEach
public void initialize() {
reader = mock(FileReader.class);
writer = mock(FileWriter.class);
sut = new FileStorage<>(reader, writer);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Test
public void setFile_ShouldStoreFile() {
// pre execution assertion
assertThat("get file returns null", sut.getFile(), nullValue());
assertThat("property is null", sut.fileProperty().isNull().get(), equalTo(true));
// execution
final File file = new File("file");
sut.setFile(file);
// assertion
assertThat("get file returns the file", sut.getFile(), sameInstance(file));
assertThat("property is not null", sut.fileProperty().isNull().get(), equalTo(false));
}
@Test
public void load_ShouldReadContentFromReader() throws Exception {
// setup
final File file = new File("file");
sut.setFile(file);
when(reader.getContent()).thenReturn("CONTENT");
// execution
sut.load();
// assertion
verify(reader).read(file);
assertThat("content is set", sut.getContent(), equalTo("CONTENT"));
}
@Test
public void load_ShouldResetFileChangedProperty() throws Exception {
// setup
sut.setFileChanged(true);
when(reader.getContent()).thenReturn("CONTENT");
// execution
sut.load();
// assertion
assertThat("file changed is reset", sut.isFileChanged(), equalTo(false));
}
@Test
public void save_ShouldWriteContentToWriter() throws Exception {
// setup
final String content = "CONTENT";
sut.setContent(content);
final File file = new File("file");
sut.setFile(file);
// execution
sut.save();
// assertion
verify(writer).setContent(content);
verify(writer).write(file);
}
@Test
public void save_ShouldResetFileChangedProperty() throws Exception {
// setup
sut.setFileChanged(true);
// execution
sut.save();
// assertion
assertThat("file changed is reset", sut.isFileChanged(), equalTo(false));
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -26,10 +26,11 @@
package ninja.javafx.smartcsv.fx.table.model;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
/**
* unit test for the csv model
@@ -39,14 +40,13 @@ public class CSVModelTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// constants
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static final String TESTHEADER = "TESTHEADER";
static final String TESTVALUE = "TESTVALUE";
static final String FILEPATH = "filepath";
private static final String TESTHEADER = "TESTHEADER";
private static final String TESTVALUE = "TESTVALUE";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// subject under test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CSVModel sut = new CSVModel();
private CSVModel sut = new CSVModel();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tests

View File

@@ -1,10 +1,11 @@
package ninja.javafx.smartcsv.fx.table.model;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
/**
* unit test for row class
@@ -14,13 +15,13 @@ public class CSVRowTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// constants
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static final String COLUMN = "COLUMN";
static final String VALUE = "VALUE";
private static final String COLUMN = "COLUMN";
private static final String VALUE = "VALUE";
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// subject under test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CSVRow sut = new CSVRow();
private CSVRow sut = new CSVRow();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,57 @@
/*
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2021 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);
assertNotEquals(StandardCharsets.UTF_16.name(), Charset.defaultCharset());
}
@Test
public void getCharsetName_unknown_charset() {
String result = CharsetHelper.getCharsetName("foobar");
assertEquals(Charset.defaultCharset().name(), result);
}
@Test
public void getCharsetName_null_charset() {
String result = CharsetHelper.getCharsetName(null);
assertEquals(Charset.defaultCharset().name(), result);
}
}

View File

@@ -2,7 +2,7 @@
The MIT License (MIT)
-----------------------------------------------------------------------------
Copyright (c) 2015-2016 javafx.ninja <info@javafx.ninja>
Copyright (c) 2015-2021 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
@@ -29,68 +29,39 @@ package ninja.javafx.smartcsv.validation;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.joining;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* unit test for header validator
*/
@RunWith(Parameterized.class)
public class HeaderValidationTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameters
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private ValidationConfiguration config;
private Boolean expectedResult;
private List<ValidationMessage> expectedErrors;
private String[] headerNames;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// subject under test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private Validator sut;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameterized constructor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public HeaderValidationTest(String configHeaderNames,
String[] headerNames,
Boolean expectedResult,
List<ValidationMessage> expectedErrors) {
Gson gson = new GsonBuilder().create();
this.config = gson.fromJson(configHeaderNames, ValidationConfiguration.class);
this.headerNames = headerNames;
this.expectedResult = expectedResult;
this.expectedErrors = expectedErrors;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Before
public void initialize() {
sut = new Validator(config);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Test
public void validation() {
@ParameterizedTest
@MethodSource("validationConfigurations")
public void validation(String configHeaderNames,
String[] headerNames,
Boolean expectedResult,
List<ValidationMessage> expectedErrors) {
// setup
Gson gson = new GsonBuilder().create();
ValidationConfiguration config = gson.fromJson(configHeaderNames, ValidationConfiguration.class);
Validator sut = new Validator(config, new TestColumnValueProvider());
// execution
ValidationError result = sut.isHeaderValid(headerNames);
@@ -104,19 +75,33 @@ public class HeaderValidationTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameters for tests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Parameterized.Parameters
public static Collection validationConfigurations() {
return asList(new Object[][] {
{ json(), new String[] {}, true, null },
{ json("a"), new String[] {"a"}, true, null },
{ json("a"), new String[] {"b"}, false, singletonList(new ValidationMessage("validation.message.header.match", "0", "a", "b"))},
{ json("a"), new String[] {"a","b"}, false, singletonList(new ValidationMessage("validation.message.header.length", "2", "1"))},
{ json("a", "b"), new String[] {"b", "a"}, false, asList(new ValidationMessage("validation.message.header.match", "0", "a", "b"), new ValidationMessage("validation.message.header.match", "1", "b", "a")) }
});
public static Stream<Arguments> validationConfigurations() {
return Stream.of(
Arguments.of( json(), new String[] {}, true, null ),
Arguments.of( json("a"), new String[] {"a"}, true, null ),
Arguments.of( json("a"), new String[] {"b"}, false, singletonList(new ValidationMessage("validation.message.header.match", "0", "a", "b"))),
Arguments.of( json("a"), new String[] {"a","b"}, false, singletonList(new ValidationMessage("validation.message.header.length", "2", "1"))),
Arguments.of( json("a", "b"), new String[] {"b", "a"}, false, asList(new ValidationMessage("validation.message.header.match", "0", "a", "b"), new ValidationMessage("validation.message.header.match", "1", "b", "a")) )
);
}
@SuppressWarnings("StringConcatenationInLoop")
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

@@ -3,78 +3,40 @@ package ninja.javafx.smartcsv.validation;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.joining;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
/**
* unit test for validator
*/
@RunWith(Parameterized.class)
public class ValidatorTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameters
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private ValidationConfiguration config;
private String column;
private String value;
private Boolean expectedResult;
private ValidationMessage expectedError;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// subject under test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private Validator sut;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameterized constructor
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public ValidatorTest(String config,
String column,
String value,
Boolean expectedResult,
ValidationMessage expectedError) {
System.out.println(config);
Gson gson = new GsonBuilder().create();
this.config = gson.fromJson(config, ValidationConfiguration.class);
this.column = column;
this.value = value;
this.expectedResult = expectedResult;
this.expectedError = expectedError;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// init
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Before
public void initialize() {
sut = new Validator(config);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Test
public void validation() {
System.out.println(column + " " + value + " " + expectedResult + " " + expectedError);
@ParameterizedTest
@MethodSource("validationConfigurations")
public void validation(String config,
String value,
Boolean expectedResult,
ValidationMessage expectedError) {
// setup
Gson gson = new GsonBuilder().create();
ValidationConfiguration validationConfiguration = gson.fromJson(config, ValidationConfiguration.class);
Validator sut = new Validator(validationConfiguration, new TestColumnValueProvider());
// execution
ValidationError result = sut.isValid(0, column, value);
ValidationError result = sut.isValid(0, "column", value);
// assertion
assertThat(result == null, is(expectedResult));
@@ -86,45 +48,80 @@ public class ValidatorTest {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// parameters for tests
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Parameterized.Parameters
public static Collection validationConfigurations() {
return asList(new Object[][] {
{ json("column", "not empty", true), "column", "value", true, null },
{ json("column", "not empty", true), "column", "", false, new ValidationMessage("validation.message.not.empty") },
{ json("column", "not empty", true), "column", null, false, new ValidationMessage("validation.message.not.empty") },
{ json("column", "integer", true), "column", "999", true, null },
{ json("column", "integer", true), "column", "a", false, new ValidationMessage("validation.message.integer") },
{ json("column", "double", true), "column", "999", true, null },
{ json("column", "double", true), "column", "999.000", true, null },
{ json("column", "double", true), "column", "a", false, new ValidationMessage("validation.message.double") },
{ json("column", "minlength", 2), "column", "12", true, null },
{ json("column", "minlength", 2), "column", "1", false, new ValidationMessage("validation.message.min.length", "2") },
{ json("column", "maxlength", 2), "column", "12", true, null },
{ json("column", "maxlength", 2), "column", "123", false, new ValidationMessage("validation.message.max.length", "2") },
{ json("column", "date", "yyyyMMdd"), "column", "20151127", true, null },
{ json("column", "date", "yyyyMMdd"), "column", "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyyMMdd") },
{ json("column", "alphanumeric", true), "column", "abcABC123", true, null },
{ json("column", "alphanumeric", true), "column", "-abcABC123", false, new ValidationMessage("validation.message.alphanumeric") },
{ json("column", "regexp", "[a-z]*"), "column", "abc", true, null },
{ json("column", "regexp", "[a-z]*"), "column", "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") },
{ json("column", "groovy", "value.contains('a')? 'true' : 'no a inside'"), "column", "abcdef", true, null },
{ json("column", "groovy", "value.contains('a')? 'true' : 'no a inside'"), "column", "bcdefg", false, new ValidationMessage("no a inside") },
{ json("column", "value of", asList("a","b","c","d","e")), "column", "c", 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") },
});
public static Stream<Arguments> validationConfigurations() {
return Stream.of(
Arguments.of( constraintsJSON("string", "required", true), "value", true, null ),
Arguments.of( constraintsJSON("string", "required", true), "", false, new ValidationMessage("validation.message.not.empty") ),
Arguments.of( constraintsJSON("string", "required", true), null, false, new ValidationMessage("validation.message.not.empty") ),
Arguments.of( constraintsJSON("integer", null, true), "999", true, null ),
Arguments.of( constraintsJSON("integer", null, true), "a", false, new ValidationMessage("validation.message.integer") ),
Arguments.of( constraintsJSON("number", null, true), "999", true, null ),
Arguments.of( constraintsJSON("number", null, true), "999.000", true, null ),
Arguments.of( constraintsJSON("number", null, true), "a", false, new ValidationMessage("validation.message.double") ),
Arguments.of( constraintsJSON("string", "minLength", 2), "12", true, null ),
Arguments.of( constraintsJSON("string", "minLength", 2), "1", false, new ValidationMessage("validation.message.min.length", "2") ),
Arguments.of( constraintsJSON("string", "maxLength", 2), "12", true, null ),
Arguments.of( constraintsJSON("string", "maxLength", 2), "123", false, new ValidationMessage("validation.message.max.length", "2") ),
Arguments.of( constraintsJSON("string", "pattern", "[a-z]*"), "abc", true, null ),
Arguments.of( constraintsJSON("string", "pattern", "[a-z]*"), "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") ),
Arguments.of( constraintsJSON("string", "enum", asList("a","b","c","d","e")), "c", true, null ),
Arguments.of( constraintsJSON("string", "enum", asList("a","b","c","d","e")), "f", false, new ValidationMessage("validation.message.value.of", "f", "a, b, c, d, e") ),
Arguments.of( formatJSON("string", null), "some string", true, null ),
Arguments.of( formatJSON("string", "email"), "test@javafx.ninja", true, null ),
Arguments.of( formatJSON("string", "email"), "wrong email", false, new ValidationMessage("validation.message.email") ),
Arguments.of( formatJSON("string", "uri"), "http://www.javafx.ninja", true, null ),
Arguments.of( formatJSON("string", "uri"), "!$%&/()", false, new ValidationMessage("validation.message.uri") ),
Arguments.of( formatJSON("string", "binary"), "dGVzdA==", true, null ),
Arguments.of( formatJSON("string", "binary"), "no binary", false, new ValidationMessage("validation.message.binary") ),
Arguments.of( formatJSON("string", "uuid"), "6ba7b810-9dad-11d1-80b4-00c04fd430c8", true, null ),
Arguments.of( formatJSON("string", "uuid"), "no uuid", false, new ValidationMessage("validation.message.uuid") ),
Arguments.of( formatJSON("date", null), "2015-11-27", true, null ),
Arguments.of( formatJSON("date", null), "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyy-MM-dd") ),
Arguments.of( formatJSON("date", "yyyyMMdd"), "20151127", true, null ),
Arguments.of( formatJSON("date", "yyyyMMdd"), "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyyMMdd") ),
Arguments.of( customAttributeJSON( "groovy", "value.contains('a')? 'true' : 'no a inside'"), "abcdef", true, null ),
Arguments.of( 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) {
String json = "{\"headers\": { \"list\": [\""+column+"\"]},\"columns\":{\"" + column + "\":{\"" + rule + "\":";
if (value instanceof String) {
json += "\""+ value + "\"";
} else if (value instanceof List) {
List<String> list = (List<String>)value;
json += "[" + list.stream().collect(joining(", ")) + "]";
} else {
json += value;
public static String constraintsJSON(String type, String constraint, Object value) {
String json = "{\"fields\": [ { \"name\": \"column\", \"type\" : \"" + type +"\"";
if (constraint != null) {
json += ", \"constraints\": { \"" + constraint + "\":";
if (value instanceof String) {
json += "\"" + value + "\"";
} else if (value instanceof List) {
List<String> list = (List<String>) value;
json += "[" + list.stream().collect(joining(", ")) + "]";
} else {
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;
}
}