mirror of
https://github.com/frosch95/SmartCSV.fx.git
synced 2026-04-11 21:48:22 +02:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 55ed382203 | |||
| 81d75a995b | |||
| f5ab096452 | |||
| 18335b9280 | |||
| 4e216b4792 | |||
| 3980e2951f | |||
| 1b39c9a08e | |||
| 0db16c0328 | |||
| bec55b6119 | |||
| 7dac3ce011 | |||
| 449f929f08 | |||
| 9e3561fedb | |||
| 9c1b110bfd | |||
| 398219a897 | |||
|
|
a79dde5421 | ||
| fb234fa50e | |||
| 43856dffab | |||
| 8cecca2172 | |||
|
|
35f395d44a | ||
|
|
9961373d76 | ||
|
|
fd6938fa80 | ||
|
|
78f3f5909e | ||
|
|
d572dcdeed | ||
| af6ce56f71 | |||
| 2f692352b7 | |||
| 5b59c76200 | |||
| 7e40daa1e5 | |||
| 2da843e1e2 | |||
| d1ffd09941 | |||
|
|
4c29d29bf5 | ||
|
|
c4f91d94f1 | ||
| 8c43c5a1de | |||
| 187002997c | |||
| aa7e38c613 | |||
| 13a41468d4 | |||
| f41979960b | |||
| a7fce854ca | |||
| 4f40418aea | |||
| d7c821d1fe | |||
|
|
49f8003f97 | ||
|
|
5f8383c6a1 | ||
| 03dcf20229 | |||
| 543125812a | |||
| c52f6c0bc8 | |||
| 422bd73bad | |||
| e6672834fb | |||
| 8e0ea66552 | |||
|
|
bf476308a2 | ||
|
|
cf9203549b | ||
|
|
02b102cfb2 | ||
| 8e0e1c41c3 | |||
| 3ce9ae8edd | |||
| 7c12b7506f | |||
| 6fc62006fa | |||
| fdc4f99fd5 | |||
| e29d60b9b8 | |||
| 0a4e86c160 | |||
| c07dde8e19 | |||
| 9b0e3707b7 | |||
| a1f6c24bae | |||
| c1a671504e | |||
| 7c3f140491 | |||
| 16373a033a | |||
| e9e71b5474 | |||
| 48c657b648 | |||
| 8bd90b47e1 | |||
| 44f36759a6 | |||
|
|
326e4d954b | ||
|
|
96446e4e75 | ||
|
|
5eaf021632 | ||
|
|
ef376d6c61 | ||
|
|
2676b523d3 | ||
|
|
7e34ff8c59 | ||
|
|
a37a84bd09 | ||
|
|
5100c668ab | ||
|
|
90bda028ec | ||
|
|
5e31f834ac | ||
|
|
d689423c61 | ||
|
|
9e8d71ca1d | ||
|
|
70855e614a | ||
| 4354afdf1d | |||
| 4002219dfe | |||
| 7723906935 | |||
| 5694273c51 | |||
| 04a54da798 | |||
| 6f635f5e75 | |||
| 742f129ea9 | |||
| 0c391e292e | |||
| cd0ca0ed11 | |||
| e799f0ac45 | |||
| 3664a4e8a7 | |||
| e87eec2162 | |||
| 3adfd566bc | |||
| e6742a4e30 | |||
| 7472c66823 | |||
| c7873ef0ba | |||
| b79a20201e | |||
|
|
3ebf78805c | ||
| dcdea4236f | |||
| 11358c5bec | |||
| 9c21357059 | |||
| 909617d9b7 | |||
| ab952aa98f | |||
| a7bd8d5a3e | |||
| bc59f08bbb | |||
| 4c4d25f3b5 | |||
| 6af20575e8 | |||
| b6731f7641 | |||
| d2f81d7d3e |
21
.github/workflows/build-and-test.yml
vendored
Normal file
21
.github/workflows/build-and-test.yml
vendored
Normal 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
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -74,3 +74,4 @@ crashlytics.properties
|
|||||||
crashlytics-build.properties
|
crashlytics-build.properties
|
||||||
|
|
||||||
|
|
||||||
|
smartcsv.log
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 Andreas Billmann <andreas.billmann@javafx.ninja>
|
Copyright (c) 2015-2021 Andreas Billmann <andreas.billmann@javafx.ninja>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
22
README.md
22
README.md
@@ -1,26 +1,30 @@
|
|||||||
# SmartCSV.fx
|
# SmartCSV.fx
|
||||||
##Description
|
    
|
||||||
A simple JavaFX application to load, save and edit a CSV file and provide a JSON configuration for columns to check the values in the columns.
|
## 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,
|
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.
|
even in a "normal" CSV editor. So I decided to write this simple JavaFX application.
|
||||||
|
|
||||||
##Video
|
## Video
|
||||||
[](https://youtu.be/eUh_WLx1OwI)
|
[](https://youtu.be/eUh_WLx1OwI)
|
||||||
|
|
||||||
##Links
|
## Links
|
||||||
[GitHub Page](http://frosch95.github.io/SmartCSV.fx/)
|
[GitHub Page](http://frosch95.github.io/SmartCSV.fx/)
|
||||||
|
|
||||||
[Wiki & Documentation](https://github.com/frosch95/SmartCSV.fx/wiki)
|
[Wiki & Documentation](https://github.com/frosch95/SmartCSV.fx/wiki)
|
||||||
|
|
||||||
binary distribution of the [latest release (0.4)](https://drive.google.com/open?id=0BwY9gBUvn5qmREdCc0FvNDNEQTA)
|
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)
|
||||||
|
|
||||||
##License
|
## Talks
|
||||||
###The MIT License (MIT)
|
[Introduction](http://javafx.ninja/talks/introduction/)
|
||||||
|
|
||||||
|
## License
|
||||||
|
### The MIT License (MIT)
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2015 Andreas Billmann <andreas.billmann@javafx.ninja>
|
Copyright (c) 2015-2020 Andreas Billmann <andreas.billmann@javafx.ninja>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
83
build.gradle
83
build.gradle
@@ -1,38 +1,63 @@
|
|||||||
group 'ninja.javafx'
|
plugins {
|
||||||
version '0.4-SNAPSHOT'
|
id 'idea'
|
||||||
|
id 'java'
|
||||||
apply plugin: 'java'
|
id 'groovy'
|
||||||
apply plugin: 'groovy'
|
id 'application'
|
||||||
apply plugin:'application'
|
id 'org.openjfx.javafxplugin' version '0.0.14'
|
||||||
apply plugin: 'idea'
|
id 'com.github.ben-manes.versions' version '0.48.0'
|
||||||
|
}
|
||||||
sourceCompatibility = 1.8
|
|
||||||
mainClassName = 'ninja.javafx.smartcsv.fx.SmartCSV'
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
}
|
||||||
|
|
||||||
|
apply plugin: 'java'
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(25)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
javafx {
|
||||||
|
version = "25"
|
||||||
|
modules = [ 'javafx.controls', 'javafx.fxml' ]
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
// updated testing libraries
|
||||||
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
|
testImplementation group: 'org.junit.platform', name: 'junit-platform-launcher', version: '6.0.0'
|
||||||
testCompile group: 'org.mockito', name: 'mockito-all', version: '1.10.19'
|
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '6.0.0'
|
||||||
compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.7'
|
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '6.0.0'
|
||||||
compile group: 'org.springframework', name:'spring-context', version: '4.3.1.RELEASE'
|
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '6.0.0'
|
||||||
compile group: 'net.sf.supercsv', name: 'super-csv', version: '2.4.0'
|
testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '3.0'
|
||||||
compile group: 'commons-validator', name: 'commons-validator', version: '1.5.1'
|
testImplementation group: 'org.mockito', name: 'mockito-core', version:'5.20.0'
|
||||||
compile group: 'de.jensd', name: 'fontawesomefx-commons', version: '8.12'
|
|
||||||
compile group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.6.3'
|
// runtime libraries - bumped to recent stable versions where compatible
|
||||||
compile group: 'de.jensd', name: 'fontawesomefx-materialdesignfont', version: '1.6.50'
|
implementation group: 'org.apache.groovy', name: 'groovy', version: '5.0.2'
|
||||||
compile group: 'de.jensd', name: 'fontawesomefx-materialicons', version: '2.2.0'
|
implementation group: 'org.springframework', name: 'spring-context', version: '6.2.12'
|
||||||
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.11'
|
implementation group: 'de.siegmar', name: 'fastcsv', version: '4.1.0'
|
||||||
compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
|
implementation group: 'commons-validator', name: 'commons-validator', version: '1.10.0'
|
||||||
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2'
|
implementation group: 'de.jensd', name: 'fontawesomefx-commons', version: '9.1.2'
|
||||||
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2'
|
implementation group: 'de.jensd', name: 'fontawesomefx-fontawesome', version: '4.7.0-9.1.2'
|
||||||
compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.6.10'
|
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) {
|
test {
|
||||||
gradleVersion = '2.14.1' //version required
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
group 'ninja.javafx'
|
||||||
|
version '1.5.0'
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass = 'ninja.javafx.smartcsv.Main'
|
||||||
|
applicationDefaultJvmArgs = ["--enable-native-access=javafx.graphics"]
|
||||||
}
|
}
|
||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
|||||||
#Sat Jul 23 09:35:51 CEST 2016
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip
|
|
||||||
|
|||||||
100
gradlew
vendored
Normal file → Executable file
100
gradlew
vendored
Normal file → Executable 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
|
# Attempt to set APP_HOME
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
PRG="$0"
|
||||||
@@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null
|
|||||||
APP_HOME="`pwd -P`"
|
APP_HOME="`pwd -P`"
|
||||||
cd "$SAVED" >/dev/null
|
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
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -85,7 +89,7 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
@@ -150,11 +154,19 @@ if $cygwin ; then
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
|
|||||||
12
gradlew.bat
vendored
12
gradlew.bat
vendored
@@ -8,14 +8,14 @@
|
|||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
@@ -49,7 +49,6 @@ goto fail
|
|||||||
@rem Get command-line arguments, handling Windows variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
@@ -60,11 +59,6 @@ set _SKIP=2
|
|||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
rootProject.name = 'SmartCSV.ninja.javafx.smartcsv.fx'
|
rootProject.name = 'SmartCSV.fx'
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
36
src/main/java/ninja/javafx/smartcsv/Main.java
Normal file
36
src/main/java/ninja/javafx/smartcsv/Main.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,20 +26,29 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.csv;
|
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 {
|
public class CSVConfigurable {
|
||||||
|
|
||||||
protected CsvPreference csvPreference;
|
protected Preferences csvPreference;
|
||||||
|
|
||||||
|
protected String fileEncoding;
|
||||||
|
|
||||||
public CSVConfigurable() {
|
public CSVConfigurable() {
|
||||||
csvPreference = CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE;
|
csvPreference = defaultPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCsvPreference(CsvPreference csvPreference) {
|
public void setCsvPreference(Preferences csvPreference) {
|
||||||
this.csvPreference = csvPreference;
|
this.csvPreference = csvPreference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFileEncoding(String fileEncoding) {
|
||||||
|
this.fileEncoding = fileEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,16 +26,14 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.csv;
|
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.FileReader;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.supercsv.io.CsvMapReader;
|
|
||||||
import org.supercsv.io.ICsvMapReader;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reads the csv file and stores the values in csv model
|
* reads the csv file and stores the values in csv model
|
||||||
@@ -47,30 +45,44 @@ public class CSVFileReader extends CSVConfigurable implements FileReader<CSVMode
|
|||||||
@Override
|
@Override
|
||||||
public void read(File file) throws IOException {
|
public void read(File file) throws IOException {
|
||||||
|
|
||||||
ICsvMapReader mapReader = null;
|
System.out.println(csvPreference);
|
||||||
try {
|
try (var csv = getNamedCsvReader(file)) {
|
||||||
mapReader = new CsvMapReader(new java.io.FileReader(file.getAbsoluteFile()), csvPreference);
|
|
||||||
model = new CSVModel();
|
model = new CSVModel();
|
||||||
|
|
||||||
// the header columns are used as the keys to the Map
|
// the header columns are used as the keys to the Map
|
||||||
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);
|
model.setHeader(header);
|
||||||
|
|
||||||
Map<String, String> customerMap;
|
csv.forEach(csvRow -> {
|
||||||
while ((customerMap = mapReader.read(header)) != null) {
|
var row = model.addRow();
|
||||||
CSVRow row = model.addRow();
|
|
||||||
for (String column : header) {
|
for (String column : header) {
|
||||||
row.addValue(column, customerMap.get(column));
|
model.addValue(row, column, csvRow.getField(column));
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
} finally {
|
} catch (IOException ex) {
|
||||||
if (mapReader != null) {
|
// TODO perhaps a custom NinjaException that can properly identify and localize the exception message
|
||||||
mapReader.close();
|
// 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() {
|
public CSVModel getContent() {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,18 +26,17 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.csv;
|
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.CSVModel;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.supercsv.io.CsvMapWriter;
|
|
||||||
import org.supercsv.io.ICsvMapWriter;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
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
|
* filewriter for the csv
|
||||||
@@ -52,21 +51,22 @@ public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smart
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(File filename) throws IOException {
|
public void write(File filename) throws IOException {
|
||||||
ICsvMapWriter mapWriter = null;
|
try (var writer = getCsvWriter(filename)){
|
||||||
try {
|
writer.writeRecord(model.getHeader());
|
||||||
mapWriter = new CsvMapWriter(new FileWriter(filename.getAbsolutePath()), csvPreference);
|
|
||||||
mapWriter.writeHeader(model.getHeader());
|
|
||||||
|
|
||||||
for(CSVRow row: model.getRows()) {
|
for(CSVRow row: model.getRows()) {
|
||||||
Map<String, String> columns = convertMapFromModel(row);
|
writer.writeRecord(convertMapFromModel(row));
|
||||||
mapWriter.write(columns, model.getHeader());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,13 +74,8 @@ public class CSVFileWriter extends CSVConfigurable implements ninja.javafx.smart
|
|||||||
* @param row the row to convert
|
* @param row the row to convert
|
||||||
* @return a simple map for the supercvs writer
|
* @return a simple map for the supercvs writer
|
||||||
*/
|
*/
|
||||||
private Map<String, String> convertMapFromModel(CSVRow row) {
|
private List<String> convertMapFromModel(CSVRow row) {
|
||||||
return row.getColumns().entrySet().stream()
|
return row.getColumns().values().stream().map(v -> v.get().getValue())
|
||||||
.collect(
|
.collect(toList());
|
||||||
toMap(
|
|
||||||
Map.Entry::getKey,
|
|
||||||
e -> e.getValue().getValue().getValue() != null ? e.getValue().getValue().getValue() : ""
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
96
src/main/java/ninja/javafx/smartcsv/export/ErrorExport.java
Normal file
96
src/main/java/ninja/javafx/smartcsv/export/ErrorExport.java
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
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 java.io.File;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import static java.text.MessageFormat.format;
|
||||||
|
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this class exports the error messages into a log file
|
||||||
|
*/
|
||||||
|
@org.springframework.stereotype.Service
|
||||||
|
public class ErrorExport extends Service {
|
||||||
|
|
||||||
|
private CSVModel model;
|
||||||
|
private File file;
|
||||||
|
private ResourceBundle resourceBundle;
|
||||||
|
private String csvFilename;
|
||||||
|
|
||||||
|
public void setCsvFilename(String csvFilename) {
|
||||||
|
this.csvFilename = csvFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceBundle(ResourceBundle resourceBundle) {
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModel(CSVModel model) {
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFile(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task createTask() {
|
||||||
|
return new Task() {
|
||||||
|
@Override
|
||||||
|
protected Void call() throws Exception {
|
||||||
|
try {
|
||||||
|
StringWriter log = new StringWriter();
|
||||||
|
log.append(
|
||||||
|
format(resourceBundle.getString("log.header.message"),
|
||||||
|
csvFilename,
|
||||||
|
Integer.toString(model.getValidationError().size()))).append("\n\n");
|
||||||
|
model.getValidationError().forEach(error ->
|
||||||
|
log.append(
|
||||||
|
format(resourceBundle.getString("log.message"),
|
||||||
|
error.getLineNumber().toString(),
|
||||||
|
error.getColumn(),
|
||||||
|
getI18nValidatioMessage(resourceBundle, error))).append("\n")
|
||||||
|
);
|
||||||
|
Files.write(file.toPath(), log.toString().getBytes());
|
||||||
|
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
package ninja.javafx.smartcsv.files;
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
@@ -11,7 +37,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class stores files and there state
|
* This class stores files and their state
|
||||||
* @author abi
|
* @author abi
|
||||||
*/
|
*/
|
||||||
public class FileStorage<E> {
|
public class FileStorage<E> {
|
||||||
@@ -26,7 +52,7 @@ public class FileStorage<E> {
|
|||||||
|
|
||||||
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
|
private BooleanProperty fileChanged = new SimpleBooleanProperty(true);
|
||||||
private ObjectProperty<File> file = new SimpleObjectProperty<>();
|
private ObjectProperty<File> file = new SimpleObjectProperty<>();
|
||||||
private ObjectProperty<E> content = new SimpleObjectProperty<E>();
|
private ObjectProperty<E> content = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
public boolean isFileChanged() {
|
public boolean isFileChanged() {
|
||||||
return fileChanged.get();
|
return fileChanged.get();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,11 +28,10 @@ package ninja.javafx.smartcsv.fx;
|
|||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.event.EventHandler;
|
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.WindowEvent;
|
|
||||||
import ninja.javafx.smartcsv.fx.about.AboutController;
|
import ninja.javafx.smartcsv.fx.about.AboutController;
|
||||||
import org.springframework.context.annotation.*;
|
import org.springframework.context.annotation.*;
|
||||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||||
@@ -86,9 +85,12 @@ public class SmartCSV extends Application {
|
|||||||
private void showUI(Stage primaryStage, String name, String version) {
|
private void showUI(Stage primaryStage, String name, String version) {
|
||||||
SmartCSVController smartCVSController = appContext.getBean(SmartCSVController.class);
|
SmartCSVController smartCVSController = appContext.getBean(SmartCSVController.class);
|
||||||
Scene scene = new Scene((Parent) smartCVSController.getView());
|
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.setScene(scene);
|
||||||
primaryStage.setTitle(String.format("%s %s", name, version));
|
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.show();
|
||||||
primaryStage.setMaximized(true);
|
primaryStage.setMaximized(true);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.fx;
|
package ninja.javafx.smartcsv.fx;
|
||||||
|
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.WeakListChangeListener;
|
import javafx.collections.WeakListChangeListener;
|
||||||
import javafx.concurrent.WorkerStateEvent;
|
import javafx.concurrent.WorkerStateEvent;
|
||||||
@@ -34,37 +36,41 @@ import javafx.event.EventHandler;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.input.Dragboard;
|
||||||
|
import javafx.scene.input.TransferMode;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.BorderPane;
|
import javafx.scene.layout.BorderPane;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
import ninja.javafx.smartcsv.csv.CSVFileReader;
|
import ninja.javafx.smartcsv.csv.CSVFileReader;
|
||||||
import ninja.javafx.smartcsv.csv.CSVFileWriter;
|
import ninja.javafx.smartcsv.csv.CSVFileWriter;
|
||||||
|
import ninja.javafx.smartcsv.export.ErrorExport;
|
||||||
import ninja.javafx.smartcsv.files.FileStorage;
|
import ninja.javafx.smartcsv.files.FileStorage;
|
||||||
import ninja.javafx.smartcsv.fx.about.AboutController;
|
import ninja.javafx.smartcsv.fx.about.AboutController;
|
||||||
import ninja.javafx.smartcsv.fx.list.ErrorSideBar;
|
import ninja.javafx.smartcsv.fx.list.ErrorSideBar;
|
||||||
|
import ninja.javafx.smartcsv.fx.list.GotoLineDialog;
|
||||||
import ninja.javafx.smartcsv.fx.preferences.PreferencesController;
|
import ninja.javafx.smartcsv.fx.preferences.PreferencesController;
|
||||||
import ninja.javafx.smartcsv.fx.table.ObservableMapValueFactory;
|
import ninja.javafx.smartcsv.fx.table.ObservableMapValueFactory;
|
||||||
import ninja.javafx.smartcsv.fx.table.ValidationCellFactory;
|
import ninja.javafx.smartcsv.fx.table.ValidationCellFactory;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
|
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.LoadFileService;
|
||||||
import ninja.javafx.smartcsv.fx.util.SaveFileService;
|
import ninja.javafx.smartcsv.fx.util.SaveFileService;
|
||||||
import ninja.javafx.smartcsv.fx.validation.ValidationEditorController;
|
import ninja.javafx.smartcsv.fx.validation.ValidationEditorController;
|
||||||
import ninja.javafx.smartcsv.preferences.PreferencesFileReader;
|
import ninja.javafx.smartcsv.preferences.*;
|
||||||
import ninja.javafx.smartcsv.preferences.PreferencesFileWriter;
|
|
||||||
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
|
|
||||||
import ninja.javafx.smartcsv.validation.ValidationError;
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
import ninja.javafx.smartcsv.validation.ValidationFileReader;
|
import ninja.javafx.smartcsv.validation.ValidationFileReader;
|
||||||
import ninja.javafx.smartcsv.validation.ValidationFileWriter;
|
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.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.supercsv.prefs.CsvPreference;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
@@ -74,6 +80,7 @@ import static javafx.application.Platform.exit;
|
|||||||
import static javafx.application.Platform.runLater;
|
import static javafx.application.Platform.runLater;
|
||||||
import static javafx.beans.binding.Bindings.*;
|
import static javafx.beans.binding.Bindings.*;
|
||||||
import static javafx.scene.layout.AnchorPane.*;
|
import static javafx.scene.layout.AnchorPane.*;
|
||||||
|
import static ninja.javafx.smartcsv.preferences.Preferences.defaultPreferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* main controller of the application
|
* main controller of the application
|
||||||
@@ -81,6 +88,7 @@ import static javafx.scene.layout.AnchorPane.*;
|
|||||||
@Component
|
@Component
|
||||||
public class SmartCSVController extends FXMLController {
|
public class SmartCSVController extends FXMLController {
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// constants
|
// constants
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -90,10 +98,20 @@ public class SmartCSVController extends FXMLController {
|
|||||||
".SmartCSV.fx" +
|
".SmartCSV.fx" +
|
||||||
File.separator + "" +
|
File.separator + "" +
|
||||||
"preferences.json");
|
"preferences.json");
|
||||||
|
|
||||||
|
private static final File ENCODING_FILE = new File(System.getProperty("user.home") +
|
||||||
|
File.separator +
|
||||||
|
".SmartCSV.fx" +
|
||||||
|
File.separator +
|
||||||
|
"encoding.json");
|
||||||
|
|
||||||
public static final String CSV_FILTER_TEXT = "CSV files (*.csv)";
|
public static final String CSV_FILTER_TEXT = "CSV files (*.csv)";
|
||||||
public static final String CSV_FILTER_EXTENSION = "*.csv";
|
public static final String CSV_FILTER_EXTENSION = "*.csv";
|
||||||
public static final String JSON_FILTER_TEXT = "JSON files (*.json)";
|
public static final String JSON_FILTER_TEXT = "JSON files (*.json)";
|
||||||
public static final String JSON_FILTER_EXTENSION = "*.json";
|
public static final String JSON_FILTER_EXTENSION = "*.json";
|
||||||
|
public static final String EXPORT_LOG_FILTER_TEXT = "Error log files (*.log)";
|
||||||
|
public static final String EXPORT_LOG_FILTER_EXTENSION = "*.log";
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// injections
|
// injections
|
||||||
@@ -114,6 +132,9 @@ public class SmartCSVController extends FXMLController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SaveFileService saveFileService;
|
private SaveFileService saveFileService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ErrorExport errorExport;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private BorderPane applicationPane;
|
private BorderPane applicationPane;
|
||||||
|
|
||||||
@@ -153,6 +174,12 @@ public class SmartCSVController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private MenuItem addRowMenuItem;
|
private MenuItem addRowMenuItem;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private MenuItem gotoLineMenuItem;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private MenuItem exportMenuItem;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button saveButton;
|
private Button saveButton;
|
||||||
|
|
||||||
@@ -177,6 +204,15 @@ public class SmartCSVController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private Button addRowButton;
|
private Button addRowButton;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button exportButton;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label currentLineNumber;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label totalNumberOfLines;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// members
|
// members
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -186,10 +222,13 @@ public class SmartCSVController extends FXMLController {
|
|||||||
private TableView<CSVRow> tableView;
|
private TableView<CSVRow> tableView;
|
||||||
private ErrorSideBar errorSideBar;
|
private ErrorSideBar errorSideBar;
|
||||||
private ResourceBundle resourceBundle;
|
private ResourceBundle resourceBundle;
|
||||||
|
private CSVFileReader csvFileReader = new CSVFileReader();
|
||||||
|
private CSVFileWriter csvFileWriter = new CSVFileWriter();
|
||||||
|
|
||||||
private FileStorage<CSVModel> currentCsvFile = new FileStorage<>(new CSVFileReader(), new CSVFileWriter());
|
private FileStorage<CSVModel> currentCsvFile = new FileStorage<>(csvFileReader, csvFileWriter);
|
||||||
private FileStorage<ValidationConfiguration> currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter());
|
private FileStorage<ValidationConfiguration> currentConfigFile = new FileStorage<>(new ValidationFileReader(), new ValidationFileWriter());
|
||||||
private FileStorage<CsvPreference> csvPreferenceFile = new FileStorage<>(new PreferencesFileReader(), new PreferencesFileWriter());
|
private FileStorage<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 ListChangeListener<ValidationError> errorListListener = c -> tableView.refresh();
|
||||||
private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener);
|
private WeakListChangeListener<ValidationError> weakErrorListListener = new WeakListChangeListener<>(errorListListener);
|
||||||
@@ -205,7 +244,7 @@ public class SmartCSVController extends FXMLController {
|
|||||||
setupTableCellFactory();
|
setupTableCellFactory();
|
||||||
setupErrorSideBar(resourceBundle);
|
setupErrorSideBar(resourceBundle);
|
||||||
|
|
||||||
bindMenuItemsToContentExistence(currentCsvFile, saveMenuItem, saveAsMenuItem, addRowMenuItem, createConfigMenuItem, loadConfigMenuItem);
|
bindMenuItemsToContentExistence(currentCsvFile, saveMenuItem, saveAsMenuItem, addRowMenuItem, gotoLineMenuItem, createConfigMenuItem, loadConfigMenuItem);
|
||||||
bindButtonsToContentExistence(currentCsvFile, saveButton, saveAsButton, addRowButton, createConfigButton, loadConfigButton);
|
bindButtonsToContentExistence(currentCsvFile, saveButton, saveAsButton, addRowButton, createConfigButton, loadConfigButton);
|
||||||
|
|
||||||
bindMenuItemsToContentExistence(currentConfigFile, saveConfigMenuItem, saveAsConfigMenuItem);
|
bindMenuItemsToContentExistence(currentConfigFile, saveConfigMenuItem, saveAsConfigMenuItem);
|
||||||
@@ -215,8 +254,51 @@ public class SmartCSVController extends FXMLController {
|
|||||||
bindConfigFileName();
|
bindConfigFileName();
|
||||||
|
|
||||||
csvPreferenceFile.setFile(PREFERENCES_FILE);
|
csvPreferenceFile.setFile(PREFERENCES_FILE);
|
||||||
|
fileEncodingFile.setFile(ENCODING_FILE);
|
||||||
|
|
||||||
loadCsvPreferencesFromFile();
|
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) {
|
private void setupErrorSideBar(ResourceBundle resourceBundle) {
|
||||||
@@ -319,11 +401,32 @@ public class SmartCSVController extends FXMLController {
|
|||||||
Optional<ButtonType> result = alert.showAndWait();
|
Optional<ButtonType> result = alert.showAndWait();
|
||||||
|
|
||||||
if (result.get() == ButtonType.OK){
|
if (result.get() == ButtonType.OK){
|
||||||
CsvPreference csvPreference = preferencesController.getCsvPreference();
|
Preferences csvPreference = preferencesController.getCsvPreference();
|
||||||
setCsvPreference(csvPreference);
|
setCsvPreference(csvPreference);
|
||||||
saveCsvPreferences(csvPreference);
|
saveCsvPreferences(csvPreference);
|
||||||
|
String fileEncoding = CharsetHelper.getCharsetName(preferencesController.getFileEncoding());
|
||||||
|
setFileEncoding(fileEncoding);
|
||||||
|
saveFileEncoding(fileEncoding);
|
||||||
} else {
|
} else {
|
||||||
preferencesController.setCsvPreference(csvPreferenceFile.getContent());
|
preferencesController.setCsvPreference(csvPreferenceFile.getContent());
|
||||||
|
preferencesController.setFileEncoding(fileEncodingFile.getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveFileEncoding(String fileEncoding) {
|
||||||
|
try {
|
||||||
|
createFileEncodingFile();
|
||||||
|
fileEncodingFile.setContent(fileEncoding);
|
||||||
|
useSaveFileService(fileEncodingFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createFileEncodingFile() throws IOException {
|
||||||
|
if (!fileEncodingFile.getFile().exists()) {
|
||||||
|
createPreferencesFileFolder();
|
||||||
|
fileEncodingFile.getFile().createNewFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +441,7 @@ public class SmartCSVController extends FXMLController {
|
|||||||
public void addRow(ActionEvent actionEvent) {
|
public void addRow(ActionEvent actionEvent) {
|
||||||
CSVRow row = currentCsvFile.getContent().addRow();
|
CSVRow row = currentCsvFile.getContent().addRow();
|
||||||
for (String column : currentCsvFile.getContent().getHeader()) {
|
for (String column : currentCsvFile.getContent().getHeader()) {
|
||||||
row.addValue(column, "");
|
currentCsvFile.getContent().addValue(row, column, "");
|
||||||
}
|
}
|
||||||
currentCsvFile.setFileChanged(true);
|
currentCsvFile.setFileChanged(true);
|
||||||
resetContent();
|
resetContent();
|
||||||
@@ -346,6 +449,43 @@ public class SmartCSVController extends FXMLController {
|
|||||||
selectNewRow();
|
selectNewRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void gotoLine(ActionEvent actionEvent) {
|
||||||
|
int maxLineNumber = currentCsvFile.getContent().getRows().size();
|
||||||
|
GotoLineDialog dialog = new GotoLineDialog(maxLineNumber);
|
||||||
|
dialog.setTitle(resourceBundle.getString("dialog.goto.line.title"));
|
||||||
|
dialog.setHeaderText(format(resourceBundle.getString("dialog.goto.line.header.text"), maxLineNumber));
|
||||||
|
dialog.setContentText(resourceBundle.getString("dialog.goto.line.label"));
|
||||||
|
Optional<Integer> result = dialog.showAndWait();
|
||||||
|
if (result.isPresent()){
|
||||||
|
Integer lineNumber = result.get();
|
||||||
|
if (lineNumber != null) {
|
||||||
|
tableView.scrollTo(max(0, lineNumber - 2));
|
||||||
|
tableView.getSelectionModel().select(lineNumber - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void export(ActionEvent actionEvent) {
|
||||||
|
final FileChooser fileChooser = new FileChooser();
|
||||||
|
|
||||||
|
//Set extension filter
|
||||||
|
final FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(EXPORT_LOG_FILTER_TEXT, EXPORT_LOG_FILTER_EXTENSION);
|
||||||
|
fileChooser.getExtensionFilters().add(extFilter);
|
||||||
|
fileChooser.setTitle("Save");
|
||||||
|
|
||||||
|
//Show open file dialog
|
||||||
|
File file = fileChooser.showSaveDialog(applicationPane.getScene().getWindow());
|
||||||
|
if (file != null) {
|
||||||
|
errorExport.setCsvFilename(currentCsvFile.getFile().getName());
|
||||||
|
errorExport.setModel(currentCsvFile.getContent());
|
||||||
|
errorExport.setFile(file);
|
||||||
|
errorExport.setResourceBundle(resourceBundle);
|
||||||
|
errorExport.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canExit() {
|
public boolean canExit() {
|
||||||
boolean canExit = true;
|
boolean canExit = true;
|
||||||
if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
|
if (currentCsvFile.getContent() != null && currentCsvFile.isFileChanged()) {
|
||||||
@@ -363,8 +503,25 @@ public class SmartCSVController extends FXMLController {
|
|||||||
return canExit;
|
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) {
|
public void showValidationEditor(String column) {
|
||||||
validationEditorController.setSelectedColumn(column);
|
validationEditorController.setSelectedColumn(column);
|
||||||
|
validationEditorController.updateForm();
|
||||||
|
|
||||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
alert.setGraphic(null);
|
alert.setGraphic(null);
|
||||||
@@ -377,7 +534,7 @@ public class SmartCSVController extends FXMLController {
|
|||||||
runLater(() -> {
|
runLater(() -> {
|
||||||
validationEditorController.updateConfiguration();
|
validationEditorController.updateConfiguration();
|
||||||
currentCsvFile.setFileChanged(true);
|
currentCsvFile.setFileChanged(true);
|
||||||
currentCsvFile.getContent().revalidate();
|
currentCsvFile.getContent().revalidate(column);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,15 +582,23 @@ public class SmartCSVController extends FXMLController {
|
|||||||
configurationName.textProperty().bind(selectString(currentConfigFile.fileProperty(), "name"));
|
configurationName.textProperty().bind(selectString(currentConfigFile.fileProperty(), "name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bindLineNumber() {
|
||||||
|
currentLineNumber.textProperty().bind(tableView.getSelectionModel().selectedIndexProperty().add(1).asString());
|
||||||
|
}
|
||||||
|
|
||||||
private void loadCsvPreferencesFromFile() {
|
private void loadCsvPreferencesFromFile() {
|
||||||
if (csvPreferenceFile.getFile().exists()) {
|
if (csvPreferenceFile.getFile().exists()) {
|
||||||
useLoadFileService(csvPreferenceFile, event -> setCsvPreference(csvPreferenceFile.getContent()));
|
useLoadFileService(csvPreferenceFile, event -> {
|
||||||
|
setCsvPreference(csvPreferenceFile.getContent());
|
||||||
|
loadEncodingFromFile();
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
setCsvPreference(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);
|
setCsvPreference(defaultPreferences());
|
||||||
|
loadEncodingFromFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveCsvPreferences(CsvPreference csvPreference) {
|
private void saveCsvPreferences(Preferences csvPreference) {
|
||||||
try {
|
try {
|
||||||
createPreferenceFile();
|
createPreferenceFile();
|
||||||
csvPreferenceFile.setContent(csvPreference);
|
csvPreferenceFile.setContent(csvPreference);
|
||||||
@@ -456,8 +621,11 @@ public class SmartCSVController extends FXMLController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCsvPreference(CsvPreference csvPreference) {
|
private void setCsvPreference(Preferences csvPreference) {
|
||||||
preferencesController.setCsvPreference(csvPreference);
|
preferencesController.setCsvPreference(csvPreference);
|
||||||
|
csvFileReader.setCsvPreference(csvPreference);
|
||||||
|
csvFileWriter.setCsvPreference(csvPreference);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadFile(String filterText,
|
private void loadFile(String filterText,
|
||||||
@@ -477,9 +645,14 @@ public class SmartCSVController extends FXMLController {
|
|||||||
|
|
||||||
//Show open file dialog
|
//Show open file dialog
|
||||||
File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
|
File file = fileChooser.showOpenDialog(applicationPane.getScene().getWindow());
|
||||||
|
openFile(storageFile, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openFile(FileStorage storageFile, File file) {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
File previousFile = storageFile.getFile();
|
||||||
storageFile.setFile(file);
|
storageFile.setFile(file);
|
||||||
useLoadFileService(storageFile, t -> resetContent());
|
useLoadFileService(storageFile, t -> resetContent(), () -> storageFile.setFile(previousFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,13 +681,20 @@ public class SmartCSVController extends FXMLController {
|
|||||||
return file;
|
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.setFileStorage(fileStorage);
|
||||||
loadFileService.restart();
|
loadFileService.restart();
|
||||||
loadFileService.setOnSucceeded(onSucceededHandler);
|
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.setFileStorage(fileStorage);
|
||||||
saveFileService.restart();
|
saveFileService.restart();
|
||||||
saveFileService.setOnSucceeded(t -> resetContent());
|
saveFileService.setOnSucceeded(t -> resetContent());
|
||||||
@@ -524,11 +704,14 @@ public class SmartCSVController extends FXMLController {
|
|||||||
* Creates new table view and add the new content
|
* Creates new table view and add the new content
|
||||||
*/
|
*/
|
||||||
private void resetContent() {
|
private void resetContent() {
|
||||||
|
resetExportButtons();
|
||||||
|
|
||||||
if (currentCsvFile.getContent() != null) {
|
if (currentCsvFile.getContent() != null) {
|
||||||
currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener);
|
currentCsvFile.getContent().getValidationError().addListener(weakErrorListListener);
|
||||||
currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent());
|
currentCsvFile.getContent().setValidationConfiguration(currentConfigFile.getContent());
|
||||||
validationEditorController.setValidationConfiguration(currentConfigFile.getContent());
|
validationEditorController.setValidationConfiguration(currentConfigFile.getContent());
|
||||||
tableView = new TableView<>();
|
tableView = new TableView<>();
|
||||||
|
bindLineNumber();
|
||||||
|
|
||||||
bindMenuItemsToTableSelection(deleteRowMenuItem);
|
bindMenuItemsToTableSelection(deleteRowMenuItem);
|
||||||
bindButtonsToTableSelection(deleteRowButton);
|
bindButtonsToTableSelection(deleteRowButton);
|
||||||
@@ -537,24 +720,43 @@ public class SmartCSVController extends FXMLController {
|
|||||||
addColumn(column, tableView);
|
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.getItems().setAll(currentCsvFile.getContent().getRows());
|
||||||
tableView.setEditable(true);
|
tableView.setEditable(true);
|
||||||
|
|
||||||
|
totalNumberOfLines.textProperty().setValue("" + currentCsvFile.getContent().getRows().size());
|
||||||
|
|
||||||
setBottomAnchor(tableView, 0.0);
|
setBottomAnchor(tableView, 0.0);
|
||||||
setTopAnchor(tableView, 0.0);
|
setTopAnchor(tableView, 0.0);
|
||||||
setLeftAnchor(tableView, 0.0);
|
setLeftAnchor(tableView, 0.0);
|
||||||
setRightAnchor(tableView, 0.0);
|
setRightAnchor(tableView, 0.0);
|
||||||
tableWrapper.getChildren().setAll(tableView);
|
tableWrapper.getChildren().setAll(tableView);
|
||||||
errorSideBar.setModel(currentCsvFile.getContent());
|
errorSideBar.setModel(currentCsvFile.getContent());
|
||||||
|
binExportButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void binExportButtons() {
|
||||||
|
exportButton.disableProperty().bind(Bindings.isEmpty(currentCsvFile.getContent().getValidationError()));
|
||||||
|
exportMenuItem.disableProperty().bind(Bindings.isEmpty(currentCsvFile.getContent().getValidationError()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetExportButtons() {
|
||||||
|
exportButton.disableProperty().unbind();
|
||||||
|
exportMenuItem.disableProperty().unbind();
|
||||||
|
exportButton.disableProperty().setValue(true);
|
||||||
|
exportMenuItem.disableProperty().setValue(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a column with the given name to the tableview
|
* Adds a column with the given name to the tableview
|
||||||
* @param header name of the column header
|
* @param header name of the column header
|
||||||
* @param tableView the tableview
|
* @param tableView the tableview
|
||||||
*/
|
*/
|
||||||
private void addColumn(String header, TableView tableView) {
|
private void addColumn(final String header, TableView tableView) {
|
||||||
TableColumn column = new TableColumn(header);
|
TableColumn column = new TableColumn(header);
|
||||||
column.setCellValueFactory(new ObservableMapValueFactory(header));
|
column.setCellValueFactory(new ObservableMapValueFactory(header));
|
||||||
column.setCellFactory(cellFactory);
|
column.setCellFactory(cellFactory);
|
||||||
@@ -571,7 +773,6 @@ public class SmartCSVController extends FXMLController {
|
|||||||
getColumns().get(header).setValue(event.getNewValue());
|
getColumns().get(header).setValue(event.getNewValue());
|
||||||
runLater(() -> {
|
runLater(() -> {
|
||||||
currentCsvFile.setFileChanged(true);
|
currentCsvFile.setFileChanged(true);
|
||||||
currentCsvFile.getContent().revalidate();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -36,7 +36,6 @@ import javafx.scene.layout.Region;
|
|||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
import ninja.javafx.smartcsv.fx.table.model.CSVModel;
|
||||||
import ninja.javafx.smartcsv.fx.util.ColorConstants;
|
|
||||||
import ninja.javafx.smartcsv.validation.ValidationError;
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -49,7 +48,7 @@ import java.util.ResourceBundle;
|
|||||||
import static javafx.geometry.Pos.CENTER;
|
import static javafx.geometry.Pos.CENTER;
|
||||||
import static ninja.javafx.smartcsv.fx.util.ColorConstants.ERROR_COLOR;
|
import static ninja.javafx.smartcsv.fx.util.ColorConstants.ERROR_COLOR;
|
||||||
import static ninja.javafx.smartcsv.fx.util.ColorConstants.OK_COLOR;
|
import static ninja.javafx.smartcsv.fx.util.ColorConstants.OK_COLOR;
|
||||||
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessage;
|
import static ninja.javafx.smartcsv.fx.util.I18nValidationUtil.getI18nValidatioMessageWithColumn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clickable side bar with error markers
|
* clickable side bar with error markers
|
||||||
@@ -138,9 +137,7 @@ public class ErrorSideBar extends Region {
|
|||||||
|
|
||||||
int rows = model.get().getRows().size();
|
int rows = model.get().getRows().size();
|
||||||
double space = (double)heightWithoutStatusBlock() / rows;
|
double space = (double)heightWithoutStatusBlock() / rows;
|
||||||
for (ValidationError error : errorList) {
|
errorList.forEach(error -> errorMarkerList.add(generateErrorMarker(space, error)));
|
||||||
errorMarkerList.add(generateErrorMarker(space, error));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getChildren().setAll(errorMarkerList);
|
getChildren().setAll(errorMarkerList);
|
||||||
@@ -159,7 +156,7 @@ public class ErrorSideBar extends Region {
|
|||||||
errorMarker.setStyle("-fx-background-color: " + ERROR_COLOR);
|
errorMarker.setStyle("-fx-background-color: " + ERROR_COLOR);
|
||||||
errorMarker.setOnMouseClicked(event -> selectedValidationError.setValue(error));
|
errorMarker.setOnMouseClicked(event -> selectedValidationError.setValue(error));
|
||||||
errorMarker.setOnMouseEntered(event -> {
|
errorMarker.setOnMouseEntered(event -> {
|
||||||
popOver.setContentNode(popupContent(getI18nValidatioMessage(resourceBundle, error)));
|
popOver.setContentNode(popupContent(getI18nValidatioMessageWithColumn(resourceBundle, error)));
|
||||||
popOver.show(errorMarker, -16);
|
popOver.show(errorMarker, -16);
|
||||||
});
|
});
|
||||||
return errorMarker;
|
return errorMarker;
|
||||||
|
|||||||
113
src/main/java/ninja/javafx/smartcsv/fx/list/GotoLineDialog.java
Normal file
113
src/main/java/ninja/javafx/smartcsv/fx/list/GotoLineDialog.java
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class GotoLineDialog extends Dialog<Integer> {
|
||||||
|
|
||||||
|
private final GridPane grid;
|
||||||
|
private final Label label;
|
||||||
|
private final TextField textField;
|
||||||
|
|
||||||
|
public GotoLineDialog(int maxLineNumber) {
|
||||||
|
final DialogPane dialogPane = getDialogPane();
|
||||||
|
|
||||||
|
this.textField = new TextField("");
|
||||||
|
this.textField.setMaxWidth(Double.MAX_VALUE);
|
||||||
|
|
||||||
|
UnaryOperator<TextFormatter.Change> filter = change -> {
|
||||||
|
String text = change.getText();
|
||||||
|
|
||||||
|
if (text.matches("[0-9]*")) {
|
||||||
|
try {
|
||||||
|
int lineNumber = Integer.parseInt(textField.getText() + text);
|
||||||
|
if (lineNumber <= maxLineNumber) {
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// this happens when focusing textfield or press special keys like DEL
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
TextFormatter<String> textFormatter = new TextFormatter<>(filter);
|
||||||
|
textField.setTextFormatter(textFormatter);
|
||||||
|
|
||||||
|
GridPane.setHgrow(textField, Priority.ALWAYS);
|
||||||
|
GridPane.setFillWidth(textField, true);
|
||||||
|
|
||||||
|
label = createContentLabel(dialogPane.getContentText());
|
||||||
|
label.setPrefWidth(Region.USE_COMPUTED_SIZE);
|
||||||
|
label.textProperty().bind(dialogPane.contentTextProperty());
|
||||||
|
|
||||||
|
this.grid = new GridPane();
|
||||||
|
this.grid.setHgap(10);
|
||||||
|
this.grid.setMaxWidth(Double.MAX_VALUE);
|
||||||
|
this.grid.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
|
||||||
|
dialogPane.contentTextProperty().addListener(o -> updateGrid());
|
||||||
|
|
||||||
|
dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL);
|
||||||
|
|
||||||
|
updateGrid();
|
||||||
|
|
||||||
|
setResultConverter((dialogButton) -> {
|
||||||
|
ButtonBar.ButtonData data = dialogButton == null ? null : dialogButton.getButtonData();
|
||||||
|
return data == ButtonBar.ButtonData.OK_DONE ? Integer.parseInt(textField.getText()) : null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Label createContentLabel(String text) {
|
||||||
|
Label label = new Label(text);
|
||||||
|
label.setMaxWidth(Double.MAX_VALUE);
|
||||||
|
label.setMaxHeight(Double.MAX_VALUE);
|
||||||
|
label.getStyleClass().add("content");
|
||||||
|
label.setWrapText(true);
|
||||||
|
label.setPrefWidth(360);
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGrid() {
|
||||||
|
grid.getChildren().clear();
|
||||||
|
|
||||||
|
grid.add(label, 0, 0);
|
||||||
|
grid.add(textField, 1, 0);
|
||||||
|
getDialogPane().setContent(grid);
|
||||||
|
|
||||||
|
Platform.runLater(() -> textField.requestFocus());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
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.TextField;
|
||||||
import javafx.scene.control.TextFormatter;
|
import javafx.scene.control.TextFormatter;
|
||||||
import ninja.javafx.smartcsv.fx.FXMLController;
|
import ninja.javafx.smartcsv.fx.FXMLController;
|
||||||
|
import ninja.javafx.smartcsv.preferences.Preferences;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.supercsv.prefs.CsvPreference;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteMode;
|
|
||||||
import static ninja.javafx.smartcsv.preferences.QuoteModeHelper.getQuoteModeName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* controller for preferences
|
* controller for preferences
|
||||||
*/
|
*/
|
||||||
@@ -57,14 +55,11 @@ public class PreferencesController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private TextField delimiterChar;
|
private TextField delimiterChar;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private CheckBox surroundingSpacesNeedQuotes;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox ignoreEmptyLines;
|
private CheckBox ignoreEmptyLines;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ComboBox<String> quoteMode;
|
private ComboBox<String> fileEncoding;
|
||||||
|
|
||||||
private String endOfLineSymbols;
|
private String endOfLineSymbols;
|
||||||
|
|
||||||
@@ -79,7 +74,7 @@ public class PreferencesController extends FXMLController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
quoteMode.getItems().addAll("normal", "always", "column");
|
fileEncoding.getItems().addAll(Charset.availableCharsets().keySet());
|
||||||
|
|
||||||
UnaryOperator<TextFormatter.Change> allowOnlyOneCharacter = change -> {
|
UnaryOperator<TextFormatter.Change> allowOnlyOneCharacter = change -> {
|
||||||
if (change.isContentChange()) {
|
if (change.isContentChange()) {
|
||||||
@@ -97,24 +92,31 @@ public class PreferencesController extends FXMLController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void revalidate() {
|
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) {
|
public void setCsvPreference(Preferences csvPreference) {
|
||||||
quoteChar.setText(Character.toString(csvPreference.getQuoteChar()));
|
if (csvPreference.quoteChar() != null) {
|
||||||
delimiterChar.setText(Character.toString((char)csvPreference.getDelimiterChar()));
|
quoteChar.setText(csvPreference.quoteChar().toString());
|
||||||
surroundingSpacesNeedQuotes.setSelected(csvPreference.isSurroundingSpacesNeedQuotes());
|
} else {
|
||||||
ignoreEmptyLines.setSelected(csvPreference.isIgnoreEmptyLines());
|
quoteChar.setText("");
|
||||||
quoteMode.getSelectionModel().select(getQuoteModeName(csvPreference.getQuoteMode()));
|
}
|
||||||
endOfLineSymbols = csvPreference.getEndOfLineSymbols();
|
delimiterChar.setText(Character.toString(csvPreference.delimiterChar()));
|
||||||
|
ignoreEmptyLines.setSelected(csvPreference.ignoreEmptyLines());
|
||||||
|
endOfLineSymbols = csvPreference.endOfLineSymbols();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CsvPreference getCsvPreference() {
|
public Preferences getCsvPreference() {
|
||||||
return new CsvPreference.Builder(quoteChar.getText().charAt(0), delimiterChar.getText().charAt(0), endOfLineSymbols)
|
var quote = quoteChar.getText().length() == 0 ? null : quoteChar.getText().charAt(0);
|
||||||
.useQuoteMode(getQuoteMode(quoteMode.getSelectionModel().getSelectedItem()))
|
return new Preferences(quote, delimiterChar.getText().charAt(0), endOfLineSymbols, ignoreEmptyLines.isSelected());
|
||||||
.surroundingSpacesNeedQuotes(surroundingSpacesNeedQuotes.isSelected())
|
}
|
||||||
.ignoreEmptyLines(ignoreEmptyLines.isSelected())
|
|
||||||
.build();
|
public void setFileEncoding(String fileEncoding) {
|
||||||
|
this.fileEncoding.setValue(fileEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileEncoding() {
|
||||||
|
return fileEncoding.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getValid() {
|
public boolean getValid() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -33,7 +33,6 @@ import javafx.scene.control.Tooltip;
|
|||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
||||||
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
|
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
|
||||||
import ninja.javafx.smartcsv.fx.util.ColorConstants;
|
|
||||||
|
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
@@ -66,8 +65,8 @@ public class EditableValidationCell extends TableCell<CSVRow, CSVValue> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelEdit() {
|
public void cancelEdit() {
|
||||||
super.cancelEdit();
|
|
||||||
setText(getItem().getValue());
|
setText(getItem().getValue());
|
||||||
|
super.cancelEdit();
|
||||||
setContentDisplay(ContentDisplay.TEXT_ONLY);
|
setContentDisplay(ContentDisplay.TEXT_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,19 +113,14 @@ public class EditableValidationCell extends TableCell<CSVRow, CSVValue> {
|
|||||||
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
|
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
|
||||||
textField.setOnKeyPressed(t -> {
|
textField.setOnKeyPressed(t -> {
|
||||||
if (t.getCode() == KeyCode.ENTER) {
|
if (t.getCode() == KeyCode.ENTER) {
|
||||||
commitEdit(textField.getValue());
|
runLater(() -> commitEdit(textField.getValue()));
|
||||||
} else if (t.getCode() == KeyCode.ESCAPE) {
|
} else if (t.getCode() == KeyCode.ESCAPE) {
|
||||||
cancelEdit();
|
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;
|
private CSVValue value;
|
||||||
|
|
||||||
public ValueTextField(CSVValue value) {
|
public ValueTextField(CSVValue value) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -47,7 +47,6 @@ public class ObservableMapValueFactory implements
|
|||||||
@Override
|
@Override
|
||||||
public ObjectProperty<CSVValue> call(TableColumn.CellDataFeatures<CSVRow, CSVValue> features) {
|
public ObjectProperty<CSVValue> call(TableColumn.CellDataFeatures<CSVRow, CSVValue> features) {
|
||||||
CSVRow row = features.getValue();
|
CSVRow row = features.getValue();
|
||||||
ObjectProperty<CSVValue> value = row.getColumns().get(key);
|
return row.getColumns().get(key);
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,42 +28,40 @@ package ninja.javafx.smartcsv.fx.table.model;
|
|||||||
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.concurrent.Service;
|
import ninja.javafx.smartcsv.validation.RevalidationService;
|
||||||
import javafx.concurrent.Task;
|
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
|
||||||
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
|
|
||||||
import ninja.javafx.smartcsv.validation.ValidationError;
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
import ninja.javafx.smartcsv.validation.Validator;
|
import ninja.javafx.smartcsv.validation.Validator;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The CSVModel is the client representation for the csv filepath.
|
* The CSVModel is the client representation for the csv filepath.
|
||||||
* It holds the data in rows, stores the header and manages the validator.
|
* It holds the data in rows, stores the header and manages the validator.
|
||||||
*/
|
*/
|
||||||
public class CSVModel {
|
public final class CSVModel implements ColumnValueProvider {
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger(CSVModel.class);
|
private static final Logger logger = LogManager.getLogger(CSVModel.class);
|
||||||
|
|
||||||
private Validator validator;
|
private Validator validator;
|
||||||
private ObservableList<CSVRow> rows = FXCollections.observableArrayList();
|
private ObservableList<CSVRow> rows = FXCollections.observableArrayList();
|
||||||
private String[] header;
|
private String[] header;
|
||||||
private ObservableList<ValidationError> validationError = FXCollections.observableArrayList();
|
private ObservableList<ValidationError> validationError = FXCollections.observableArrayList();
|
||||||
private RevalidationService revalidationService = new RevalidationService();
|
private RevalidationService revalidationService = new RevalidationService();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the validator configuration for the data revalidates
|
* sets the validator configuration for the data revalidates
|
||||||
|
*
|
||||||
* @param validationConfiguration the validator configuration for this data
|
* @param validationConfiguration the validator configuration for this data
|
||||||
*/
|
*/
|
||||||
public void setValidationConfiguration(ValidationConfiguration validationConfiguration) {
|
public void setValidationConfiguration(ValidationConfiguration validationConfiguration) {
|
||||||
this.validator = new Validator(validationConfiguration);
|
this.validator = new Validator(validationConfiguration, this);
|
||||||
revalidate();
|
revalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the data as a list of rows of the
|
* returns the data as a list of rows of the
|
||||||
|
*
|
||||||
* @return list of rows
|
* @return list of rows
|
||||||
*/
|
*/
|
||||||
public ObservableList<CSVRow> getRows() {
|
public ObservableList<CSVRow> getRows() {
|
||||||
@@ -76,18 +74,30 @@ public class CSVModel {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* adds a new and empty row
|
* adds a new and empty row
|
||||||
|
*
|
||||||
* @return the new row
|
* @return the new row
|
||||||
*/
|
*/
|
||||||
public CSVRow addRow() {
|
public CSVRow addRow() {
|
||||||
CSVRow row = new CSVRow();
|
CSVRow row = new CSVRow();
|
||||||
row.setValidator(validator);
|
|
||||||
row.setRowNumber(rows.size());
|
row.setRowNumber(rows.size());
|
||||||
rows.add(row);
|
rows.add(row);
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addValue(final CSVRow row, final String column, final String value) {
|
||||||
|
final CSVValue csvValue = row.addValue(column, value);
|
||||||
|
csvValue.valueProperty().addListener(observable -> {
|
||||||
|
if (validator.needsColumnValidation(column)) {
|
||||||
|
revalidate();
|
||||||
|
} else {
|
||||||
|
csvValue.setValidationError(validator.isValid(row.getRowNumber(), column, csvValue.getValue()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the column headers as string array
|
* sets the column headers as string array
|
||||||
|
*
|
||||||
* @param header the headers of the columns
|
* @param header the headers of the columns
|
||||||
*/
|
*/
|
||||||
public void setHeader(String[] header) {
|
public void setHeader(String[] header) {
|
||||||
@@ -97,6 +107,7 @@ public class CSVModel {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the column headers
|
* returns the column headers
|
||||||
|
*
|
||||||
* @return the column headers
|
* @return the column headers
|
||||||
*/
|
*/
|
||||||
public String[] getHeader() {
|
public String[] getHeader() {
|
||||||
@@ -104,6 +115,12 @@ public class CSVModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void revalidate(String column) {
|
||||||
|
if (!hasValidator()) return;
|
||||||
|
validator.reinitializeColumn(column);
|
||||||
|
revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* walks through the data and validates each value
|
* walks through the data and validates each value
|
||||||
*/
|
*/
|
||||||
@@ -113,8 +130,6 @@ public class CSVModel {
|
|||||||
logger.info("revalidate: hasValidator -> {}", hasValidator());
|
logger.info("revalidate: hasValidator -> {}", hasValidator());
|
||||||
|
|
||||||
if (!hasValidator()) return;
|
if (!hasValidator()) return;
|
||||||
|
|
||||||
validator.clearScriptCache();
|
|
||||||
revalidationService.setHeader(header);
|
revalidationService.setHeader(header);
|
||||||
revalidationService.setRows(rows);
|
revalidationService.setRows(rows);
|
||||||
revalidationService.setValidator(validator);
|
revalidationService.setValidator(validator);
|
||||||
@@ -130,71 +145,19 @@ public class CSVModel {
|
|||||||
public ValidationConfiguration createValidationConfiguration() {
|
public ValidationConfiguration createValidationConfiguration() {
|
||||||
ValidationConfiguration newValidationConfiguration = new ValidationConfiguration();
|
ValidationConfiguration newValidationConfiguration = new ValidationConfiguration();
|
||||||
newValidationConfiguration.setHeaderNames(this.header);
|
newValidationConfiguration.setHeaderNames(this.header);
|
||||||
this.validator = new Validator(newValidationConfiguration);
|
this.validator = new Validator(newValidationConfiguration, this);
|
||||||
this.revalidate();
|
this.revalidate();
|
||||||
return newValidationConfiguration;
|
return newValidationConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class RevalidationService extends Service<List<ValidationError>> {
|
|
||||||
|
|
||||||
private Validator validator;
|
@Override
|
||||||
private List<CSVRow> rows;
|
public String getValue(int row, String column) {
|
||||||
private String[] header;
|
return rows.get(row).getColumns().get(column).getValue().getValue();
|
||||||
|
|
||||||
public void setValidator(Validator validator) {
|
|
||||||
this.validator = validator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRows(List<CSVRow> rows) {
|
|
||||||
this.rows = rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeader(String[] header) {
|
|
||||||
this.header = header;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Task<List<ValidationError>> createTask() {
|
|
||||||
return new Task<List<ValidationError>>() {
|
|
||||||
@Override
|
|
||||||
protected List<ValidationError> call() throws Exception {
|
|
||||||
List<ValidationError> errors = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
if (header != null) {
|
|
||||||
ValidationError headerError = validator.isHeaderValid(header);
|
|
||||||
if (headerError != null) {
|
|
||||||
logger.info("revalidate: header error found");
|
|
||||||
errors.add(headerError);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int lineNumber = 0; lineNumber < rows.size(); lineNumber++) {
|
|
||||||
CSVRow row = rows.get(lineNumber);
|
|
||||||
row.setValidator(validator);
|
|
||||||
for (String column : row.getColumns().keySet()) {
|
|
||||||
CSVValue value = row.getColumns().get(column).getValue();
|
|
||||||
value.setValidator(validator);
|
|
||||||
if (validator != null) {
|
|
||||||
ValidationError validationError = validator.isValid(column, value.getValue(), lineNumber);
|
|
||||||
if (validationError != null) {
|
|
||||||
logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber);
|
|
||||||
errors.add(validationError);
|
|
||||||
value.setValidationError(validationError);
|
|
||||||
} else {
|
|
||||||
value.setValidationError(null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value.setValidationError(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
logger.error("validation error", t);
|
|
||||||
}
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfRows() {
|
||||||
|
return rows.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -30,24 +30,14 @@ import javafx.beans.property.ObjectProperty;
|
|||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableMap;
|
import javafx.collections.ObservableMap;
|
||||||
import ninja.javafx.smartcsv.validation.Validator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a single row in the csv file.
|
* This class represents a single row in the csv file.
|
||||||
*/
|
*/
|
||||||
public class CSVRow {
|
public class CSVRow {
|
||||||
private Validator validator;
|
|
||||||
private ObservableMap<String, ObjectProperty<CSVValue>> columns = FXCollections.observableHashMap();
|
private ObservableMap<String, ObjectProperty<CSVValue>> columns = FXCollections.observableHashMap();
|
||||||
private int rowNumber;
|
private int rowNumber;
|
||||||
|
|
||||||
/**
|
|
||||||
* single row
|
|
||||||
* @param validator the reference to the validator
|
|
||||||
*/
|
|
||||||
public void setValidator(Validator validator) {
|
|
||||||
this.validator = validator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the row number
|
* sets the row number
|
||||||
* @param rowNumber
|
* @param rowNumber
|
||||||
@@ -78,13 +68,11 @@ public class CSVRow {
|
|||||||
* @param column column name
|
* @param column column name
|
||||||
* @param value the value to store
|
* @param value the value to store
|
||||||
*/
|
*/
|
||||||
public void addValue(String column, String value) {
|
CSVValue addValue(String column, String value) {
|
||||||
CSVValue v = new CSVValue();
|
CSVValue v = new CSVValue();
|
||||||
v.setValidator(validator);
|
|
||||||
v.setColumn(column);
|
|
||||||
v.setRowNumber(rowNumber);
|
|
||||||
v.setValue(value);
|
v.setValue(value);
|
||||||
columns.put(column, new SimpleObjectProperty<>(v));
|
columns.put(column, new SimpleObjectProperty<>(v));
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -29,7 +29,6 @@ package ninja.javafx.smartcsv.fx.table.model;
|
|||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import ninja.javafx.smartcsv.validation.ValidationError;
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
import ninja.javafx.smartcsv.validation.Validator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The csv value represents the value of a single cell.
|
* The csv value represents the value of a single cell.
|
||||||
@@ -37,36 +36,9 @@ import ninja.javafx.smartcsv.validation.Validator;
|
|||||||
* and if the value is valid based on the validator.
|
* and if the value is valid based on the validator.
|
||||||
*/
|
*/
|
||||||
public class CSVValue {
|
public class CSVValue {
|
||||||
private Validator validator;
|
|
||||||
private int rowNumber;
|
|
||||||
private String column;
|
|
||||||
private StringProperty value = new SimpleStringProperty();
|
private StringProperty value = new SimpleStringProperty();
|
||||||
private ValidationError valid;
|
private ValidationError valid;
|
||||||
|
|
||||||
/**
|
|
||||||
* single value of a cell
|
|
||||||
* @param validator the reference to the validator
|
|
||||||
*/
|
|
||||||
public void setValidator(Validator validator) {
|
|
||||||
this.validator = validator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the row number this value is stored in
|
|
||||||
* @param row row number
|
|
||||||
*/
|
|
||||||
public void setRowNumber(int row) {
|
|
||||||
this.rowNumber = row;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the column this value is stored in
|
|
||||||
* @param column header name of the column
|
|
||||||
*/
|
|
||||||
public void setColumn(String column) {
|
|
||||||
this.column = column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the real value
|
* returns the real value
|
||||||
* @return the real value
|
* @return the real value
|
||||||
@@ -88,9 +60,6 @@ public class CSVValue {
|
|||||||
* @param value the real value
|
* @param value the real value
|
||||||
*/
|
*/
|
||||||
public void setValue(String value) {
|
public void setValue(String value) {
|
||||||
if (validator != null) {
|
|
||||||
valid = validator.isValid(column, value, rowNumber);
|
|
||||||
}
|
|
||||||
this.value.set(value);
|
this.value.set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +75,7 @@ public class CSVValue {
|
|||||||
* sets the state if a value is valid or not
|
* sets the state if a value is valid or not
|
||||||
* @param valid the validation state
|
* @param valid the validation state
|
||||||
*/
|
*/
|
||||||
protected void setValidationError(ValidationError valid) {
|
public void setValidationError(ValidationError valid) {
|
||||||
this.valid = valid;
|
this.valid = valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interface for easier access to values in a column
|
||||||
|
*/
|
||||||
|
public interface ColumnValueProvider {
|
||||||
|
|
||||||
|
String getValue(int row, String column);
|
||||||
|
int getNumberOfRows();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -31,5 +31,5 @@ package ninja.javafx.smartcsv.fx.util;
|
|||||||
*/
|
*/
|
||||||
public class ColorConstants {
|
public class ColorConstants {
|
||||||
public static final String OK_COLOR = "#22aa22";
|
public static final String OK_COLOR = "#22aa22";
|
||||||
public static final String ERROR_COLOR = "#ff6622";
|
public static final String ERROR_COLOR = "#ff3333";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -43,9 +43,8 @@ public class I18nValidationUtil {
|
|||||||
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, List<ValidationError> errors) {
|
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, List<ValidationError> errors) {
|
||||||
|
|
||||||
StringWriter message = new StringWriter();
|
StringWriter message = new StringWriter();
|
||||||
for (ValidationError validationError: errors) {
|
errors.forEach(error -> message.append(getI18nValidatioMessage(resourceBundle, error)).append("\n"));
|
||||||
message.append(getI18nValidatioMessage(resourceBundle, validationError)).append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.toString().length() != 0) {
|
if (message.toString().length() != 0) {
|
||||||
return cutOffLastLineBreak(message.toString());
|
return cutOffLastLineBreak(message.toString());
|
||||||
@@ -54,22 +53,31 @@ public class I18nValidationUtil {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getI18nValidatioMessageWithColumn(ResourceBundle resourceBundle, ValidationError error) {
|
||||||
|
return getI18nValidatioMessage(resourceBundle, error, resourceBundle.getString("column") + " " + error.getColumn() + " : ");
|
||||||
|
}
|
||||||
|
|
||||||
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) {
|
public static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error) {
|
||||||
|
return getI18nValidatioMessage(resourceBundle, error, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getI18nValidatioMessage(ResourceBundle resourceBundle, ValidationError error, String prefix) {
|
||||||
|
|
||||||
List<ValidationMessage> validationMessages = error.getMessages();
|
List<ValidationMessage> validationMessages = error.getMessages();
|
||||||
StringWriter message = new StringWriter();
|
StringWriter message = new StringWriter();
|
||||||
for (ValidationMessage validationMessage: validationMessages) {
|
validationMessages.forEach(validationMessage -> {
|
||||||
|
message.append(prefix);
|
||||||
if (resourceBundle.containsKey(validationMessage.getKey())) {
|
if (resourceBundle.containsKey(validationMessage.getKey())) {
|
||||||
String resourceText = resourceBundle.getString(validationMessage.getKey());
|
String resourceText = resourceBundle.getString(validationMessage.getKey());
|
||||||
if (validationMessage.getParameters().length > 0) {
|
if (validationMessage.getParameters().length > 0) {
|
||||||
message.append(format(resourceText, validationMessage.getParameters())).append("\n");
|
message.append(format(resourceText, (Object[]) validationMessage.getParameters())).append("\n");
|
||||||
} else {
|
} else {
|
||||||
message.append(resourceText).append("\n");
|
message.append(resourceText).append("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.append(validationMessage.getKey()).append("\n");
|
message.append(validationMessage.getKey()).append("\n");
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
if (!validationMessages.isEmpty()) {
|
if (!validationMessages.isEmpty()) {
|
||||||
return cutOffLastLineBreak(message.toString());
|
return cutOffLastLineBreak(message.toString());
|
||||||
|
|||||||
73
src/main/java/ninja/javafx/smartcsv/fx/util/JavaFxUtils.java
Normal file
73
src/main/java/ninja/javafx/smartcsv/fx/util/JavaFxUtils.java
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,26 +28,23 @@ package ninja.javafx.smartcsv.fx.util;
|
|||||||
|
|
||||||
import javafx.concurrent.Service;
|
import javafx.concurrent.Service;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import ninja.javafx.smartcsv.FileReader;
|
|
||||||
import ninja.javafx.smartcsv.files.FileStorage;
|
import ninja.javafx.smartcsv.files.FileStorage;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service class for async load of a csv file
|
* Service class for async load of a csv file
|
||||||
*/
|
*/
|
||||||
@org.springframework.stereotype.Service
|
@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;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Task createTask() {
|
protected Task<Void> createTask() {
|
||||||
return new Task() {
|
return new Task<>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void call() throws Exception {
|
protected Void call() throws Exception {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,31 +28,25 @@ package ninja.javafx.smartcsv.fx.util;
|
|||||||
|
|
||||||
import javafx.concurrent.Service;
|
import javafx.concurrent.Service;
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import ninja.javafx.smartcsv.FileWriter;
|
|
||||||
import ninja.javafx.smartcsv.csv.CSVFileWriter;
|
|
||||||
import ninja.javafx.smartcsv.files.FileStorage;
|
import ninja.javafx.smartcsv.files.FileStorage;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static javafx.application.Platform.runLater;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service class for async load of a csv file
|
* Service class for async save of a csv file
|
||||||
*/
|
*/
|
||||||
@org.springframework.stereotype.Service
|
@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;
|
file = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Task createTask() {
|
protected Task<Void> createTask() {
|
||||||
return new Task() {
|
return new Task<>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void call() throws Exception {
|
protected Void call() {
|
||||||
try {
|
try {
|
||||||
file.save();
|
file.save();
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
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.validation;
|
||||||
|
|
||||||
|
import javafx.scene.control.ListCell;
|
||||||
|
import javafx.scene.control.ListView;
|
||||||
|
import javafx.util.Callback;
|
||||||
|
import ninja.javafx.smartcsv.validation.configuration.StringFormat;
|
||||||
|
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cell factory for string formats
|
||||||
|
*/
|
||||||
|
public class StringFormatEditorCellFactory implements Callback<ListView<StringFormat>, ListCell<StringFormat>> {
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle;
|
||||||
|
|
||||||
|
public StringFormatEditorCellFactory(ResourceBundle resourceBundle) {
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListCell<StringFormat> call(ListView<StringFormat> param) {
|
||||||
|
return new ListCell<StringFormat>(){
|
||||||
|
@Override
|
||||||
|
protected void updateItem(StringFormat item, boolean empty) {
|
||||||
|
super.updateItem(item, empty);
|
||||||
|
if (item == null || empty) {
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
setText(resourceBundle.getString("format.type."+item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
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.validation;
|
||||||
|
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
import ninja.javafx.smartcsv.validation.configuration.StringFormat;
|
||||||
|
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converter for string formats
|
||||||
|
*/
|
||||||
|
public class StringFormatStringConverter extends StringConverter<StringFormat> {
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle;
|
||||||
|
|
||||||
|
public StringFormatStringConverter(ResourceBundle resourceBundle) {
|
||||||
|
this.resourceBundle = resourceBundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(StringFormat item) {
|
||||||
|
return resourceBundle.getString("format.type."+item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringFormat fromString(String string) {
|
||||||
|
return StringFormat.fromExternalValue(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -30,12 +30,13 @@ import javafx.beans.property.SimpleStringProperty;
|
|||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory;
|
||||||
import ninja.javafx.smartcsv.fx.FXMLController;
|
import ninja.javafx.smartcsv.fx.FXMLController;
|
||||||
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
|
import ninja.javafx.smartcsv.validation.configuration.*;
|
||||||
import org.fxmisc.richtext.CodeArea;
|
import org.fxmisc.richtext.CodeArea;
|
||||||
import org.fxmisc.richtext.LineNumberFactory;
|
import org.fxmisc.richtext.LineNumberFactory;
|
||||||
import org.fxmisc.richtext.StyleSpans;
|
import org.fxmisc.richtext.model.StyleSpans;
|
||||||
import org.fxmisc.richtext.StyleSpansBuilder;
|
import org.fxmisc.richtext.model.StyleSpansBuilder;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -47,8 +48,11 @@ import java.util.ResourceBundle;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static java.lang.Boolean.FALSE;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static java.util.stream.Collectors.joining;
|
import static java.util.stream.Collectors.joining;
|
||||||
|
import static javafx.beans.binding.Bindings.when;
|
||||||
|
import static ninja.javafx.smartcsv.validation.configuration.Type.STRING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* controller for editing column validations
|
* controller for editing column validations
|
||||||
@@ -75,7 +79,7 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
"transient", "true", "try", "void", "volatile", "while"
|
"transient", "true", "try", "void", "volatile", "while"
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", KEYWORDS) + ")\\b";
|
private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", (CharSequence[]) KEYWORDS) + ")\\b";
|
||||||
private static final String PAREN_PATTERN = "\\(|\\)";
|
private static final String PAREN_PATTERN = "\\(|\\)";
|
||||||
private static final String BRACE_PATTERN = "\\{|\\}";
|
private static final String BRACE_PATTERN = "\\{|\\}";
|
||||||
private static final String BRACKET_PATTERN = "\\[|\\]";
|
private static final String BRACKET_PATTERN = "\\[|\\]";
|
||||||
@@ -96,16 +100,13 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
);
|
);
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox notEmptyRuleCheckBox;
|
private ComboBox<Type> typeComboBox;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox integerRuleCheckBox;
|
private ComboBox<StringFormat> formatComboBox;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox doublerRuleCheckBox;
|
private TextField formatTextField;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private CheckBox alphanumericRuleCheckBox;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Spinner<Integer> minLengthSpinner;
|
private Spinner<Integer> minLengthSpinner;
|
||||||
@@ -113,9 +114,6 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private Spinner<Integer> maxLengthSpinner;
|
private Spinner<Integer> maxLengthSpinner;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private TextField dateformatRuleTextField;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField regexpRuleTextField;
|
private TextField regexpRuleTextField;
|
||||||
|
|
||||||
@@ -128,24 +126,12 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private CheckBox enableNotEmptyRule;
|
private CheckBox enableNotEmptyRule;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private CheckBox enableIntegerRule;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private CheckBox enableDoubleRule;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private CheckBox enableAlphanumericRule;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox enableMinLengthRule;
|
private CheckBox enableMinLengthRule;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox enableMaxLengthRule;
|
private CheckBox enableMaxLengthRule;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private CheckBox enableDateRule;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckBox enableRegexpRule;
|
private CheckBox enableRegexpRule;
|
||||||
|
|
||||||
@@ -155,6 +141,9 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
private CheckBox enableGroovyRule;
|
private CheckBox enableGroovyRule;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private CheckBox enableUniqueRule;
|
||||||
|
|
||||||
|
|
||||||
@Value("${fxml.smartcvs.validation.editor.view}")
|
@Value("${fxml.smartcvs.validation.editor.view}")
|
||||||
@Override
|
@Override
|
||||||
@@ -164,24 +153,13 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
initTypeAndFormatInput(resources);
|
||||||
minLengthSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0));
|
initMinMaxSpinner();
|
||||||
maxLengthSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0));
|
|
||||||
|
|
||||||
initCheckBox(notEmptyRuleCheckBox, enableNotEmptyRule);
|
|
||||||
initCheckBox(integerRuleCheckBox, enableIntegerRule);
|
|
||||||
initCheckBox(doublerRuleCheckBox, enableDoubleRule);
|
|
||||||
initCheckBox(alphanumericRuleCheckBox, enableAlphanumericRule);
|
|
||||||
initSpinner(minLengthSpinner, enableMinLengthRule);
|
initSpinner(minLengthSpinner, enableMinLengthRule);
|
||||||
initSpinner(maxLengthSpinner, enableMaxLengthRule);
|
initSpinner(maxLengthSpinner, enableMaxLengthRule);
|
||||||
initTextInputControl(dateformatRuleTextField, enableDateRule);
|
|
||||||
initTextInputControl(regexpRuleTextField, enableRegexpRule);
|
initTextInputControl(regexpRuleTextField, enableRegexpRule);
|
||||||
initTextInputControl(valueOfRuleTextField, enableValueOfRule);
|
initTextInputControl(valueOfRuleTextField, enableValueOfRule);
|
||||||
initCodeAreaControl(groovyRuleTextArea, enableGroovyRule);
|
initCodeAreaControl(groovyRuleTextArea, enableGroovyRule);
|
||||||
|
|
||||||
selectedColumn.addListener(observable -> {
|
|
||||||
updateForm();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSelectedColumn() {
|
public String getSelectedColumn() {
|
||||||
@@ -200,138 +178,236 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
this.validationConfiguration = validationConfiguration;
|
this.validationConfiguration = validationConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateConfiguration() {
|
private void initTypeAndFormatInput(ResourceBundle resources) {
|
||||||
|
typeComboBox.getItems().addAll(STRING,
|
||||||
|
Type.INTEGER,
|
||||||
|
Type.NUMBER,
|
||||||
|
Type.DATE,
|
||||||
|
Type.DATETIME,
|
||||||
|
Type.TIME);
|
||||||
|
formatComboBox.setCellFactory(new StringFormatEditorCellFactory(resources));
|
||||||
|
formatComboBox.setConverter(new StringFormatStringConverter(resources));
|
||||||
|
formatComboBox.getItems().addAll(
|
||||||
|
StringFormat.DEFAULT,
|
||||||
|
StringFormat.EMAIL,
|
||||||
|
StringFormat.URI,
|
||||||
|
StringFormat.BINARY,
|
||||||
|
StringFormat.UUID
|
||||||
|
);
|
||||||
|
typeComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> changeFormat());
|
||||||
|
}
|
||||||
|
|
||||||
if (enableIntegerRule.isSelected()) {
|
private void updateFormatTextField() {
|
||||||
validationConfiguration.setIntegerRuleFor(selectedColumn.getValue(), integerRuleCheckBox.isSelected());
|
switch (typeComboBox.getValue()) {
|
||||||
} else {
|
case DATE:
|
||||||
validationConfiguration.setIntegerRuleFor(selectedColumn.getValue(), null);
|
case DATETIME:
|
||||||
}
|
case TIME:
|
||||||
|
formatTextField.setVisible(true);
|
||||||
if (enableNotEmptyRule.isSelected()) {
|
formatTextField.setText(getCurrentFieldConfig().getFormat());
|
||||||
validationConfiguration.setNotEmptyRuleFor(selectedColumn.getValue(), notEmptyRuleCheckBox.isSelected());
|
break;
|
||||||
} else {
|
default:
|
||||||
validationConfiguration.setNotEmptyRuleFor(selectedColumn.getValue(), null);
|
formatTextField.setVisible(false);
|
||||||
}
|
formatTextField.setText(null);
|
||||||
|
break;
|
||||||
if (enableDoubleRule.isSelected()) {
|
|
||||||
validationConfiguration.setDoubleRuleFor(selectedColumn.getValue(), doublerRuleCheckBox.isSelected());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setDoubleRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableAlphanumericRule.isSelected()) {
|
|
||||||
validationConfiguration.setAlphanumericRuleFor(selectedColumn.getValue(), alphanumericRuleCheckBox.isSelected());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setAlphanumericRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableDateRule.isSelected()) {
|
|
||||||
validationConfiguration.setDateRuleFor(selectedColumn.getValue(), dateformatRuleTextField.getText());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setDateRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableGroovyRule.isSelected()) {
|
|
||||||
validationConfiguration.setGroovyRuleFor(selectedColumn.getValue(), groovyRuleTextArea.getText());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setGroovyRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableMinLengthRule.isSelected()) {
|
|
||||||
validationConfiguration.setMinLengthRuleFor(selectedColumn.getValue(), minLengthSpinner.getValue());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setMinLengthRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableMaxLengthRule.isSelected()) {
|
|
||||||
validationConfiguration.setMaxLengthRuleFor(selectedColumn.getValue(), maxLengthSpinner.getValue());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setMaxLengthRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableRegexpRule.isSelected()) {
|
|
||||||
validationConfiguration.setRegexpRuleFor(selectedColumn.getValue(), regexpRuleTextField.getText());
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setRegexpRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableValueOfRule.isSelected()) {
|
|
||||||
validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), asList(valueOfRuleTextField.getText().split(", ")));
|
|
||||||
} else {
|
|
||||||
validationConfiguration.setValueOfRuleFor(selectedColumn.getValue(), null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateForm() {
|
private void updateFormatComboBox() {
|
||||||
|
switch (typeComboBox.getValue()) {
|
||||||
|
case STRING:
|
||||||
|
formatComboBox.setVisible(true);
|
||||||
|
formatComboBox.getSelectionModel().select(StringFormat.fromExternalValue(getCurrentFieldConfig().getFormat()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
formatComboBox.setVisible(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateCheckBox(
|
private void initMinMaxSpinner() {
|
||||||
notEmptyRuleCheckBox,
|
IntegerSpinnerValueFactory minValueFactory = new IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0);
|
||||||
validationConfiguration.getNotEmptyRuleFor(getSelectedColumn()),
|
minLengthSpinner.setValueFactory(minValueFactory);
|
||||||
enableNotEmptyRule
|
IntegerSpinnerValueFactory maxValueFactory = new IntegerSpinnerValueFactory(0, Integer.MAX_VALUE, 0);
|
||||||
|
maxLengthSpinner.setValueFactory(maxValueFactory);
|
||||||
|
|
||||||
|
minValueFactory.maxProperty().bind(
|
||||||
|
when(enableMaxLengthRule.selectedProperty()).
|
||||||
|
then(maxLengthSpinner.valueProperty()).
|
||||||
|
otherwise(Integer.MAX_VALUE));
|
||||||
|
maxValueFactory.minProperty().bind(
|
||||||
|
when(enableMinLengthRule.selectedProperty()).
|
||||||
|
then(minLengthSpinner.valueProperty()).
|
||||||
|
otherwise(0));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void changeFormat() {
|
||||||
|
switch (typeComboBox.getValue()) {
|
||||||
|
case STRING:
|
||||||
|
updateFormatComboBox();
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
case DATETIME:
|
||||||
|
case TIME:
|
||||||
|
updateFormatTextField();
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
case NUMBER:
|
||||||
|
default:
|
||||||
|
// format: no options
|
||||||
|
formatComboBox.setVisible(false);
|
||||||
|
formatTextField.setVisible(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateConfiguration() {
|
||||||
|
|
||||||
|
Field config = getCurrentFieldConfig();
|
||||||
|
config.setType(typeComboBox.getValue());
|
||||||
|
|
||||||
|
switch (typeComboBox.getValue()) {
|
||||||
|
case STRING:
|
||||||
|
config.setFormat(formatComboBox.getValue().getExternalValue());
|
||||||
|
break;
|
||||||
|
case DATE:
|
||||||
|
case DATETIME:
|
||||||
|
case TIME:
|
||||||
|
if (formatTextField.getText().trim().isEmpty()) {
|
||||||
|
config.setFormat(null);
|
||||||
|
} else {
|
||||||
|
// TODO: validate input
|
||||||
|
config.setFormat(formatTextField.getText());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INTEGER:
|
||||||
|
case NUMBER:
|
||||||
|
default:
|
||||||
|
// format: no options
|
||||||
|
config.setFormat(null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableGroovyRule.isSelected()) {
|
||||||
|
config.setGroovy(groovyRuleTextArea.getText());
|
||||||
|
} else {
|
||||||
|
config.setGroovy(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraints constraints = config.getConstraints();
|
||||||
|
if (constraints == null) {
|
||||||
|
constraints = new Constraints();
|
||||||
|
config.setConstraints(constraints);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableNotEmptyRule.isSelected()) {
|
||||||
|
constraints.setRequired(enableNotEmptyRule.isSelected());
|
||||||
|
} else {
|
||||||
|
constraints.setRequired(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableUniqueRule.isSelected()) {
|
||||||
|
constraints.setUnique(enableUniqueRule.isSelected());
|
||||||
|
} else {
|
||||||
|
constraints.setUnique(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableMinLengthRule.isSelected()) {
|
||||||
|
constraints.setMinLength(minLengthSpinner.getValue());
|
||||||
|
} else {
|
||||||
|
constraints.setMinLength(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableMaxLengthRule.isSelected()) {
|
||||||
|
constraints.setMaxLength(maxLengthSpinner.getValue());
|
||||||
|
} else {
|
||||||
|
constraints.setMaxLength(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableRegexpRule.isSelected()) {
|
||||||
|
constraints.setPattern(regexpRuleTextField.getText());
|
||||||
|
} else {
|
||||||
|
constraints.setPattern(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableValueOfRule.isSelected()) {
|
||||||
|
constraints.setEnumeration(asList(valueOfRuleTextField.getText().split(", ")));
|
||||||
|
} else {
|
||||||
|
constraints.setEnumeration(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Field getCurrentFieldConfig() {
|
||||||
|
return validationConfiguration.getFieldConfiguration(getSelectedColumn());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDependencyListener(CheckBox rule, CheckBox... dependentRules) {
|
||||||
|
rule.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
if (newValue) {
|
||||||
|
for (CheckBox dependentRule: dependentRules) {
|
||||||
|
dependentRule.selectedProperty().setValue(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateForm() {
|
||||||
|
|
||||||
|
Field config = getCurrentFieldConfig();
|
||||||
|
|
||||||
|
if (config.getType() != null) {
|
||||||
|
typeComboBox.setValue(config.getType());
|
||||||
|
} else {
|
||||||
|
typeComboBox.setValue(STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFormatComboBox();
|
||||||
|
updateFormatTextField();
|
||||||
|
|
||||||
|
updateCodeAreaControl(
|
||||||
|
groovyRuleTextArea,
|
||||||
|
config.getGroovy(),
|
||||||
|
enableGroovyRule
|
||||||
);
|
);
|
||||||
|
|
||||||
updateCheckBox(
|
Constraints constraints = config.getConstraints();
|
||||||
integerRuleCheckBox,
|
updateCheckBox(constraints != null ? constraints.getRequired() : FALSE, enableNotEmptyRule);
|
||||||
validationConfiguration.getIntegerRuleFor(getSelectedColumn()),
|
updateCheckBox(constraints != null ? constraints.getUnique() : FALSE, enableUniqueRule);
|
||||||
enableIntegerRule
|
|
||||||
);
|
|
||||||
|
|
||||||
updateCheckBox(
|
|
||||||
doublerRuleCheckBox,
|
|
||||||
validationConfiguration.getDoubleRuleFor(getSelectedColumn()),
|
|
||||||
enableDoubleRule
|
|
||||||
);
|
|
||||||
|
|
||||||
updateCheckBox(
|
|
||||||
alphanumericRuleCheckBox,
|
|
||||||
validationConfiguration.getAlphanumericRuleFor(getSelectedColumn()),
|
|
||||||
enableAlphanumericRule
|
|
||||||
);
|
|
||||||
|
|
||||||
updateSpinner(
|
updateSpinner(
|
||||||
minLengthSpinner,
|
minLengthSpinner,
|
||||||
validationConfiguration.getMinLengthRuleFor(getSelectedColumn()),
|
constraints != null ? constraints.getMinLength() : null,
|
||||||
enableMinLengthRule
|
enableMinLengthRule
|
||||||
);
|
);
|
||||||
|
|
||||||
updateSpinner(
|
updateSpinner(
|
||||||
maxLengthSpinner,
|
maxLengthSpinner,
|
||||||
validationConfiguration.getMaxLengthRuleFor(getSelectedColumn()),
|
constraints != null ? constraints.getMaxLength() : null,
|
||||||
enableMaxLengthRule
|
enableMaxLengthRule
|
||||||
);
|
);
|
||||||
|
|
||||||
updateTextInputControl(
|
|
||||||
dateformatRuleTextField,
|
|
||||||
validationConfiguration.getDateRuleFor(getSelectedColumn()),
|
|
||||||
enableDateRule
|
|
||||||
);
|
|
||||||
|
|
||||||
updateTextInputControl(
|
updateTextInputControl(
|
||||||
regexpRuleTextField,
|
regexpRuleTextField,
|
||||||
validationConfiguration.getRegexpRuleFor(getSelectedColumn()),
|
constraints != null ? constraints.getPattern() : null,
|
||||||
enableRegexpRule
|
enableRegexpRule
|
||||||
);
|
);
|
||||||
|
|
||||||
updateTextInputControl(
|
updateTextInputControl(
|
||||||
valueOfRuleTextField,
|
valueOfRuleTextField,
|
||||||
validationConfiguration.getValueOfRuleFor(getSelectedColumn()),
|
constraints != null ? constraints.getEnumeration() : null,
|
||||||
enableValueOfRule
|
enableValueOfRule
|
||||||
);
|
);
|
||||||
|
|
||||||
updateCodeAreaControl(
|
|
||||||
groovyRuleTextArea,
|
|
||||||
validationConfiguration.getGroovyRuleFor(getSelectedColumn()),
|
|
||||||
enableGroovyRule
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCheckBox(CheckBox rule, Boolean value, CheckBox ruleEnabled) {
|
private void updateCheckBox(Boolean value, CheckBox ruleEnabled) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
ruleEnabled.setSelected(false);
|
ruleEnabled.setSelected(false);
|
||||||
} else {
|
} else {
|
||||||
rule.setSelected(value);
|
ruleEnabled.setSelected(value);
|
||||||
ruleEnabled.setSelected(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,19 +443,10 @@ public class ValidationEditorController extends FXMLController {
|
|||||||
ruleEnabled.setSelected(false);
|
ruleEnabled.setSelected(false);
|
||||||
} else {
|
} else {
|
||||||
ruleEnabled.setSelected(true);
|
ruleEnabled.setSelected(true);
|
||||||
rule.replaceText(0, 0, value);
|
rule.replaceText(0, rule.getLength(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initCheckBox(CheckBox rule, CheckBox ruleEnabled) {
|
|
||||||
rule.disableProperty().bind(ruleEnabled.selectedProperty().not());
|
|
||||||
ruleEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
|
||||||
if (!newValue) {
|
|
||||||
rule.setSelected(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initSpinner(Spinner rule, CheckBox ruleEnabled) {
|
private void initSpinner(Spinner rule, CheckBox ruleEnabled) {
|
||||||
rule.disableProperty().bind(ruleEnabled.selectedProperty().not());
|
rule.disableProperty().bind(ruleEnabled.selectedProperty().not());
|
||||||
ruleEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
ruleEnabled.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,31 +26,37 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.preferences;
|
package ninja.javafx.smartcsv.preferences;
|
||||||
|
|
||||||
import org.supercsv.quote.AlwaysQuoteMode;
|
import com.google.gson.GsonBuilder;
|
||||||
import org.supercsv.quote.ColumnQuoteMode;
|
import ninja.javafx.smartcsv.FileReader;
|
||||||
import org.supercsv.quote.NormalQuoteMode;
|
|
||||||
import org.supercsv.quote.QuoteMode;
|
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) {
|
private String fileEncoding;
|
||||||
switch (quoteModeName) {
|
|
||||||
case "always": return new AlwaysQuoteMode();
|
public EncodingFileReader() {
|
||||||
case "column": return new ColumnQuoteMode();
|
fileEncoding = Charset.defaultCharset().name();
|
||||||
default: return new NormalQuoteMode();
|
}
|
||||||
|
|
||||||
|
@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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,52 +28,39 @@ package ninja.javafx.smartcsv.preferences;
|
|||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import ninja.javafx.smartcsv.FileReader;
|
import ninja.javafx.smartcsv.FileReader;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.supercsv.prefs.CsvPreference;
|
|
||||||
import org.supercsv.quote.AlwaysQuoteMode;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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
|
* file reader for the preferences
|
||||||
*/
|
*/
|
||||||
public class PreferencesFileReader implements FileReader<CsvPreference> {
|
public class PreferencesFileReader implements FileReader<Preferences> {
|
||||||
|
|
||||||
private Map config;
|
private Preferences csvPreference;
|
||||||
private CsvPreference csvPreference;
|
|
||||||
|
|
||||||
public PreferencesFileReader() {
|
public PreferencesFileReader() {
|
||||||
csvPreference = new CsvPreference.
|
csvPreference = defaultPreferences();
|
||||||
Builder(CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE).
|
|
||||||
useQuoteMode(new AlwaysQuoteMode()).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(File filename) throws IOException {
|
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) {
|
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);
|
char delimiterChar = config.get("delimiterChar").toString().charAt(0);
|
||||||
String endOfLineSymbols = config.get("endOfLineSymbols").toString();
|
String endOfLineSymbols = config.get("endOfLineSymbols").toString();
|
||||||
boolean surroundingSpacesNeedQuotes = (Boolean)config.get("surroundingSpacesNeedQuotes");
|
boolean ignoreEmptyLines = (Boolean) config.get("ignoreEmptyLines");
|
||||||
boolean ignoreEmptyLines = (Boolean)config.get("ignoreEmptyLines");
|
csvPreference = new Preferences(quoteChar, delimiterChar, endOfLineSymbols, ignoreEmptyLines);
|
||||||
String quoteMode = config.get("quoteMode").toString();
|
|
||||||
|
|
||||||
csvPreference = new CsvPreference.Builder(quoteChar, delimiterChar, endOfLineSymbols)
|
|
||||||
.useQuoteMode(getQuoteMode(quoteMode))
|
|
||||||
.surroundingSpacesNeedQuotes(surroundingSpacesNeedQuotes)
|
|
||||||
.ignoreEmptyLines(ignoreEmptyLines)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CsvPreference getContent() {
|
public Preferences getContent() {
|
||||||
return csvPreference;
|
return csvPreference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -29,8 +29,6 @@ package ninja.javafx.smartcsv.preferences;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import ninja.javafx.smartcsv.FileWriter;
|
import ninja.javafx.smartcsv.FileWriter;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.supercsv.prefs.CsvPreference;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -41,22 +39,20 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* Save preferences to configuration file
|
* 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;
|
this.csvPreference = csvPreference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(File file) throws IOException {
|
public void write(File file) throws IOException {
|
||||||
Map<String, Object> preferences = new HashMap<>();
|
Map<String, Object> preferences = new HashMap<>();
|
||||||
preferences.put("quoteChar", Character.toString(csvPreference.getQuoteChar()));
|
preferences.put("quoteChar", csvPreference.quoteChar() == null ? null: csvPreference.quoteChar().toString());
|
||||||
preferences.put("delimiterChar", Character.toString((char)csvPreference.getDelimiterChar()));
|
preferences.put("delimiterChar", Character.toString((char)csvPreference.delimiterChar()));
|
||||||
preferences.put("endOfLineSymbols", csvPreference.getEndOfLineSymbols());
|
preferences.put("endOfLineSymbols", csvPreference.endOfLineSymbols());
|
||||||
preferences.put("surroundingSpacesNeedQuotes", csvPreference.isSurroundingSpacesNeedQuotes());
|
preferences.put("ignoreEmptyLines", csvPreference.ignoreEmptyLines());
|
||||||
preferences.put("ignoreEmptyLines", csvPreference.isIgnoreEmptyLines());
|
|
||||||
preferences.put("quoteMode", QuoteModeHelper.getQuoteModeName(csvPreference.getQuoteMode()));
|
|
||||||
|
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
Files.write(file.toPath(), gson.toJson(preferences).getBytes());
|
Files.write(file.toPath(), gson.toJson(preferences).getBytes());
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
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.validation;
|
||||||
|
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.concurrent.Service;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
|
import ninja.javafx.smartcsv.fx.table.model.CSVRow;
|
||||||
|
import ninja.javafx.smartcsv.fx.table.model.CSVValue;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for running the validation async of the ui thread
|
||||||
|
*/
|
||||||
|
public class RevalidationService extends Service<List<ValidationError>> {
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.getLogger(RevalidationService.class);
|
||||||
|
|
||||||
|
private Validator validator;
|
||||||
|
private List<CSVRow> rows;
|
||||||
|
private String[] header;
|
||||||
|
|
||||||
|
public void setValidator(Validator validator) {
|
||||||
|
this.validator = validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRows(List<CSVRow> rows) {
|
||||||
|
this.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(String[] header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task<List<ValidationError>> createTask() {
|
||||||
|
return new Task<List<ValidationError>>() {
|
||||||
|
@Override
|
||||||
|
protected List<ValidationError> call() throws Exception {
|
||||||
|
List<ValidationError> errors = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
if (header != null) {
|
||||||
|
ValidationError headerError = validator.isHeaderValid(header);
|
||||||
|
if (headerError != null) {
|
||||||
|
logger.info("revalidate: header error found");
|
||||||
|
errors.add(headerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxRows = rows.size();
|
||||||
|
for (int lineNumber = 0; lineNumber < maxRows; lineNumber++) {
|
||||||
|
CSVRow row = rows.get(lineNumber);
|
||||||
|
|
||||||
|
Map<String, ObjectProperty<CSVValue>> table = row.getColumns();
|
||||||
|
Set<String> columns = table.keySet();
|
||||||
|
|
||||||
|
for (String column : columns) {
|
||||||
|
CSVValue value = table.get(column).getValue();
|
||||||
|
if (validator != null) {
|
||||||
|
ValidationError validationError = validator.isValid(lineNumber, column, value.getValue());
|
||||||
|
if (validationError != null) {
|
||||||
|
logger.info("revalidate: {} errors found in line {}", validationError.getMessages().size(), lineNumber);
|
||||||
|
errors.add(validationError);
|
||||||
|
value.setValidationError(validationError);
|
||||||
|
} else {
|
||||||
|
value.setValidationError(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value.setValidationError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
logger.error("validation error", t);
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
The MIT License (MIT)
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Copyright (c) 2015 javafx.ninja <info@javafx.ninja>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
package ninja.javafx.smartcsv.validation;
|
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* validation configuration
|
|
||||||
*/
|
|
||||||
public class ValidationConfiguration {
|
|
||||||
|
|
||||||
@SerializedName("headers")
|
|
||||||
private HeaderConfiguration headerConfiguration = new HeaderConfiguration();
|
|
||||||
|
|
||||||
@SerializedName("columns")
|
|
||||||
private Map<String, Map<String, Object>> columnConfigurations = new HashMap<>();
|
|
||||||
|
|
||||||
public String[] headerNames() {
|
|
||||||
if (noHeader()) return null;
|
|
||||||
return headerConfiguration.getNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeaderNames(String[] headerNames) {
|
|
||||||
headerConfiguration.setNames(headerNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getIntegerRuleFor(String column) {
|
|
||||||
return (Boolean)getValue(column, "integer");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getDoubleRuleFor(String column) {
|
|
||||||
return (Boolean)getValue(column, "double");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getNotEmptyRuleFor(String column) {
|
|
||||||
return (Boolean)getValue(column, "not empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getMinLengthRuleFor(String column) {
|
|
||||||
return doubleToInteger((Double)getValue(column, "minlength"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getMaxLengthRuleFor(String column) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return doubleToInteger((Double)getValue(column, "maxlength"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDateRuleFor(String column) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return (String)getValue(column, "date");
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getAlphanumericRuleFor(String column) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return (Boolean)getValue(column, "alphanumeric");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRegexpRuleFor(String column) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return (String)getValue(column, "regexp");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getValueOfRuleFor(String column) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return (List<String>)getValue(column, "value of");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getGroovyRuleFor(String column) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return (String)getValue(column, "groovy");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIntegerRuleFor(String column, Boolean value) {
|
|
||||||
setValue(column, value, "integer");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDoubleRuleFor(String column, Boolean value) {
|
|
||||||
setValue(column, value, "double");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNotEmptyRuleFor(String column, Boolean value) {
|
|
||||||
setValue(column, value, "not empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMinLengthRuleFor(String column, Integer value) {
|
|
||||||
setValue(column, value == null ? null : value.doubleValue(), "minlength");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMaxLengthRuleFor(String column, Integer value) {
|
|
||||||
setValue(column, value == null ? null : value.doubleValue(), "maxlength");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDateRuleFor(String column, String value) {
|
|
||||||
setValue(column, value, "date");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAlphanumericRuleFor(String column, Boolean value) {
|
|
||||||
setValue(column, value, "alphanumeric");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegexpRuleFor(String column, String value) {
|
|
||||||
setValue(column, value, "regexp");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValueOfRuleFor(String column, List<String> value) {
|
|
||||||
setValue(column, value, "value of");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGroovyRuleFor(String column, String value) {
|
|
||||||
setValue(column, value, "groovy");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setValue(String column, Object value, String key) {
|
|
||||||
if (!columnConfigurations.containsKey(column)) {
|
|
||||||
columnConfigurations.put(column, new HashMap<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value == null && columnConfigurations.get(column).containsKey(key)) {
|
|
||||||
columnConfigurations.get(column).remove(key);
|
|
||||||
} else {
|
|
||||||
columnConfigurations.get(column).put(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object getValue(String column, String key) {
|
|
||||||
if (noRulesFor(column)) return null;
|
|
||||||
return columnConfigurations.get(column).get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean noHeader() {
|
|
||||||
return headerConfiguration == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean noRulesFor(String column) {
|
|
||||||
return columnConfigurations == null || columnConfigurations.get(column) == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Integer doubleToInteger(Double value) {
|
|
||||||
if (value == null) return null;
|
|
||||||
return (int)Math.round(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,6 +38,7 @@ public class ValidationError {
|
|||||||
|
|
||||||
private List<ValidationMessage> messages = new ArrayList<>();
|
private List<ValidationMessage> messages = new ArrayList<>();
|
||||||
private Integer lineNumber;
|
private Integer lineNumber;
|
||||||
|
private String column = "";
|
||||||
|
|
||||||
private ValidationError(Integer lineNumber) {
|
private ValidationError(Integer lineNumber) {
|
||||||
this.lineNumber = lineNumber;
|
this.lineNumber = lineNumber;
|
||||||
@@ -51,10 +52,19 @@ public class ValidationError {
|
|||||||
return new ValidationError(-1);
|
return new ValidationError(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValidationError column(String column) {
|
||||||
|
this.column = column;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Integer getLineNumber() {
|
public Integer getLineNumber() {
|
||||||
return lineNumber;
|
return lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getColumn() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
public List<ValidationMessage> getMessages() {
|
public List<ValidationMessage> getMessages() {
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,11 +28,14 @@ package ninja.javafx.smartcsv.validation;
|
|||||||
|
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import ninja.javafx.smartcsv.FileReader;
|
import ninja.javafx.smartcsv.FileReader;
|
||||||
import org.springframework.stereotype.Service;
|
import ninja.javafx.smartcsv.validation.configuration.Field;
|
||||||
|
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static ninja.javafx.smartcsv.validation.configuration.Type.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class loads the constraints as json config
|
* This class loads the constraints as json config
|
||||||
*/
|
*/
|
||||||
@@ -43,6 +46,30 @@ public class ValidationFileReader implements FileReader<ValidationConfiguration>
|
|||||||
@Override
|
@Override
|
||||||
public void read(File file) throws IOException {
|
public void read(File file) throws IOException {
|
||||||
config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class);
|
config = new GsonBuilder().create().fromJson(new java.io.FileReader(file), ValidationConfiguration.class);
|
||||||
|
setDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDefaults() {
|
||||||
|
for (Field field : config.getFields()) {
|
||||||
|
if (field.getType() == null) {
|
||||||
|
field.setType(STRING);
|
||||||
|
}
|
||||||
|
if (field.getType() == DATE) {
|
||||||
|
if (field.getFormat() == null) {
|
||||||
|
field.setFormat("yyyy-MM-dd");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (field.getType() == DATETIME) {
|
||||||
|
if (field.getFormat() == null) {
|
||||||
|
field.setFormat("yyyy-MM-ddThh:mm:ssZ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (field.getType() == TIME) {
|
||||||
|
if (field.getFormat() == null) {
|
||||||
|
field.setFormat("hh:mm:ss");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidationConfiguration getContent() {
|
public ValidationConfiguration getContent() {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -29,7 +29,7 @@ package ninja.javafx.smartcsv.validation;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import ninja.javafx.smartcsv.FileWriter;
|
import ninja.javafx.smartcsv.FileWriter;
|
||||||
import org.springframework.stereotype.Service;
|
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package ninja.javafx.smartcsv.validation;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abi
|
||||||
|
*/
|
||||||
|
public class ValidationFormatHelper {
|
||||||
|
|
||||||
|
|
||||||
|
public static String dateFormat(String format, String defaultFormat) {
|
||||||
|
|
||||||
|
if (format != null && !format.trim().isEmpty()) {
|
||||||
|
format = format.trim();
|
||||||
|
if (format.startsWith("fmt:")) {
|
||||||
|
format = format.substring(4);
|
||||||
|
format = format.replace("%Y", "yyyy");
|
||||||
|
format = format.replace("%y", "yy");
|
||||||
|
format = format.replace("%m", "MM");
|
||||||
|
format = format.replace("%d", "dd");
|
||||||
|
format = format.replace("%a", "E");
|
||||||
|
format = format.replace("%A", "EEEE");
|
||||||
|
format = format.replace("%w", "F");
|
||||||
|
format = format.replace("%b", "MMM");
|
||||||
|
format = format.replace("%B", "MMMMM");
|
||||||
|
format = format.replace("%H", "HH");
|
||||||
|
format = format.replace("%I", "hh");
|
||||||
|
format = format.replace("%p", "a");
|
||||||
|
format = format.replace("%M", "mm");
|
||||||
|
format = format.replace("%S", "ss");
|
||||||
|
format = format.replace("%z", "Z");
|
||||||
|
format = format.replace("%Z", "z");
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer doubleToInteger(Double value) {
|
||||||
|
if (value == null) return null;
|
||||||
|
return (int)Math.round(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,17 +26,19 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.validation;
|
package ninja.javafx.smartcsv.validation;
|
||||||
|
|
||||||
import groovy.lang.Binding;
|
import ninja.javafx.smartcsv.fx.table.model.ColumnValueProvider;
|
||||||
import groovy.lang.GroovyShell;
|
import ninja.javafx.smartcsv.validation.checker.*;
|
||||||
import groovy.lang.Script;
|
import ninja.javafx.smartcsv.validation.configuration.Constraints;
|
||||||
import org.codehaus.groovy.control.CompilationFailedException;
|
import ninja.javafx.smartcsv.validation.configuration.Field;
|
||||||
|
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.joining;
|
import static ninja.javafx.smartcsv.validation.ValidationFormatHelper.dateFormat;
|
||||||
import static org.apache.commons.validator.GenericValidator.*;
|
import static ninja.javafx.smartcsv.validation.configuration.StringFormat.*;
|
||||||
|
import static ninja.javafx.smartcsv.validation.configuration.Type.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class checks all the validations defined in the
|
* This class checks all the validations defined in the
|
||||||
@@ -49,9 +51,8 @@ public class Validator {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private ValidationConfiguration validationConfig;
|
private ValidationConfiguration validationConfig;
|
||||||
private GroovyShell shell = new GroovyShell();
|
private ColumnValueProvider columnValueProvider;
|
||||||
private Map<String, Script> scriptCache = new HashMap<>();
|
private Map<String, Map<Validation.Type, Validation>> columnValidationMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// constructors
|
// constructors
|
||||||
@@ -59,10 +60,13 @@ public class Validator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON configuration for this validator
|
* JSON configuration for this validator
|
||||||
|
*
|
||||||
* @param validationConfig
|
* @param validationConfig
|
||||||
*/
|
*/
|
||||||
public Validator(ValidationConfiguration validationConfig) {
|
public Validator(ValidationConfiguration validationConfig, ColumnValueProvider columnValueProvider) {
|
||||||
this.validationConfig = validationConfig;
|
this.validationConfig = validationConfig;
|
||||||
|
this.columnValueProvider = columnValueProvider;
|
||||||
|
initColumnValidations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,30 +74,35 @@ public class Validator {
|
|||||||
// public methods
|
// public methods
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public boolean needsColumnValidation(String column) {
|
||||||
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
||||||
|
if (validationMap != null) {
|
||||||
|
return validationMap.containsKey(Validation.Type.UNIQUE);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checks if the value is valid for the column configuration
|
* checks if the value is valid for the column configuration
|
||||||
|
*
|
||||||
* @param column the column name
|
* @param column the column name
|
||||||
* @param value the value to check
|
* @param value the value to check
|
||||||
* @return ValidationError with information if valid and if not which getMessage happened
|
* @return ValidationError with information if valid and if not which getMessage happened
|
||||||
*/
|
*/
|
||||||
public ValidationError isValid(String column, String value, Integer lineNumber) {
|
public ValidationError isValid(Integer row, String column, String value) {
|
||||||
ValidationError result = null;
|
ValidationError result = null;
|
||||||
if (hasConfig()) {
|
if (hasConfig()) {
|
||||||
|
ValidationError error = ValidationError.withLineNumber(row).column(column);
|
||||||
ValidationError error = ValidationError.withLineNumber(lineNumber);
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
||||||
checkBlankOrNull(column, value, error);
|
if (validationMap != null) {
|
||||||
if (value != null && !value.isEmpty()) {
|
for (Validation validation: validationMap.values()) {
|
||||||
checkRegularExpression(column, value, error);
|
if (validation.canBeChecked(value)) {
|
||||||
checkAlphaNumeric(column, value, error);
|
validation.check(row, value, error);
|
||||||
checkDate(column, value, error);
|
}
|
||||||
checkMaxLength(column, value, error);
|
}
|
||||||
checkMinLength(column, value, error);
|
|
||||||
checkInteger(column, value, error);
|
|
||||||
checkGroovy(column, value, error);
|
|
||||||
checkValueOf(column, value, error);
|
|
||||||
checkDouble(column, value, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error.isEmpty()) {
|
if (!error.isEmpty()) {
|
||||||
result = error;
|
result = error;
|
||||||
}
|
}
|
||||||
@@ -101,127 +110,157 @@ public class Validator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean hasConfig() {
|
public boolean hasConfig() {
|
||||||
return validationConfig != null;
|
return validationConfig != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reinitializeColumn(String column) {
|
||||||
|
clear(column);
|
||||||
|
initializeColumnWithRules(column);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// private methods
|
// private methods
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void checkGroovy(String column, String value, ValidationError error) {
|
private void add(String column, Validation validation) {
|
||||||
String groovyScript = validationConfig.getGroovyRuleFor(column);
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
||||||
if (groovyScript != null) {
|
if (validationMap == null) {
|
||||||
|
validationMap = new HashMap<>();
|
||||||
|
columnValidationMap.put(column, validationMap);
|
||||||
|
}
|
||||||
|
validationMap.put(validation.getType(), validation);
|
||||||
|
}
|
||||||
|
|
||||||
Script script = scriptCache.get(column);
|
private void remove(String column, Validation.Type type) {
|
||||||
if (script == null) {
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
||||||
script = shell.parse(groovyScript);
|
if (validationMap == null) {
|
||||||
scriptCache.put(column, script);
|
validationMap = new HashMap<>();
|
||||||
}
|
columnValidationMap.put(column, validationMap);
|
||||||
|
}
|
||||||
Binding binding = new Binding();
|
validationMap.remove(type);
|
||||||
binding.setVariable("value", value);
|
}
|
||||||
script.setBinding(binding);
|
|
||||||
|
|
||||||
Object groovyResult = null;
|
|
||||||
try {
|
|
||||||
groovyResult = script.run();
|
|
||||||
} catch (CompilationFailedException e) {
|
|
||||||
error.add("validation.message.groovy.exception", groovyScript, e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (groovyResult == null) {
|
|
||||||
error.add("validation.message.groovy.return.null", groovyScript);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isScriptResultTrue(groovyResult)) {
|
|
||||||
error.add(groovyResult.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private void clear(String column) {
|
||||||
|
Map<Validation.Type, Validation> validationMap = columnValidationMap.get(column);
|
||||||
|
if (validationMap != null) {
|
||||||
|
validationMap.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isScriptResultTrue(Object groovyResult) {
|
private void initColumnValidations() {
|
||||||
return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true");
|
if (hasConfig()) {
|
||||||
}
|
for (Field column : validationConfig.getFields()) {
|
||||||
|
initializeColumnWithRules(column);
|
||||||
private void checkValueOf(String column, String value, ValidationError error) {
|
|
||||||
List<String> values = validationConfig.getValueOfRuleFor(column);
|
|
||||||
if (values != null) {
|
|
||||||
if (!values.contains(value)) {
|
|
||||||
String commaSeparated = values.stream().collect(joining(", "));
|
|
||||||
error.add("validation.message.value.of", value, commaSeparated);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBlankOrNull(String column, String value, ValidationError error) {
|
private void initializeColumnWithRules(String columnName) {
|
||||||
if (validationConfig.getNotEmptyRuleFor(column) != null && validationConfig.getNotEmptyRuleFor(column)) {
|
if (hasConfig()) {
|
||||||
if (isBlankOrNull(value)) {
|
for (Field column : validationConfig.getFields()) {
|
||||||
error.add("validation.message.not.empty");
|
if (column.getName().equals(columnName)) {
|
||||||
|
initializeColumnWithRules(column);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeColumnWithRules(Field column) {
|
||||||
|
|
||||||
|
if (column.getType() != null) {
|
||||||
|
if (column.getType() == NUMBER) {
|
||||||
|
add(column.getName(), new DoubleValidation());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.getType() == INTEGER) {
|
||||||
|
add(column.getName(), new IntegerValidation());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.getType() == DATE) {
|
||||||
|
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");
|
||||||
|
add(column.getName(), new DateValidation(format));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.getType() == TIME) {
|
||||||
|
String format = dateFormat(column.getFormat(), "hh:mm:ss");
|
||||||
|
add(column.getName(), new DateValidation(format));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column.getType() == STRING && column.getFormat() == null) {
|
||||||
|
remove(column.getName(), Validation.Type.STRING);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (column.getType() == STRING && column.getFormat().equalsIgnoreCase(EMAIL.getExternalValue())) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String groovy = column.getGroovy();
|
||||||
|
if (groovy != null && !groovy.trim().isEmpty()) {
|
||||||
|
add(column.getName(), new GroovyValidation(groovy));
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraints constraints = column.getConstraints();
|
||||||
|
if (constraints != null) {
|
||||||
|
Boolean notEmptyRule = constraints.getRequired();
|
||||||
|
if (notEmptyRule != null && notEmptyRule) {
|
||||||
|
add(column.getName(), new NotEmptyValidation());
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean uniqueRule = constraints.getUnique();
|
||||||
|
if (uniqueRule != null && uniqueRule) {
|
||||||
|
add(column.getName(), new UniqueValidation(columnValueProvider, column.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer minLength = constraints.getMinLength();
|
||||||
|
if (minLength != null) {
|
||||||
|
add(column.getName(), new MinLengthValidation(minLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer maxLength = constraints.getMaxLength();
|
||||||
|
if (maxLength != null) {
|
||||||
|
add(column.getName(), new MaxLengthValidation(maxLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
String regexp = constraints.getPattern();
|
||||||
|
if (regexp != null && !regexp.trim().isEmpty()) {
|
||||||
|
add(column.getName(), new RegExpValidation(regexp));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
List<String> valueOfRule = constraints.getEnumeration();
|
||||||
|
if (valueOfRule != null && !valueOfRule.isEmpty()) {
|
||||||
|
add(column.getName(), new ValueOfValidation(valueOfRule));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkInteger(String column, String value, ValidationError error) {
|
|
||||||
if (validationConfig.getIntegerRuleFor(column) != null && validationConfig.getIntegerRuleFor(column)) {
|
|
||||||
if (!isInt(value)) {
|
|
||||||
error.add("validation.message.integer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDouble(String column, String value, ValidationError error) {
|
|
||||||
if (validationConfig.getDoubleRuleFor(column) != null && validationConfig.getDoubleRuleFor(column)) {
|
|
||||||
if (!isDouble(value)) {
|
|
||||||
error.add("validation.message.double");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkMinLength(String column, String value, ValidationError error) {
|
|
||||||
Integer minLength = validationConfig.getMinLengthRuleFor(column);
|
|
||||||
if (minLength != null) {
|
|
||||||
if (!minLength(value, minLength)) {
|
|
||||||
error.add("validation.message.min.length", minLength.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkMaxLength(String column, String value, ValidationError error) {
|
|
||||||
Integer maxLength = validationConfig.getMaxLengthRuleFor(column);
|
|
||||||
if (maxLength != null) {
|
|
||||||
if (!maxLength(value, maxLength)) {
|
|
||||||
error.add("validation.message.max.length", maxLength.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkDate(String column, String value, ValidationError error) {
|
|
||||||
String dateformat = validationConfig.getDateRuleFor(column);
|
|
||||||
if (dateformat != null && !dateformat.trim().isEmpty()) {
|
|
||||||
if (!isDate(value, dateformat, true)) {
|
|
||||||
error.add("validation.message.date.format", dateformat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkAlphaNumeric(String column, String value, ValidationError error) {
|
|
||||||
if (validationConfig.getAlphanumericRuleFor(column) != null && validationConfig.getAlphanumericRuleFor(column)) {
|
|
||||||
if (!matchRegexp(value, "[0-9a-zA-Z]*")) {
|
|
||||||
error.add("validation.message.alphanumeric");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkRegularExpression(String column, String value, ValidationError error) {
|
|
||||||
String regexp = validationConfig.getRegexpRuleFor(column);
|
|
||||||
if (regexp != null && !regexp.trim().isEmpty()) {
|
|
||||||
if (!matchRegexp(value, regexp)) {
|
|
||||||
error.add("validation.message.regexp", regexp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValidationError isHeaderValid(String[] headerNames) {
|
public ValidationError isHeaderValid(String[] headerNames) {
|
||||||
ValidationError result = null;
|
ValidationError result = null;
|
||||||
@@ -237,7 +276,7 @@ public class Validator {
|
|||||||
|
|
||||||
ValidationError error = ValidationError.withoutLineNumber();
|
ValidationError error = ValidationError.withoutLineNumber();
|
||||||
|
|
||||||
for(int i=0; i<headerNamesConfig.length; i++) {
|
for (int i = 0; i < headerNamesConfig.length; i++) {
|
||||||
if (!headerNamesConfig[i].equals(headerNames[i])) {
|
if (!headerNamesConfig[i].equals(headerNames[i])) {
|
||||||
error.add("validation.message.header.match",
|
error.add("validation.message.header.match",
|
||||||
Integer.toString(i),
|
Integer.toString(i),
|
||||||
@@ -253,7 +292,5 @@ public class Validator {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearScriptCache() {
|
|
||||||
scriptCache.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the value is a base64 encoded string representing binary data
|
||||||
|
*/
|
||||||
|
public class BinaryValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
try {
|
||||||
|
Base64.getDecoder().decode(value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
error.add("validation.message.binary");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import static org.apache.commons.validator.GenericValidator.isDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the date has the right format
|
||||||
|
*/
|
||||||
|
public class DateValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private String dateformat;
|
||||||
|
|
||||||
|
public DateValidation(String dateformat) {
|
||||||
|
assert dateformat != null && !dateformat.trim().isEmpty() : "empty date format for date validation";
|
||||||
|
this.dateformat = dateformat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!isDate(value, dateformat, true)) {
|
||||||
|
error.add("validation.message.date.format", dateformat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.DATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import static org.apache.commons.validator.GenericValidator.isDouble;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is a double
|
||||||
|
*/
|
||||||
|
public class DoubleValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!isDouble(value)) {
|
||||||
|
error.add("validation.message.double");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.DOUBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
import org.apache.commons.validator.routines.EmailValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the value is a valid email address
|
||||||
|
*/
|
||||||
|
public class EmailValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!EmailValidator.getInstance().isValid(value)) {
|
||||||
|
error.add("validation.message.email");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package ninja.javafx.smartcsv.validation.checker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* validations based on this are not validated when the value is null or empty
|
||||||
|
*/
|
||||||
|
public abstract class EmptyValueIsValid implements Validation {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeChecked(String value) {
|
||||||
|
return value != null && !value.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import groovy.lang.Binding;
|
||||||
|
import groovy.lang.GroovyShell;
|
||||||
|
import groovy.lang.Script;
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
import org.codehaus.groovy.control.CompilationFailedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the given groovy as check
|
||||||
|
*/
|
||||||
|
public class GroovyValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private String groovyScript;
|
||||||
|
private Script script;
|
||||||
|
|
||||||
|
public GroovyValidation(String groovyScript) {
|
||||||
|
this.groovyScript = groovyScript;
|
||||||
|
GroovyShell shell = new GroovyShell();
|
||||||
|
script = shell.parse(groovyScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
Binding binding = new Binding();
|
||||||
|
binding.setVariable("value", value);
|
||||||
|
script.setBinding(binding);
|
||||||
|
|
||||||
|
Object groovyResult = null;
|
||||||
|
try {
|
||||||
|
groovyResult = script.run();
|
||||||
|
} catch (CompilationFailedException e) {
|
||||||
|
error.add("validation.message.groovy.exception", groovyScript, e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (groovyResult == null) {
|
||||||
|
error.add("validation.message.groovy.return.null", groovyScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isScriptResultTrue(groovyResult)) {
|
||||||
|
error.add(groovyResult.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.GROOVY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isScriptResultTrue(Object groovyResult) {
|
||||||
|
return groovyResult.equals(true) || groovyResult.toString().trim().toLowerCase().equals("true");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -23,24 +23,26 @@
|
|||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
package ninja.javafx.smartcsv.validation.checker;
|
||||||
|
|
||||||
package ninja.javafx.smartcsv.validation;
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import static org.apache.commons.validator.GenericValidator.isInt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* header configuration for the validation
|
* Checks if the value is an integer
|
||||||
*/
|
*/
|
||||||
public class HeaderConfiguration {
|
public class IntegerValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
@SerializedName("list")
|
@Override
|
||||||
private String[] names ;
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!isInt(value)) {
|
||||||
public String[] getNames() {
|
error.add("validation.message.integer");
|
||||||
return names;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNames(String[] names) {
|
@Override
|
||||||
this.names = names;
|
public Type getType() {
|
||||||
|
return Type.INTEGER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import static org.apache.commons.validator.GenericValidator.maxLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is shorter or exactly as long as the given max length
|
||||||
|
*/
|
||||||
|
public class MaxLengthValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private int maxLength;
|
||||||
|
|
||||||
|
public MaxLengthValidation(int maxLength) {
|
||||||
|
this.maxLength = maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!maxLength(value, maxLength)) {
|
||||||
|
error.add("validation.message.max.length", Integer.toString(maxLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.MAX_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import static org.apache.commons.validator.GenericValidator.minLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is at minimum long as the given min length
|
||||||
|
*/
|
||||||
|
public class MinLengthValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private int minLength;
|
||||||
|
|
||||||
|
public MinLengthValidation(int minLength) {
|
||||||
|
this.minLength = minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!minLength(value, minLength)) {
|
||||||
|
error.add("validation.message.min.length", Integer.toString(minLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.MIN_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import static org.apache.commons.validator.GenericValidator.isBlankOrNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is not empty
|
||||||
|
*/
|
||||||
|
public class NotEmptyValidation implements Validation {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (isBlankOrNull(value)) {
|
||||||
|
error.add("validation.message.not.empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.NOT_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeChecked(String value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import static org.apache.commons.validator.GenericValidator.matchRegexp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the value against the given reg exp
|
||||||
|
*/
|
||||||
|
public class RegExpValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private String regexp;
|
||||||
|
|
||||||
|
public RegExpValidation(String regexp) {
|
||||||
|
this.regexp = regexp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!matchRegexp(value, regexp)) {
|
||||||
|
error.add("validation.message.regexp", regexp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.REGEXP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.fx.table.model.ColumnValueProvider;
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Collections.sort;
|
||||||
|
import static java.util.stream.Collectors.joining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is unique in the column
|
||||||
|
*/
|
||||||
|
public class UniqueValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private ColumnValueProvider columnValueProvider;
|
||||||
|
private String column;
|
||||||
|
|
||||||
|
public UniqueValidation(ColumnValueProvider columnValueProvider, String column) {
|
||||||
|
this.columnValueProvider = columnValueProvider;
|
||||||
|
this.column = column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
|
||||||
|
List<Integer> lineNumbers = new ArrayList<>();
|
||||||
|
|
||||||
|
int numberOfRows = columnValueProvider.getNumberOfRows();
|
||||||
|
for (int currentRowOfIteration = 0; currentRowOfIteration < numberOfRows; currentRowOfIteration++) {
|
||||||
|
String storedValue = columnValueProvider.getValue(currentRowOfIteration, column);
|
||||||
|
|
||||||
|
if (value.equals(storedValue) && currentRowOfIteration != row) {
|
||||||
|
lineNumbers.add(currentRowOfIteration + 1); // show not 0 based line numbers to user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lineNumbers.isEmpty()) {
|
||||||
|
if (lineNumbers.size() > 1) {
|
||||||
|
sort(lineNumbers);
|
||||||
|
error.add("validation.message.uniqueness.multiple", value, lineNumbers.stream().map(Object::toString).collect(joining(", ")));
|
||||||
|
} else {
|
||||||
|
error.add("validation.message.uniqueness.single", value, lineNumbers.get(0).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.UNIQUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the value is a valid uri address
|
||||||
|
*/
|
||||||
|
public class UriValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
try {
|
||||||
|
new URI(value);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
error.add("validation.message.uri");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if the value is a valid uuid
|
||||||
|
*/
|
||||||
|
public class UuidValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
try {
|
||||||
|
UUID.fromString(value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
error.add("validation.message.uuid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for all validations
|
||||||
|
*/
|
||||||
|
public interface Validation {
|
||||||
|
|
||||||
|
enum Type { NOT_EMPTY, UNIQUE, DOUBLE, INTEGER, MIN_LENGTH, MAX_LENGTH, DATE, REGEXP, VALUE_OF, STRING, GROOVY }
|
||||||
|
void check(int row, String value, ValidationError error);
|
||||||
|
Type getType();
|
||||||
|
boolean canBeChecked(String value);
|
||||||
|
}
|
||||||
@@ -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.validation.checker;
|
||||||
|
|
||||||
|
import ninja.javafx.smartcsv.validation.ValidationError;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.joining;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the value is part of a list of values
|
||||||
|
*/
|
||||||
|
public class ValueOfValidation extends EmptyValueIsValid {
|
||||||
|
|
||||||
|
private List<String> values;
|
||||||
|
|
||||||
|
public ValueOfValidation(List<String> values) {
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void check(int row, String value, ValidationError error) {
|
||||||
|
if (!values.contains(value)) {
|
||||||
|
String commaSeparated = values.stream().collect(joining(", "));
|
||||||
|
error.add("validation.message.value.of", value, commaSeparated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.VALUE_OF;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
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.validation.configuration;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* contraints defined in JSON Table Schema
|
||||||
|
* @see <a href="http://specs.frictionlessdata.io/json-table-schema/">JSON Table Schema</a>
|
||||||
|
*/
|
||||||
|
public class Constraints {
|
||||||
|
private Boolean required;
|
||||||
|
private Boolean unique;
|
||||||
|
private Integer minLength;
|
||||||
|
private Integer maxLength;
|
||||||
|
|
||||||
|
private String pattern;
|
||||||
|
|
||||||
|
@SerializedName("enum")
|
||||||
|
private List<String> enumeration;
|
||||||
|
|
||||||
|
public Boolean getRequired() {
|
||||||
|
return required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequired(Boolean required) {
|
||||||
|
this.required = required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getUnique() {
|
||||||
|
return unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnique(Boolean unique) {
|
||||||
|
this.unique = unique;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMinLength() {
|
||||||
|
return minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinLength(Integer minLength) {
|
||||||
|
this.minLength = minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMaxLength() {
|
||||||
|
return maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxLength(Integer maxLength) {
|
||||||
|
this.maxLength = maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPattern(String pattern) {
|
||||||
|
this.pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getEnumeration() {
|
||||||
|
return enumeration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumeration(List<String> enumeration) {
|
||||||
|
this.enumeration = enumeration;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
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.validation.configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this class represents a field in the configuration
|
||||||
|
* @see <a href="http://specs.frictionlessdata.io/json-table-schema/">JSON Table Schema</a>
|
||||||
|
*/
|
||||||
|
public class Field {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String title;
|
||||||
|
private Type type;
|
||||||
|
private String description;
|
||||||
|
private String format;
|
||||||
|
private Object missingValue;
|
||||||
|
private Constraints constraints;
|
||||||
|
private String groovy;
|
||||||
|
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(Type type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormat(String format) {
|
||||||
|
this.format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getMissingValue() {
|
||||||
|
return missingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMissingValue(Object missingValue) {
|
||||||
|
this.missingValue = missingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Constraints getConstraints() {
|
||||||
|
return constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConstraints(Constraints constraints) {
|
||||||
|
this.constraints = constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroovy() {
|
||||||
|
return groovy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroovy(String groovy) {
|
||||||
|
this.groovy = groovy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
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.validation.configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumeration for format values for type string in JSON Table Schema
|
||||||
|
* @see <a href="http://specs.frictionlessdata.io/json-table-schema/">JSON Table Schema</a>
|
||||||
|
*/
|
||||||
|
public enum StringFormat {
|
||||||
|
DEFAULT(null),
|
||||||
|
EMAIL("email"),
|
||||||
|
URI("uri"),
|
||||||
|
BINARY("binary"),
|
||||||
|
UUID("uuid");
|
||||||
|
|
||||||
|
private String externalValue;
|
||||||
|
|
||||||
|
StringFormat(String externalValue) {
|
||||||
|
this.externalValue = externalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExternalValue() {
|
||||||
|
return externalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringFormat fromExternalValue(String externalValue) {
|
||||||
|
if (externalValue != null) {
|
||||||
|
for (StringFormat value : StringFormat.values()) {
|
||||||
|
if (externalValue.equals(value.getExternalValue())) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
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.validation.configuration;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of JSON Table Schema
|
||||||
|
* @see <a href="http://specs.frictionlessdata.io/json-table-schema/">JSON Table Schema</a>
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
@SerializedName("string")STRING,
|
||||||
|
@SerializedName("integer")INTEGER,
|
||||||
|
@SerializedName("number")NUMBER,
|
||||||
|
@SerializedName("date")DATE,
|
||||||
|
@SerializedName("datetime")DATETIME,
|
||||||
|
@SerializedName("time")TIME
|
||||||
|
// TODO: currently not supported
|
||||||
|
// @SerializedName("object") OBJECT,
|
||||||
|
// @SerializedName("array") ARRAY,
|
||||||
|
// @SerializedName("duration") DURATION,
|
||||||
|
// @SerializedName("geopoint") GEOPOINT,
|
||||||
|
// @SerializedName("geojson") GEOJSON
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
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.validation.configuration;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration based on JSON Table Schema
|
||||||
|
* @see <a href="http://specs.frictionlessdata.io/json-table-schema/">JSON Table Schema</a>
|
||||||
|
*/
|
||||||
|
public class ValidationConfiguration {
|
||||||
|
|
||||||
|
@SerializedName("fields")
|
||||||
|
private Field[] fields;
|
||||||
|
|
||||||
|
public Field[] getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFields(Field[] fields) {
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field getFieldConfiguration(String column) {
|
||||||
|
for (Field field : fields) {
|
||||||
|
if (field.getName().equals(column)) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] headerNames() {
|
||||||
|
if (fields != null) {
|
||||||
|
List<String> headerNames = new ArrayList<>();
|
||||||
|
for (Field field : fields) {
|
||||||
|
headerNames.add(field.getName());
|
||||||
|
}
|
||||||
|
return headerNames.toArray(new String[headerNames.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaderNames(String[] header) {
|
||||||
|
fields = new Field[header.length];
|
||||||
|
int i = 0;
|
||||||
|
for (String headerName: header) {
|
||||||
|
fields[i] = new Field();
|
||||||
|
fields[i].setName(headerName);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,18 +11,8 @@
|
|||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" spacing="4.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
|
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="600.0" spacing="4.0" xmlns="http://javafx.com/javafx/8.0.76-ea" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Label text="SmartCSV.fx">
|
|
||||||
<font>
|
|
||||||
<Font size="18.0" />
|
|
||||||
</font>
|
|
||||||
<VBox.margin>
|
|
||||||
<Insets top="8.0" />
|
|
||||||
</VBox.margin>
|
|
||||||
</Label>
|
|
||||||
<Label text="A simple JavaFX application to load, save and edit a CSV file and provide a JSON configuration for columns " wrapText="true" />
|
|
||||||
<Label text="to check the values in the columns." />
|
|
||||||
<Label text="Thanks for contributions:">
|
<Label text="Thanks for contributions:">
|
||||||
<font>
|
<font>
|
||||||
<Font size="18.0" />
|
<Font size="18.0" />
|
||||||
@@ -32,6 +22,8 @@
|
|||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
</Label>
|
</Label>
|
||||||
<Label text="AOE Takashi (https://github.com/aoetk)" />
|
<Label text="AOE Takashi (https://github.com/aoetk)" />
|
||||||
|
<Label text="Hasan Kara (https://github.com/haisi)" />
|
||||||
|
<Label text="apixandru (https://github.com/apixandru)" />
|
||||||
<Label text="3rd party software">
|
<Label text="3rd party software">
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets top="8.0" />
|
<Insets top="8.0" />
|
||||||
@@ -48,17 +40,17 @@
|
|||||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
|
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="20.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label text="junit" />
|
<Label text="junit" />
|
||||||
@@ -69,8 +61,8 @@
|
|||||||
<Hyperlink onAction="#openLinkInBrowser" text="http://www.groovy-lang.org/" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
<Hyperlink onAction="#openLinkInBrowser" text="http://www.groovy-lang.org/" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||||
<Label text="spring framework" GridPane.rowIndex="3" />
|
<Label text="spring framework" GridPane.rowIndex="3" />
|
||||||
<Hyperlink onAction="#openLinkInBrowser" text="https://spring.io/" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
<Hyperlink onAction="#openLinkInBrowser" text="https://spring.io/" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
||||||
<Label text="supercsv" GridPane.rowIndex="4" />
|
<Label text="FastCSV" GridPane.rowIndex="4" />
|
||||||
<Hyperlink onAction="#openLinkInBrowser" text="http://super-csv.github.io/super-csv/" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
<Hyperlink onAction="#openLinkInBrowser" text="https://github.com/osiegmar/FastCSV" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
||||||
<Label text="Gson" GridPane.rowIndex="5" />
|
<Label text="Gson" GridPane.rowIndex="5" />
|
||||||
<Hyperlink onAction="#openLinkInBrowser" text="https://github.com/google/gson/" GridPane.columnIndex="1" 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" />
|
<Label text="commons-validator" GridPane.rowIndex="6" />
|
||||||
@@ -98,7 +90,7 @@
|
|||||||
<Font size="18.0" />
|
<Font size="18.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<TextArea editable="false" prefHeight="200.0" prefWidth="200.0" text="Copyright (c) 2015 Andreas Billmann <andreas.billmann@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." wrapText="true" />
|
<TextArea editable="false" prefHeight="200.0" prefWidth="200.0" text="Copyright (c) 2015-2021 Andreas Billmann <andreas.billmann@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." wrapText="true" />
|
||||||
</children>
|
</children>
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets />
|
<Insets />
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
application.name = SmartCSV.fx
|
application.name = SmartCSV.fx
|
||||||
application.version = 0.4
|
application.version = 1.4.0
|
||||||
|
|
||||||
# fxml views
|
# fxml views
|
||||||
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml
|
fxml.smartcvs.view = /ninja/javafx/smartcsv/fx/smartcsv.fxml
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.geometry.*?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import java.lang.*?>
|
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<GridPane hgap="8.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="8.0" xmlns="http://javafx.com/javafx/8.0.66" xmlns:fx="http://javafx.com/fxml/1">
|
<GridPane hgap="8.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" vgap="8.0" xmlns="http://javafx.com/javafx/8.0.66" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
|
||||||
@@ -14,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 minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
|
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label text="%preferences.quoteChar" />
|
<Label text="%preferences.quoteChar" />
|
||||||
<TextField fx:id="quoteChar" GridPane.columnIndex="1" />
|
<TextField fx:id="quoteChar" GridPane.columnIndex="1" />
|
||||||
<Label text="%preferences.delimiterChar" GridPane.rowIndex="1" />
|
<Label text="%preferences.delimiterChar" GridPane.rowIndex="1" />
|
||||||
<TextField fx:id="delimiterChar" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
<TextField fx:id="delimiterChar" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||||
<Label text="%preferences.surroundingSpacesNeedQuotes" GridPane.rowIndex="2" />
|
<Label text="%preferences.ignoreEmptyLines" GridPane.rowIndex="2" />
|
||||||
<CheckBox fx:id="surroundingSpacesNeedQuotes" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
<CheckBox fx:id="ignoreEmptyLines" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
||||||
<Label text="%preferences.ignoreEmptyLines" GridPane.rowIndex="3" />
|
<Label text="%preferences.fileEncoding" GridPane.rowIndex="3" />
|
||||||
<CheckBox fx:id="ignoreEmptyLines" mnemonicParsing="false" text="" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
<ComboBox fx:id="fileEncoding" editable="true" prefWidth="150.0" 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" />
|
|
||||||
</children>
|
</children>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
.list-view {
|
.table-view .list-view {
|
||||||
-fx-background-color: -fx-background;
|
-fx-background-color: -fx-background;
|
||||||
-fx-padding: 1;
|
-fx-padding: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-cell {
|
.table-view .list-cell {
|
||||||
-fx-padding: 1.0em 1.0em 1.0em 1.0em;
|
-fx-padding: 1.0em 1.0em 1.0em 1.0em;
|
||||||
}
|
}
|
||||||
.list-cell:odd {
|
.table-view .list-cell:odd {
|
||||||
-fx-background: -fx-control-inner-background-alt;
|
-fx-background: -fx-control-inner-background-alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-cell:even {
|
.table-view .list-cell:even {
|
||||||
-fx-background: -fx-control-inner-background;
|
-fx-background: -fx-control-inner-background;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +79,17 @@
|
|||||||
-glyph-size: 16px;
|
-glyph-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.goto-icon {
|
||||||
|
-glyph-name: "SUBDIRECTORY_ARROW_RIGHT";
|
||||||
|
-glyph-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-icon {
|
||||||
|
-glyph-name: "BUG";
|
||||||
|
-glyph-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */
|
/* toolbar customization based on http://fxexperience.com/2012/02/customized-segmented-toolbar-buttons/ */
|
||||||
|
|
||||||
#background {
|
#background {
|
||||||
@@ -143,6 +154,11 @@
|
|||||||
-fx-fill: white;
|
-fx-fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tool-bar .export-icon {
|
||||||
|
-glyph-size: 16px;
|
||||||
|
-fx-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
.segmented-button-bar .button {
|
.segmented-button-bar .button {
|
||||||
-fx-background-color:
|
-fx-background-color:
|
||||||
-darkest-black,
|
-darkest-black,
|
||||||
|
|||||||
@@ -1,28 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import de.jensd.fx.glyphs.GlyphsStack?>
|
<?import de.jensd.fx.glyphs.*?>
|
||||||
<?import java.net.URL?>
|
<?import de.jensd.fx.glyphs.materialdesignicons.*?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import javafx.scene.control.Menu?>
|
<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">
|
||||||
<?import javafx.scene.control.MenuBar?>
|
|
||||||
<?import javafx.scene.control.MenuItem?>
|
|
||||||
<?import javafx.scene.control.SeparatorMenuItem?>
|
|
||||||
<?import javafx.scene.control.TableView?>
|
|
||||||
<?import javafx.scene.control.ToolBar?>
|
|
||||||
<?import javafx.scene.control.Tooltip?>
|
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
|
||||||
<?import javafx.scene.layout.BorderPane?>
|
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
|
||||||
<?import javafx.scene.layout.GridPane?>
|
|
||||||
<?import javafx.scene.layout.HBox?>
|
|
||||||
<?import javafx.scene.layout.Region?>
|
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
|
||||||
<?import javafx.scene.layout.VBox?>
|
|
||||||
|
|
||||||
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
|
||||||
<BorderPane fx:id="applicationPane" maxHeight="-Infinity" maxWidth="1000.0" minHeight="700.0" minWidth="-Infinity" prefHeight="700.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<top>
|
<top>
|
||||||
<VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER">
|
<VBox id="background" prefWidth="100.0" BorderPane.alignment="CENTER">
|
||||||
<children>
|
<children>
|
||||||
@@ -52,7 +35,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="create-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="create-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -62,7 +45,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="load-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="load-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -72,7 +55,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -82,7 +65,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -94,6 +77,11 @@
|
|||||||
<MaterialDesignIconView styleClass="preferences-icon" />
|
<MaterialDesignIconView styleClass="preferences-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem fx:id="exportMenuItem" disable="true" mnemonicParsing="false" onAction="#export" text="%menu.export">
|
||||||
|
<graphic>
|
||||||
|
<MaterialDesignIconView styleClass="export-icon" />
|
||||||
|
</graphic>
|
||||||
|
</MenuItem>
|
||||||
<SeparatorMenuItem mnemonicParsing="false" />
|
<SeparatorMenuItem mnemonicParsing="false" />
|
||||||
<MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close">
|
<MenuItem mnemonicParsing="false" onAction="#close" text="%menu.close">
|
||||||
<graphic>
|
<graphic>
|
||||||
@@ -114,6 +102,12 @@
|
|||||||
<MaterialDesignIconView styleClass="add-icon" />
|
<MaterialDesignIconView styleClass="add-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<SeparatorMenuItem mnemonicParsing="false" />
|
||||||
|
<MenuItem fx:id="gotoLineMenuItem" disable="true" mnemonicParsing="false" onAction="#gotoLine" text="%menu.goto.line">
|
||||||
|
<graphic>
|
||||||
|
<MaterialDesignIconView styleClass="goto-icon" />
|
||||||
|
</graphic>
|
||||||
|
</MenuItem>
|
||||||
</items>
|
</items>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Menu mnemonicParsing="false" text="%menu.help">
|
<Menu mnemonicParsing="false" text="%menu.help">
|
||||||
@@ -164,7 +158,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="create-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="create-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -177,7 +171,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="load-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="load-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -190,7 +184,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -203,7 +197,7 @@
|
|||||||
<GlyphsStack>
|
<GlyphsStack>
|
||||||
<children>
|
<children>
|
||||||
<MaterialDesignIconView styleClass="config-icon" />
|
<MaterialDesignIconView styleClass="config-icon" />
|
||||||
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
<MaterialDesignIconView style="-fx-opacity: 0.7;" styleClass="save-config-icon" />
|
||||||
</children>
|
</children>
|
||||||
</GlyphsStack>
|
</GlyphsStack>
|
||||||
|
|
||||||
@@ -239,6 +233,14 @@
|
|||||||
<MaterialDesignIconView styleClass="preferences-icon" />
|
<MaterialDesignIconView styleClass="preferences-icon" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button fx:id="exportButton" disable="true" mnemonicParsing="false" onAction="#export">
|
||||||
|
<tooltip>
|
||||||
|
<Tooltip text="%menu.export" />
|
||||||
|
</tooltip>
|
||||||
|
<graphic>
|
||||||
|
<MaterialDesignIconView styleClass="export-icon" />
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
<Button mnemonicParsing="false" onAction="#close" styleClass="last">
|
<Button mnemonicParsing="false" onAction="#close" styleClass="last">
|
||||||
<tooltip>
|
<tooltip>
|
||||||
<Tooltip text="%menu.close" />
|
<Tooltip text="%menu.close" />
|
||||||
@@ -262,9 +264,6 @@
|
|||||||
</center>
|
</center>
|
||||||
<left>
|
<left>
|
||||||
</left>
|
</left>
|
||||||
<stylesheets>
|
|
||||||
<URL value="@/ninja/javafx/smartcsv/fx/smartcsv.css" />
|
|
||||||
</stylesheets>
|
|
||||||
<bottom>
|
<bottom>
|
||||||
<GridPane hgap="8.0" BorderPane.alignment="CENTER">
|
<GridPane hgap="8.0" BorderPane.alignment="CENTER">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
@@ -275,6 +274,9 @@
|
|||||||
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
|
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
|
||||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
|
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
|
||||||
<ColumnConstraints hgrow="NEVER" 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 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>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
@@ -287,6 +289,10 @@
|
|||||||
<MaterialDesignIconView styleClass="config-check-icon" GridPane.columnIndex="3" GridPane.hgrow="NEVER" />
|
<MaterialDesignIconView styleClass="config-check-icon" GridPane.columnIndex="3" GridPane.hgrow="NEVER" />
|
||||||
<Label text="%stateline.configuration" GridPane.columnIndex="4" GridPane.hgrow="NEVER" />
|
<Label text="%stateline.configuration" GridPane.columnIndex="4" GridPane.hgrow="NEVER" />
|
||||||
<Label fx:id="configurationName" GridPane.columnIndex="5" GridPane.hgrow="ALWAYS" />
|
<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>
|
</children>
|
||||||
<BorderPane.margin>
|
<BorderPane.margin>
|
||||||
<Insets bottom="4.0" left="8.0" right="8.0" top="4.0" />
|
<Insets bottom="4.0" left="8.0" right="8.0" top="4.0" />
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ menu.help = Help
|
|||||||
menu.preferences = Preferences
|
menu.preferences = Preferences
|
||||||
menu.delete.row = Delete row
|
menu.delete.row = Delete row
|
||||||
menu.add.row = Add row
|
menu.add.row = Add row
|
||||||
|
menu.goto.line = Goto line
|
||||||
|
menu.export = Export error log
|
||||||
|
|
||||||
title.validation.errors = Validation Errors:
|
title.validation.errors = Validation Errors:
|
||||||
|
|
||||||
@@ -27,19 +29,29 @@ dialog.exit.title = Close Application
|
|||||||
dialog.exit.header.text = Do you want to 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.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.title = Preferences
|
||||||
dialog.preferences.header.text = Preferences
|
dialog.preferences.header.text = Preferences
|
||||||
|
|
||||||
|
dialog.goto.line.title = Go to line
|
||||||
|
dialog.goto.line.header.text = Go to given line (max. {0}) and select line!
|
||||||
|
dialog.goto.line.label = Line:
|
||||||
|
|
||||||
preferences.quoteChar = Quote character:
|
preferences.quoteChar = Quote character:
|
||||||
preferences.delimiterChar = Delimiter character:
|
preferences.delimiterChar = Delimiter character:
|
||||||
preferences.ignoreEmptyLines = Ignore empty lines:
|
preferences.ignoreEmptyLines = Ignore empty lines:
|
||||||
preferences.surroundingSpacesNeedQuotes = Surrounding spaces need quotes:
|
preferences.surroundingSpacesNeedQuotes = Surrounding spaces need quotes:
|
||||||
preferences.quoteMode = Quote mode:
|
preferences.quoteMode = Quote mode:
|
||||||
|
preferences.fileEncoding = File encoding:
|
||||||
|
|
||||||
# validaton messages
|
# validaton messages
|
||||||
validation.message.not.empty = should not be empty
|
validation.message.not.empty = should not be empty
|
||||||
validation.message.integer = should be an integer
|
validation.message.integer = should be an integer
|
||||||
validation.message.double = should be a double
|
validation.message.double = should be a double
|
||||||
|
validation.message.email = should be an email address
|
||||||
validation.message.alphanumeric = should be alphanumeric
|
validation.message.alphanumeric = should be alphanumeric
|
||||||
validation.message.groovy.exception = groovy script '{0}' throws exception: {1}
|
validation.message.groovy.exception = groovy script '{0}' throws exception: {1}
|
||||||
validation.message.groovy.return.null = groovy script '{0}' returns null
|
validation.message.groovy.return.null = groovy script '{0}' returns null
|
||||||
@@ -47,25 +59,47 @@ validation.message.min.length = has not min length of {0}
|
|||||||
validation.message.max.length = has not max length of {0}
|
validation.message.max.length = has not max length of {0}
|
||||||
validation.message.date.format = is not a date of format {0}
|
validation.message.date.format = is not a date of format {0}
|
||||||
validation.message.regexp = does not match {0}
|
validation.message.regexp = does not match {0}
|
||||||
|
validation.message.uniqueness.multiple = value {0} is not unique (found in rows {1})
|
||||||
|
validation.message.uniqueness.single = value {0} is not unique (found in row {1})
|
||||||
|
validation.message.uri = should be an uri
|
||||||
|
validation.message.uuid = should be an uuid
|
||||||
|
validation.message.binary = should be a base64 encoded string representing binary data
|
||||||
|
|
||||||
validation.message.header.length = number of headers is not correct! there are {0} but there should be {1}
|
validation.message.header.length = number of headers is not correct! there are {0} but there should be {1}
|
||||||
validation.message.header.match = header number {0} does not match "{1}" should be "{3}"
|
validation.message.header.match = header number {0} does not match "{1}" should be "{2}"
|
||||||
validation.message.value.of = Value {0} is not part of this list {1}
|
validation.message.value.of = Value {0} is not part of this list {1}
|
||||||
|
|
||||||
validation.rule.label.not_empty = not empty:
|
validation.rule.label.not_empty = not empty
|
||||||
validation.rule.label.integer = integer:
|
validation.rule.label.integer = integer
|
||||||
validation.rule.label.double = double:
|
validation.rule.label.double = double
|
||||||
validation.rule.label.minlength = minimum length:
|
validation.rule.label.minlength = minimum length:
|
||||||
validation.rule.label.maxlength = maximum length:
|
validation.rule.label.maxlength = maximum length:
|
||||||
validation.rule.label.dateformat = date format:
|
validation.rule.label.dateformat = date format:
|
||||||
validation.rule.label.alphanumeric = alphanumeric:
|
validation.rule.label.alphanumeric = alphanumeric
|
||||||
validation.rule.label.regexp = regular expression:
|
validation.rule.label.regexp = regular expression:
|
||||||
validation.rule.label.value_of = value in list:
|
validation.rule.label.value_of = value in list:
|
||||||
validation.rule.label.groovy = groovy:
|
validation.rule.label.groovy = groovy:
|
||||||
validation.rules.active = active
|
validation.rules.active = active
|
||||||
validation.rules.name = rule
|
validation.rules.name = rule
|
||||||
validation.rules.value = value
|
validation.rules.value = value
|
||||||
|
validation.rule.label.unique = Unique in column
|
||||||
|
validation.rule.format = Format:
|
||||||
|
validation.rule.type = Type:
|
||||||
|
|
||||||
dialog.validation.rules.title = Validation rules
|
dialog.validation.rules.title = Validation rules
|
||||||
dialog.validation.rules.header = Validation rules of column "{0}"
|
dialog.validation.rules.header = Validation rules of column "{0}"
|
||||||
context.menu.edit.column.rules = Edit rules
|
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}
|
||||||
|
|
||||||
|
column = column
|
||||||
|
|
||||||
|
format.type.DEFAULT = default
|
||||||
|
format.type.EMAIL = email
|
||||||
|
format.type.URI = uri
|
||||||
|
format.type.BINARY = binary
|
||||||
|
format.type.UUID = uuid
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ menu.help = Hilfe
|
|||||||
menu.preferences = Einstellungen
|
menu.preferences = Einstellungen
|
||||||
menu.delete.row = Zeile l\u00f6schen
|
menu.delete.row = Zeile l\u00f6schen
|
||||||
menu.add.row = Zeile hinzuf\u00fcgen
|
menu.add.row = Zeile hinzuf\u00fcgen
|
||||||
|
menu.goto.line = Springe zur Zeile
|
||||||
|
menu.export = Export Fehlerdatei
|
||||||
|
|
||||||
title.validation.errors = Fehler in der Datei:
|
title.validation.errors = Fehler in der Datei:
|
||||||
|
|
||||||
@@ -35,20 +37,30 @@ state.unchanged = Unver\u00e4ndert
|
|||||||
dialog.preferences.title = Eigenschaften
|
dialog.preferences.title = Eigenschaften
|
||||||
dialog.preferences.header.text = Eigenschaften
|
dialog.preferences.header.text = Eigenschaften
|
||||||
|
|
||||||
|
dialog.goto.line.title = Springe zur Zeile
|
||||||
|
dialog.goto.line.header.text = Zur angegebenen Zeile (max. {0}) springen und ausw\u00e4hlen!
|
||||||
|
dialog.goto.line.label = Zeile:
|
||||||
|
|
||||||
dialog.exit.title = Anwendung beenden
|
dialog.exit.title = Anwendung beenden
|
||||||
dialog.exit.header.text = M\u00f6chten Sie wirklich die 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.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.quoteChar = Einfassungszeichen:
|
||||||
preferences.delimiterChar = Trennzeichen:
|
preferences.delimiterChar = Trennzeichen:
|
||||||
preferences.ignoreEmptyLines = Leere Zeilen ignorieren:
|
preferences.ignoreEmptyLines = Leere Zeilen ignorieren:
|
||||||
preferences.surroundingSpacesNeedQuotes = Leerzeichen einfassen:
|
preferences.surroundingSpacesNeedQuotes = Leerzeichen einfassen:
|
||||||
preferences.quoteMode = Einfassungsmodus:
|
preferences.quoteMode = Einfassungsmodus:
|
||||||
|
preferences.fileEncoding = Dateicodierung:
|
||||||
|
|
||||||
# validaton messages
|
# validaton messages
|
||||||
validation.message.not.empty = Darf nicht leer sein.
|
validation.message.not.empty = Darf nicht leer sein.
|
||||||
validation.message.integer = Muss eine Zahl sein.
|
validation.message.integer = Muss eine Zahl sein.
|
||||||
validation.message.double = Muss eine Gleitkommazahl sein
|
validation.message.double = Muss eine Gleitkommazahl sein
|
||||||
|
validation.message.email = Muss eine Email-Adresse sein
|
||||||
validation.message.alphanumeric = Darf nur Zahlen und Buchstaben enthalten.
|
validation.message.alphanumeric = Darf nur Zahlen und Buchstaben enthalten.
|
||||||
validation.message.groovy.exception = groovy script '{0}' wirft folgenden Fehler: {1}
|
validation.message.groovy.exception = groovy script '{0}' wirft folgenden Fehler: {1}
|
||||||
validation.message.groovy.return.null = groovy script '{0}' meldet "null"
|
validation.message.groovy.return.null = groovy script '{0}' meldet "null"
|
||||||
@@ -56,14 +68,19 @@ validation.message.min.length = Hat nicht die minimale L\u00e4nge von {0}
|
|||||||
validation.message.max.length = Hat nicht die maximale L\u00e4nge von {0}
|
validation.message.max.length = Hat nicht die maximale L\u00e4nge von {0}
|
||||||
validation.message.date.format = Das Datumsformat entspricht nicht {0}
|
validation.message.date.format = Das Datumsformat entspricht nicht {0}
|
||||||
validation.message.regexp = entspricht nicht dem regul\u00e4ren Ausdruck {0}
|
validation.message.regexp = entspricht nicht dem regul\u00e4ren Ausdruck {0}
|
||||||
|
validation.message.uniqueness.multiple = Wert {0} ist nicht einmalig (gefunden in den Zeilen {1})
|
||||||
|
validation.message.uniqueness.single = Wert {0} ist nicht einmalig (gefunden in Zeile {1})
|
||||||
|
validation.message.uri = Muss eine URI sein
|
||||||
|
validation.message.uuid = Muss eine UUID sein
|
||||||
|
validation.message.binary = Muss ein base64 encoded Text sein, der bin\u00e4re Daten enth\u00e4lt
|
||||||
|
|
||||||
validation.message.header.length = Anzahl der \u00dcberschriften ist nicht korrekt! Es sind {0} aber es sollten {1} sein
|
validation.message.header.length = Anzahl der \u00dcberschriften ist nicht korrekt! Es sind {0} aber es sollten {1} sein
|
||||||
validation.message.header.match = \u00dcberschrift in Spalte {0} stimmt nicht. "{1}" sollte "{3}" sein
|
validation.message.header.match = \u00dcberschrift in Spalte {0} stimmt nicht. "{1}" sollte "{3}" sein
|
||||||
validation.message.value.of = Der Wert {0} ist nicht in der Liste {1} enthalten
|
validation.message.value.of = Der Wert {0} ist nicht in der Liste {1} enthalten
|
||||||
|
|
||||||
validation.rule.label.not_empty = Nicht leer:
|
validation.rule.label.not_empty = Nicht leer
|
||||||
validation.rule.label.integer = Zahl:
|
validation.rule.label.integer = Zahl
|
||||||
validation.rule.label.double = Gleitkommazahl:
|
validation.rule.label.double = Gleitkommazahl
|
||||||
validation.rule.label.minlength = Minimale L\u00e4nge:
|
validation.rule.label.minlength = Minimale L\u00e4nge:
|
||||||
validation.rule.label.maxlength = Maximale L\u00e4nge:
|
validation.rule.label.maxlength = Maximale L\u00e4nge:
|
||||||
validation.rule.label.dateformat = Datumsformat:
|
validation.rule.label.dateformat = Datumsformat:
|
||||||
@@ -74,8 +91,25 @@ validation.rule.label.groovy = groovy:
|
|||||||
validation.rules.active = Aktiv
|
validation.rules.active = Aktiv
|
||||||
validation.rules.name = Regel
|
validation.rules.name = Regel
|
||||||
validation.rules.value = Wert
|
validation.rules.value = Wert
|
||||||
|
validation.rule.label.unique = Einmalig in Spalte
|
||||||
|
validation.rule.format = Format:
|
||||||
|
validation.rule.type = Typ:
|
||||||
|
|
||||||
dialog.validation.rules.title = Pr\u00fcfregeln
|
dialog.validation.rules.title = Pr\u00fcfregeln
|
||||||
dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"
|
dialog.validation.rules.header = Pr\u00fcfregeln f\u00fcr die Spalte "{0}"
|
||||||
|
|
||||||
context.menu.edit.column.rules = Pr\u00fcfregeln bearbeiten
|
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}
|
||||||
|
|
||||||
|
column = Spalte
|
||||||
|
|
||||||
|
format.type.DEFAULT = Standard
|
||||||
|
format.type.EMAIL = Email
|
||||||
|
format.type.URI = URI
|
||||||
|
format.type.BINARY = Bin\u00e4r
|
||||||
|
format.type.UUID = UUID
|
||||||
|
|||||||
@@ -1,75 +1,68 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import java.net.URL?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.CheckBox?>
|
<?import javafx.scene.control.CheckBox?>
|
||||||
|
<?import javafx.scene.control.ComboBox?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.Separator?>
|
||||||
<?import javafx.scene.control.Spinner?>
|
<?import javafx.scene.control.Spinner?>
|
||||||
<?import javafx.scene.control.TextArea?>
|
|
||||||
<?import javafx.scene.control.TextField?>
|
<?import javafx.scene.control.TextField?>
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
<?import javafx.scene.layout.GridPane?>
|
<?import javafx.scene.layout.GridPane?>
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
|
||||||
<?import org.fxmisc.richtext.CodeArea?>
|
<?import org.fxmisc.richtext.CodeArea?>
|
||||||
<?import java.net.URL?>
|
|
||||||
<GridPane hgap="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="600.0" vgap="10.0" xmlns="http://javafx.com/javafx/8.0.101" xmlns:fx="http://javafx.com/fxml/1">
|
<GridPane hgap="20.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="800.0" vgap="6.0" xmlns="http://javafx.com/javafx/8.0.76-ea" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints halignment="CENTER" hgrow="NEVER" maxWidth="50.0" prefWidth="50.0" />
|
<ColumnConstraints halignment="LEFT" hgrow="NEVER" />
|
||||||
<ColumnConstraints hgrow="NEVER" />
|
<ColumnConstraints halignment="LEFT" hgrow="ALWAYS" />
|
||||||
<ColumnConstraints hgrow="ALWAYS" />
|
<ColumnConstraints halignment="LEFT" hgrow="NEVER" />
|
||||||
</columnConstraints>
|
<ColumnConstraints halignment="LEFT" hgrow="ALWAYS" />
|
||||||
<rowConstraints>
|
</columnConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<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" valignment="CENTER" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" vgrow="SOMETIMES" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0" valignment="CENTER" 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" valignment="TOP" vgrow="ALWAYS" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
</rowConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<children>
|
||||||
</rowConstraints>
|
<Label text="%validation.rule.type" GridPane.columnSpan="2" GridPane.halignment="LEFT" GridPane.hgrow="ALWAYS" />
|
||||||
<children>
|
<Label text="%validation.rule.format" GridPane.columnSpan="2" GridPane.halignment="LEFT" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" />
|
||||||
<Label text="%validation.rule.label.not_empty" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
<ComboBox fx:id="typeComboBox" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.halignment="LEFT" GridPane.hgrow="ALWAYS" />
|
||||||
<Label text="%validation.rule.label.integer" GridPane.columnIndex="1" GridPane.rowIndex="2" />
|
<ComboBox fx:id="formatComboBox" prefWidth="150.0" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="1" visible="false" />
|
||||||
<Label text="%validation.rule.label.double" GridPane.columnIndex="1" GridPane.rowIndex="3" />
|
<TextField fx:id="formatTextField" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="1" visible="false" />
|
||||||
<Label text="%validation.rule.label.minlength" GridPane.columnIndex="1" GridPane.rowIndex="5" />
|
<CheckBox fx:id="enableNotEmptyRule" mnemonicParsing="false" text="%validation.rule.label.not_empty" GridPane.rowIndex="3" />
|
||||||
<Label text="%validation.rule.label.maxlength" GridPane.columnIndex="1" GridPane.rowIndex="6" />
|
<CheckBox fx:id="enableUniqueRule" mnemonicParsing="false" text="%validation.rule.label.unique" GridPane.columnIndex="2" GridPane.rowIndex="3" />
|
||||||
<Label text="%validation.rule.label.dateformat" GridPane.columnIndex="1" GridPane.rowIndex="7" />
|
<CheckBox fx:id="enableMinLengthRule" mnemonicParsing="false" text="%validation.rule.label.minlength" GridPane.rowIndex="4" />
|
||||||
<Label text="%validation.rule.label.alphanumeric" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
<Spinner fx:id="minLengthSpinner" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
||||||
<Label text="%validation.rule.label.regexp" GridPane.columnIndex="1" GridPane.rowIndex="8" />
|
<CheckBox fx:id="enableMaxLengthRule" mnemonicParsing="false" text="%validation.rule.label.maxlength" GridPane.columnIndex="2" GridPane.rowIndex="4" />
|
||||||
<Label text="%validation.rule.label.value_of" GridPane.columnIndex="1" GridPane.rowIndex="9" />
|
<Spinner fx:id="maxLengthSpinner" GridPane.columnIndex="3" GridPane.rowIndex="4" />
|
||||||
<Label text="%validation.rule.label.groovy" GridPane.columnIndex="1" GridPane.rowIndex="10" />
|
<CheckBox fx:id="enableRegexpRule" mnemonicParsing="false" text="%validation.rule.label.regexp" GridPane.rowIndex="5" />
|
||||||
<CheckBox fx:id="notEmptyRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="1" />
|
<TextField fx:id="regexpRuleTextField" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="5" />
|
||||||
<CheckBox fx:id="integerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="2" />
|
<CheckBox fx:id="enableValueOfRule" mnemonicParsing="false" text="%validation.rule.label.value_of" GridPane.rowIndex="6" />
|
||||||
<CheckBox fx:id="doublerRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="3" />
|
<TextField fx:id="valueOfRuleTextField" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="6" />
|
||||||
<CheckBox fx:id="alphanumericRuleCheckBox" mnemonicParsing="false" GridPane.columnIndex="2" GridPane.rowIndex="4" />
|
<CheckBox fx:id="enableGroovyRule" mnemonicParsing="false" text="%validation.rule.label.groovy" GridPane.rowIndex="7">
|
||||||
<Spinner fx:id="minLengthSpinner" GridPane.columnIndex="2" GridPane.rowIndex="5" />
|
<GridPane.margin>
|
||||||
<Spinner fx:id="maxLengthSpinner" GridPane.columnIndex="2" GridPane.rowIndex="6" />
|
<Insets top="8.0" />
|
||||||
<TextField fx:id="dateformatRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="7" />
|
</GridPane.margin>
|
||||||
<TextField fx:id="regexpRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="8" />
|
</CheckBox>
|
||||||
<TextField fx:id="valueOfRuleTextField" GridPane.columnIndex="2" GridPane.rowIndex="9" />
|
<CodeArea fx:id="groovyRuleTextArea" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="7">
|
||||||
<CodeArea fx:id="groovyRuleTextArea" prefHeight="300.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="10" GridPane.rowSpan="2" />
|
<GridPane.margin>
|
||||||
<CheckBox fx:id="enableNotEmptyRule" mnemonicParsing="false" GridPane.rowIndex="1" />
|
<Insets top="8.0" />
|
||||||
<CheckBox fx:id="enableIntegerRule" mnemonicParsing="false" GridPane.rowIndex="2" />
|
</GridPane.margin>
|
||||||
<CheckBox fx:id="enableDoubleRule" mnemonicParsing="false" GridPane.rowIndex="3" />
|
</CodeArea>
|
||||||
<CheckBox fx:id="enableAlphanumericRule" mnemonicParsing="false" GridPane.rowIndex="4" />
|
<Separator prefWidth="200.0" GridPane.columnSpan="4" GridPane.rowIndex="2" />
|
||||||
<CheckBox fx:id="enableMinLengthRule" mnemonicParsing="false" GridPane.rowIndex="5" />
|
|
||||||
<CheckBox fx:id="enableMaxLengthRule" mnemonicParsing="false" GridPane.rowIndex="6" />
|
</children>
|
||||||
<CheckBox fx:id="enableDateRule" mnemonicParsing="false" GridPane.rowIndex="7" />
|
<padding>
|
||||||
<CheckBox fx:id="enableRegexpRule" mnemonicParsing="false" GridPane.rowIndex="8" />
|
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||||
<CheckBox fx:id="enableValueOfRule" mnemonicParsing="false" GridPane.rowIndex="9" />
|
</padding>
|
||||||
<CheckBox fx:id="enableGroovyRule" mnemonicParsing="false" GridPane.rowIndex="10" />
|
|
||||||
<Label style="-fx-font-weight: bold;" text="%validation.rules.active" />
|
|
||||||
<Label style="-fx-font-weight: bold;" text="%validation.rules.name" GridPane.columnIndex="1" />
|
|
||||||
<Label style="-fx-font-weight: bold;" text="%validation.rules.value" GridPane.columnIndex="2" />
|
|
||||||
</children>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
|
||||||
</padding>
|
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<URL value="@/ninja/javafx/smartcsv/fx/smartcsv.css" />
|
<URL value="@/ninja/javafx/smartcsv/fx/smartcsv.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
|
|||||||
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo.afdesign
Normal file
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo.afdesign
Normal file
Binary file not shown.
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo.png
Normal file
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 750 B |
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo_256x256.png
Normal file
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo_256x256.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo_32x32.png
Normal file
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo_32x32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo_64x64.png
Normal file
BIN
src/main/resources/ninja/javafx/smartcsv/icon/logo_64x64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
109
src/test/java/ninja/javafx/smartcsv/files/FileStorageTest.java
Normal file
109
src/test/java/ninja/javafx/smartcsv/files/FileStorageTest.java
Normal 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -26,13 +26,11 @@
|
|||||||
|
|
||||||
package ninja.javafx.smartcsv.fx.table.model;
|
package ninja.javafx.smartcsv.fx.table.model;
|
||||||
|
|
||||||
import ninja.javafx.smartcsv.validation.ValidationConfiguration;
|
import org.junit.jupiter.api.Test;
|
||||||
import ninja.javafx.smartcsv.validation.Validator;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* unit test for the csv model
|
* unit test for the csv model
|
||||||
@@ -42,14 +40,13 @@ public class CSVModelTest {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// constants
|
// constants
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
static final String TESTHEADER = "TESTHEADER";
|
private static final String TESTHEADER = "TESTHEADER";
|
||||||
static final String TESTVALUE = "TESTVALUE";
|
private static final String TESTVALUE = "TESTVALUE";
|
||||||
static final String FILEPATH = "filepath";
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// subject under test
|
// subject under test
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
CSVModel sut = new CSVModel();
|
private CSVModel sut = new CSVModel();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// tests
|
// tests
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package ninja.javafx.smartcsv.fx.table.model;
|
package ninja.javafx.smartcsv.fx.table.model;
|
||||||
|
|
||||||
import ninja.javafx.smartcsv.validation.Validator;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.hamcrest.Matchers;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.hasKey;
|
import static org.hamcrest.Matchers.hasKey;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* unit test for row class
|
* unit test for row class
|
||||||
@@ -17,13 +15,13 @@ public class CSVRowTest {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// constants
|
// constants
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
static final String COLUMN = "COLUMN";
|
private static final String COLUMN = "COLUMN";
|
||||||
static final String VALUE = "VALUE";
|
private static final String VALUE = "VALUE";
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// subject under test
|
// subject under test
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
CSVRow sut = new CSVRow();
|
private CSVRow sut = new CSVRow();
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
package ninja.javafx.smartcsv.fx.table.model;
|
|
||||||
|
|
||||||
import ninja.javafx.smartcsv.validation.Validator;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.mockito.Matchers.anyInt;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* unit test for the value class
|
|
||||||
*/
|
|
||||||
public class CSVValueTest {
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// constants
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
static final String COLUMN = "COLUMN";
|
|
||||||
static final String VALUE = "VALUE";
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// mocks
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
Validator validator = mock(Validator.class);
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// subject under test
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CSVValue sut;
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// init
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
@Before
|
|
||||||
public void initialize() {
|
|
||||||
sut = new CSVValue();
|
|
||||||
sut.setValidator(validator);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// tests
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
@Test
|
|
||||||
public void set_value_calls_validation() {
|
|
||||||
//setup
|
|
||||||
sut.setColumn(COLUMN);
|
|
||||||
|
|
||||||
// execution
|
|
||||||
sut.setValue(VALUE);
|
|
||||||
|
|
||||||
// assertion
|
|
||||||
verify(validator).isValid(eq(COLUMN), eq(VALUE), anyInt());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2015 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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -28,68 +28,40 @@ package ninja.javafx.smartcsv.validation;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import org.junit.Before;
|
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static java.util.Collections.singletonList;
|
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.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* unit test for header validator
|
* unit test for header validator
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class HeaderValidationTest {
|
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
|
// tests
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void validation() {
|
@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
|
// execution
|
||||||
ValidationError result = sut.isHeaderValid(headerNames);
|
ValidationError result = sut.isHeaderValid(headerNames);
|
||||||
|
|
||||||
@@ -103,19 +75,33 @@ public class HeaderValidationTest {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// parameters for tests
|
// parameters for tests
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@Parameterized.Parameters
|
public static Stream<Arguments> validationConfigurations() {
|
||||||
public static Collection validationConfigurations() {
|
return Stream.of(
|
||||||
return asList(new Object[][] {
|
Arguments.of( json(), new String[] {}, true, null ),
|
||||||
{ json(), new String[] {}, true, null },
|
Arguments.of( json("a"), new String[] {"a"}, true, null ),
|
||||||
{ 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"))),
|
||||||
{ 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"))),
|
||||||
{ 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")) )
|
||||||
{ 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) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,76 +2,41 @@ package ninja.javafx.smartcsv.validation;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import org.junit.Before;
|
import ninja.javafx.smartcsv.validation.configuration.ValidationConfiguration;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
import static java.util.stream.Collectors.joining;
|
import static java.util.stream.Collectors.joining;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* unit test for validator
|
* unit test for validator
|
||||||
*/
|
*/
|
||||||
@RunWith(Parameterized.class)
|
|
||||||
public class ValidatorTest {
|
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
|
// tests
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@Test
|
@ParameterizedTest
|
||||||
public void validation() {
|
@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
|
// execution
|
||||||
ValidationError result = sut.isValid(column, value, 0);
|
ValidationError result = sut.isValid(0, "column", value);
|
||||||
|
|
||||||
// assertion
|
// assertion
|
||||||
assertThat(result == null, is(expectedResult));
|
assertThat(result == null, is(expectedResult));
|
||||||
@@ -83,45 +48,80 @@ public class ValidatorTest {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// parameters for tests
|
// parameters for tests
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@Parameterized.Parameters
|
public static Stream<Arguments> validationConfigurations() {
|
||||||
public static Collection validationConfigurations() {
|
return Stream.of(
|
||||||
return asList(new Object[][] {
|
Arguments.of( constraintsJSON("string", "required", true), "value", true, null ),
|
||||||
{ json("column", "not empty", true), "column", "value", true, null },
|
Arguments.of( constraintsJSON("string", "required", true), "", false, new ValidationMessage("validation.message.not.empty") ),
|
||||||
{ json("column", "not empty", true), "column", "", false, new ValidationMessage("validation.message.not.empty") },
|
Arguments.of( constraintsJSON("string", "required", true), null, false, new ValidationMessage("validation.message.not.empty") ),
|
||||||
{ json("column", "not empty", true), "column", null, false, new ValidationMessage("validation.message.not.empty") },
|
Arguments.of( constraintsJSON("integer", null, true), "999", true, null ),
|
||||||
{ json("column", "integer", true), "column", "999", true, null },
|
Arguments.of( constraintsJSON("integer", null, true), "a", false, new ValidationMessage("validation.message.integer") ),
|
||||||
{ json("column", "integer", true), "column", "a", false, new ValidationMessage("validation.message.integer") },
|
Arguments.of( constraintsJSON("number", null, true), "999", true, null ),
|
||||||
{ json("column", "double", true), "column", "999", true, null },
|
Arguments.of( constraintsJSON("number", null, true), "999.000", true, null ),
|
||||||
{ json("column", "double", true), "column", "999.000", true, null },
|
Arguments.of( constraintsJSON("number", null, true), "a", false, new ValidationMessage("validation.message.double") ),
|
||||||
{ json("column", "double", true), "column", "a", false, new ValidationMessage("validation.message.double") },
|
Arguments.of( constraintsJSON("string", "minLength", 2), "12", true, null ),
|
||||||
{ json("column", "minlength", 2), "column", "12", true, null },
|
Arguments.of( constraintsJSON("string", "minLength", 2), "1", false, new ValidationMessage("validation.message.min.length", "2") ),
|
||||||
{ json("column", "minlength", 2), "column", "1", false, new ValidationMessage("validation.message.min.length", "2") },
|
Arguments.of( constraintsJSON("string", "maxLength", 2), "12", true, null ),
|
||||||
{ json("column", "maxlength", 2), "column", "12", true, null },
|
Arguments.of( constraintsJSON("string", "maxLength", 2), "123", false, new ValidationMessage("validation.message.max.length", "2") ),
|
||||||
{ json("column", "maxlength", 2), "column", "123", false, new ValidationMessage("validation.message.max.length", "2") },
|
Arguments.of( constraintsJSON("string", "pattern", "[a-z]*"), "abc", true, null ),
|
||||||
{ json("column", "date", "yyyyMMdd"), "column", "20151127", true, null },
|
Arguments.of( constraintsJSON("string", "pattern", "[a-z]*"), "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") ),
|
||||||
{ json("column", "date", "yyyyMMdd"), "column", "27.11.2015", false, new ValidationMessage("validation.message.date.format", "yyyyMMdd") },
|
Arguments.of( constraintsJSON("string", "enum", asList("a","b","c","d","e")), "c", true, null ),
|
||||||
{ json("column", "alphanumeric", true), "column", "abcABC123", 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") ),
|
||||||
{ json("column", "alphanumeric", true), "column", "-abcABC123", false, new ValidationMessage("validation.message.alphanumeric") },
|
|
||||||
{ json("column", "regexp", "[a-z]*"), "column", "abc", true, null },
|
Arguments.of( formatJSON("string", null), "some string", true, null ),
|
||||||
{ json("column", "regexp", "[a-z]*"), "column", "abcA", false, new ValidationMessage("validation.message.regexp", "[a-z]*") },
|
Arguments.of( formatJSON("string", "email"), "test@javafx.ninja", true, null ),
|
||||||
{ json("column", "groovy", "value.contains('a')? 'true' : 'no a inside'"), "column", "abcdef", true, null },
|
Arguments.of( formatJSON("string", "email"), "wrong email", false, new ValidationMessage("validation.message.email") ),
|
||||||
{ json("column", "groovy", "value.contains('a')? 'true' : 'no a inside'"), "column", "bcdefg", false, new ValidationMessage("no a inside") },
|
Arguments.of( formatJSON("string", "uri"), "http://www.javafx.ninja", true, null ),
|
||||||
{ json("column", "value of", asList("a","b","c","d","e")), "column", "c", true, null },
|
Arguments.of( formatJSON("string", "uri"), "!$%&/()", false, new ValidationMessage("validation.message.uri") ),
|
||||||
{ 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") },
|
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) {
|
public static String constraintsJSON(String type, String constraint, Object value) {
|
||||||
String json = "{\"columns\":{\"" + column + "\":{\"" + rule + "\":";
|
String json = "{\"fields\": [ { \"name\": \"column\", \"type\" : \"" + type +"\"";
|
||||||
if (value instanceof String) {
|
|
||||||
json += "\""+ value + "\"";
|
if (constraint != null) {
|
||||||
} else if (value instanceof List) {
|
json += ", \"constraints\": { \"" + constraint + "\":";
|
||||||
List<String> list = (List<String>)value;
|
if (value instanceof String) {
|
||||||
json += "[" + list.stream().collect(joining(", ")) + "]";
|
json += "\"" + value + "\"";
|
||||||
} else {
|
} else if (value instanceof List) {
|
||||||
json += value;
|
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;
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user