Update (done by @taahanis, I'm just repushing)
This commit is contained in:
parent
1f32acc597
commit
48df906a43
|
@ -0,0 +1,3 @@
|
|||
/.gradle/
|
||||
/build/
|
||||
/.idea/
|
|
@ -1,8 +0,0 @@
|
|||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- oraclejdk7
|
||||
- openjdk7
|
||||
- openjdk6
|
||||
after_success:
|
||||
- mvn clean test jacoco:report coveralls:report
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,5 +1,13 @@
|
|||
# toml4j Changelog
|
||||
|
||||
## 0.7.3 / 2022-05-05
|
||||
|
||||
## Updated
|
||||
* Added SeriaizedName annotation support
|
||||
* Add proper indentation for array types
|
||||
* Append object fields instead of overwriting the whole file
|
||||
|
||||
|
||||
## 0.7.2 / 2017-08-05
|
||||
|
||||
## Updated
|
||||
|
@ -83,4 +91,4 @@
|
|||
* Support for [TOML 0.2](https://github.com/toml-lang/toml/tree/v0.2.0) spec, most notably table arrays.
|
||||
|
||||
## 0.1 / 2014-04-06
|
||||
* Support for [TOML 0.1](https://github.com/toml-lang/toml/tree/v0.1.0) spec.
|
||||
* Support for [TOML 0.1](https://github.com/toml-lang/toml/tree/v0.1.0) spec.
|
|
@ -1,10 +1,8 @@
|
|||
Thank you for taking the time to contribute to toml4j! Here are a few guidelines to streamline the process.
|
||||
|
||||
* Pull Requests should be opened against the wip branch. Master changes only when there is a new release.
|
||||
* Cover new or modified functionality with unit tests. Run `mvn test jacoco:report` and look at `target/site/jacoco/index.html` to view code coverage.
|
||||
* Amend README.md as necessary
|
||||
* Update the UNRELEASED section of CHANGELOG.md, as described in [keepachangelog.com](http://keepachangelog.com)
|
||||
* Use 2 spaces for indentation
|
||||
* Opening braces, parentheses, etc. are not on a new line
|
||||
|
||||
If you are unsure about how something should be implemented, open a pull request and we'll discuss it.
|
||||
If you are unsure about how something should be implemented, open a pull request and we'll discuss it.
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Moandji Ezana
|
||||
Copyright (c) 2022 Plexus
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
16
README.md
16
README.md
|
@ -2,9 +2,9 @@
|
|||
|
||||
toml4j is a [TOML 0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) parser for Java.
|
||||
|
||||
[![Maven Central](https://img.shields.io/maven-central/v/com.moandjiezana.toml/toml4j.svg)](https://search.maven.org/#search|gav|1|g%3A%22com.moandjiezana.toml%22%20AND%20a%3A%22toml4j%22) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Build Status](https://travis-ci.org/mwanji/toml4j.svg)](https://travis-ci.org/mwanji/toml4j) [![Coverage Status](https://coveralls.io/repos/mwanji/toml4j/badge.svg)](https://coveralls.io/r/mwanji/toml4j) [![Dependency Status](https://www.versioneye.com/user/projects/558bc2bc653232001e000001/badge.svg?style=flat)](https://www.versioneye.com/user/projects/558bc2bc653232001e000001)
|
||||
[//]: # ([![Maven Central](https://img.shields.io/maven-central/v/com.moandjiezana.toml/toml4j.svg)](https://search.maven.org/#search|gav|1|g%3A%22com.moandjiezana.toml%22%20AND%20a%3A%22toml4j%22) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Build Status](https://travis-ci.org/mwanji/toml4j.svg)](https://travis-ci.org/mwanji/toml4j) [![Coverage Status](https://coveralls.io/repos/mwanji/toml4j/badge.svg)](https://coveralls.io/r/mwanji/toml4j) [![Dependency Status](https://www.versioneye.com/user/projects/558bc2bc653232001e000001/badge.svg?style=flat)](https://www.versioneye.com/user/projects/558bc2bc653232001e000001))
|
||||
|
||||
For the bleeding-edge version integrating the latest specs, see the [work-in-progress branch](https://github.com/mwanji/toml4j/tree/wip).
|
||||
[//]: # (For the bleeding-edge version integrating the latest specs, see the [work-in-progress branch](https://github.com/mwanji/toml4j/tree/wip).)
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -12,9 +12,9 @@ Add the following dependency to your POM (or equivalent for other dependency man
|
|||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
<groupId>dev.plex</groupId>
|
||||
<artifactId>toml4j</artifactId>
|
||||
<version>0.7.2</version>
|
||||
<version>0.7.3</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -26,11 +26,11 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
...
|
||||
implementation 'com.moandjiezana.toml:toml4j:0.7.2'
|
||||
implementation 'dev.plex:toml4j:0.7.3'
|
||||
}
|
||||
```
|
||||
|
||||
Requires Java 1.6 or above.
|
||||
Requires Java 17 above.
|
||||
|
||||
## Quick start
|
||||
|
||||
|
@ -43,7 +43,7 @@ MyClass myClass = toml.to(MyClass.class);
|
|||
|
||||
## Usage
|
||||
|
||||
A `com.moandjiezana.toml.Toml` instance is populated by calling one of `read(File)`, `read(InputStream)`, `read(Reader)`, `read(String)` or `read(Toml)`.
|
||||
A `dev.plex.Toml` instance is populated by calling one of `read(File)`, `read(InputStream)`, `read(Reader)`, `read(String)` or `read(Toml)`.
|
||||
|
||||
```java
|
||||
Toml toml = new Toml().read("a=1");
|
||||
|
@ -338,4 +338,4 @@ Please see the [contribution guidelines](CONTRIBUTING.md).
|
|||
|
||||
## License
|
||||
|
||||
toml4j is copyright (c) 2013-2015 Moandji Ezana and is licensed under the [MIT License](LICENSE)
|
||||
toml4j is copyright (c) 2013-2015 Moandji Ezana and is licensed under the [MIT License](LICENSE)
|
|
@ -0,0 +1,16 @@
|
|||
plugins {
|
||||
java
|
||||
}
|
||||
|
||||
group = "dev.plex"
|
||||
version = "0.7.3"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.google.code.gson:gson:2.9.0")
|
||||
implementation("org.projectlombok:lombok:1.18.22")
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.22")
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
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='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# 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
|
||||
;;
|
||||
MSYS* | MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# 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"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
|
@ -0,0 +1,89 @@
|
|||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@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="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
161
pom.xml
161
pom.xml
|
@ -1,161 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.moandjiezana.toml</groupId>
|
||||
<artifactId>toml4j</artifactId>
|
||||
<version>0.7.3-SNAPSHOT</version>
|
||||
<name>toml4j</name>
|
||||
<description>A parser for TOML</description>
|
||||
<url>http://moandjiezana.com/toml/toml4j</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The MIT License</name>
|
||||
<url>http://www.opensource.org/licenses/mit-license.php</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:mwanji/toml4j.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:mwanji/toml4j.git</developerConnection>
|
||||
<url>https://github.com/mwanji/toml4j</url>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
<system>Github Issues</system>
|
||||
<url>https://github.com/mwanji/toml4j/issues</url>
|
||||
</issueManagement>
|
||||
<ciManagement>
|
||||
<system>Travis CI</system>
|
||||
<url>https://travis-ci.org/mwanji/toml4j</url>
|
||||
</ciManagement>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>moandji.ezana</id>
|
||||
<name>Moandji Ezana</name>
|
||||
<email>mwanji@gmail.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<inceptionYear>2013</inceptionYear>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.9</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>prepare-agent</id>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eluder.coveralls</groupId>
|
||||
<artifactId>coveralls-maven-plugin</artifactId>
|
||||
<version>4.3.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.8</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
<goals>deploy</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,2 @@
|
|||
rootProject.name = "toml4j"
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
class Identifier {
|
||||
|
||||
static final Identifier INVALID = new Identifier("", null);
|
||||
|
||||
private static final String ALLOWED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-";
|
||||
|
||||
private final String name;
|
||||
private final Type type;
|
||||
|
||||
static Identifier from(String name, Context context) {
|
||||
Type type;
|
||||
boolean valid;
|
||||
name = name.trim();
|
||||
if (name.startsWith("[[")) {
|
||||
type = Type.TABLE_ARRAY;
|
||||
valid = isValidTableArray(name, context);
|
||||
} else if (name.startsWith("[")) {
|
||||
type = Type.TABLE;
|
||||
valid = isValidTable(name, context);
|
||||
} else {
|
||||
type = Type.KEY;
|
||||
valid = isValidKey(name, context);
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
return Identifier.INVALID;
|
||||
}
|
||||
|
||||
return new Identifier(extractName(name), type);
|
||||
}
|
||||
|
||||
private Identifier(String name, Type type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
String getBareName() {
|
||||
if (isKey()) {
|
||||
return name;
|
||||
}
|
||||
|
||||
if (isTable()) {
|
||||
return name.substring(1, name.length() - 1);
|
||||
}
|
||||
|
||||
return name.substring(2, name.length() - 2);
|
||||
}
|
||||
|
||||
boolean isKey() {
|
||||
return type == Type.KEY;
|
||||
}
|
||||
|
||||
boolean isTable() {
|
||||
return type == Type.TABLE;
|
||||
}
|
||||
|
||||
boolean isTableArray() {
|
||||
return type == Type.TABLE_ARRAY;
|
||||
}
|
||||
|
||||
private static enum Type {
|
||||
KEY, TABLE, TABLE_ARRAY;
|
||||
}
|
||||
|
||||
private static String extractName(String raw) {
|
||||
boolean quoted = false;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < raw.length(); i++) {
|
||||
char c = raw.charAt(i);
|
||||
if (c == '"' && (i == 0 || raw.charAt(i - 1) != '\\')) {
|
||||
quoted = !quoted;
|
||||
sb.append('"');
|
||||
} else if (quoted || !Character.isWhitespace(c)) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return StringValueReaderWriter.STRING_VALUE_READER_WRITER.replaceUnicodeCharacters(sb.toString());
|
||||
}
|
||||
|
||||
private static boolean isValidKey(String name, Context context) {
|
||||
if (name.trim().isEmpty()) {
|
||||
context.errors.invalidKey(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char c = name.charAt(i);
|
||||
|
||||
if (c == '"' && (i == 0 || name.charAt(i - 1) != '\\')) {
|
||||
if (!quoted && i > 0 && name.charAt(i - 1) != '.') {
|
||||
context.errors.invalidKey(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
quoted = !quoted;
|
||||
} else if (!quoted && (ALLOWED_CHARS.indexOf(c) == -1)) {
|
||||
context.errors.invalidKey(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isValidTable(String name, Context context) {
|
||||
boolean valid = true;
|
||||
|
||||
if (!name.endsWith("]")) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
String trimmed = name.substring(1, name.length() - 1).trim();
|
||||
if (trimmed.isEmpty() || trimmed.charAt(0) == '.' || trimmed.endsWith(".")) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
context.errors.invalidTable(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
boolean dotAllowed = false;
|
||||
boolean quoteAllowed = true;
|
||||
boolean charAllowed = true;
|
||||
|
||||
for (int i = 0; i < trimmed.length(); i++) {
|
||||
char c = trimmed.charAt(i);
|
||||
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (Keys.isQuote(c)) {
|
||||
if (!quoteAllowed) {
|
||||
valid = false;
|
||||
} else if (quoted && trimmed.charAt(i - 1) != '\\') {
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else if (!quoted) {
|
||||
quoted = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else if (quoted) {
|
||||
continue;
|
||||
} else if (c == '.') {
|
||||
if (dotAllowed) {
|
||||
charAllowed = true;
|
||||
dotAllowed = false;
|
||||
quoteAllowed = true;
|
||||
} else {
|
||||
context.errors.emptyImplicitTable(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
} else if (Character.isWhitespace(c)) {
|
||||
char prev = trimmed.charAt(i - 1);
|
||||
if (!Character.isWhitespace(prev) && prev != '.') {
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else {
|
||||
if (charAllowed && ALLOWED_CHARS.indexOf(c) > -1) {
|
||||
charAllowed = true;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
context.errors.invalidTable(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isValidTableArray(String line, Context context) {
|
||||
boolean valid = true;
|
||||
|
||||
if (!line.endsWith("]]")) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
String trimmed = line.substring(2, line.length() - 2).trim();
|
||||
if (trimmed.isEmpty() || trimmed.charAt(0) == '.' || trimmed.endsWith(".")) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
context.errors.invalidTableArray(line, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
boolean dotAllowed = false;
|
||||
boolean quoteAllowed = true;
|
||||
boolean charAllowed = true;
|
||||
|
||||
for (int i = 0; i < trimmed.length(); i++) {
|
||||
char c = trimmed.charAt(i);
|
||||
|
||||
if (!valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '"') {
|
||||
if (!quoteAllowed) {
|
||||
valid = false;
|
||||
} else if (quoted && trimmed.charAt(i - 1) != '\\') {
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else if (!quoted) {
|
||||
quoted = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else if (quoted) {
|
||||
continue;
|
||||
} else if (c == '.') {
|
||||
if (dotAllowed) {
|
||||
charAllowed = true;
|
||||
dotAllowed = false;
|
||||
quoteAllowed = true;
|
||||
} else {
|
||||
context.errors.emptyImplicitTable(line, context.line.get());
|
||||
return false;
|
||||
}
|
||||
} else if (Character.isWhitespace(c)) {
|
||||
char prev = trimmed.charAt(i - 1);
|
||||
if (!Character.isWhitespace(prev) && prev != '.' && prev != '"') {
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else {
|
||||
if (charAllowed && ALLOWED_CHARS.indexOf(c) > -1) {
|
||||
charAllowed = true;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
context.errors.invalidTableArray(line, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
||||
class LiteralStringValueReader implements ValueReader {
|
||||
|
||||
static final LiteralStringValueReader LITERAL_STRING_VALUE_READER = new LiteralStringValueReader();
|
||||
|
||||
@Override
|
||||
public boolean canRead(String s) {
|
||||
return s.startsWith("'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(String s, AtomicInteger index, Context context) {
|
||||
int startLine = context.line.get();
|
||||
boolean terminated = false;
|
||||
int startIndex = index.incrementAndGet();
|
||||
|
||||
for (int i = index.get(); i < s.length(); i = index.incrementAndGet()) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == '\'') {
|
||||
terminated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!terminated) {
|
||||
Results.Errors errors = new Results.Errors();
|
||||
errors.unterminated(context.identifier.getName(), s.substring(startIndex), startLine);
|
||||
return errors;
|
||||
}
|
||||
|
||||
String substring = s.substring(startIndex, index.get());
|
||||
|
||||
return substring;
|
||||
}
|
||||
|
||||
private LiteralStringValueReader() {}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.TableArrayValueWriter.TABLE_ARRAY_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.ValueWriters.WRITERS;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class MapValueWriter implements ValueWriter {
|
||||
static final ValueWriter MAP_VALUE_WRITER = new MapValueWriter();
|
||||
|
||||
private static final Pattern REQUIRED_QUOTING_PATTERN = Pattern.compile("^.*[^A-Za-z\\d_-].*$");
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return value instanceof Map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
Map<?, ?> from = (Map<?, ?>) value;
|
||||
|
||||
if (hasPrimitiveValues(from, context)) {
|
||||
context.writeKey();
|
||||
}
|
||||
|
||||
// Render primitive types and arrays of primitive first so they are
|
||||
// grouped under the same table (if there is one)
|
||||
for (Map.Entry<?, ?> entry : from.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object fromValue = entry.getValue();
|
||||
if (fromValue == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ValueWriter valueWriter = WRITERS.findWriterFor(fromValue);
|
||||
if (valueWriter.isPrimitiveType()) {
|
||||
context.indent();
|
||||
context.write(quoteKey(key)).write(" = ");
|
||||
valueWriter.write(fromValue, context);
|
||||
context.write('\n');
|
||||
} else if (valueWriter == PRIMITIVE_ARRAY_VALUE_WRITER) {
|
||||
context.setArrayKey(key.toString());
|
||||
context.write(quoteKey(key)).write(" = ");
|
||||
valueWriter.write(fromValue, context);
|
||||
context.write('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Now render (sub)tables and arrays of tables
|
||||
for (Object key : from.keySet()) {
|
||||
Object fromValue = from.get(key);
|
||||
if (fromValue == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ValueWriter valueWriter = WRITERS.findWriterFor(fromValue);
|
||||
if (valueWriter == this || valueWriter == ObjectValueWriter.OBJECT_VALUE_WRITER || valueWriter == TABLE_ARRAY_VALUE_WRITER) {
|
||||
valueWriter.write(fromValue, context.pushTable(quoteKey(key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String quoteKey(Object key) {
|
||||
String stringKey = key.toString();
|
||||
Matcher matcher = REQUIRED_QUOTING_PATTERN.matcher(stringKey);
|
||||
if (matcher.matches()) {
|
||||
stringKey = "\"" + stringKey + "\"";
|
||||
}
|
||||
|
||||
return stringKey;
|
||||
}
|
||||
|
||||
private static boolean hasPrimitiveValues(Map<?, ?> values, WriterContext context) {
|
||||
for (Object key : values.keySet()) {
|
||||
Object fromValue = values.get(key);
|
||||
if (fromValue == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ValueWriter valueWriter = WRITERS.findWriterFor(fromValue);
|
||||
if (valueWriter.isPrimitiveType() || valueWriter == PRIMITIVE_ARRAY_VALUE_WRITER) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private MapValueWriter() {}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.MapValueWriter.MAP_VALUE_WRITER;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
class ObjectValueWriter implements ValueWriter {
|
||||
static final ValueWriter OBJECT_VALUE_WRITER = new ObjectValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
Map<String, Object> to = new LinkedHashMap<String, Object>();
|
||||
Set<Field> fields = getFields(value.getClass());
|
||||
for (Field field : fields) {
|
||||
to.put(field.getName(), getFieldValue(field, value));
|
||||
}
|
||||
|
||||
MAP_VALUE_WRITER.write(to, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Set<Field> getFields(Class<?> cls) {
|
||||
Set<Field> fields = new LinkedHashSet<Field>(Arrays.asList(cls.getDeclaredFields()));
|
||||
while (cls != Object.class) {
|
||||
fields.addAll(Arrays.asList(cls.getDeclaredFields()));
|
||||
cls = cls.getSuperclass();
|
||||
}
|
||||
removeConstantsAndSyntheticFields(fields);
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
private static void removeConstantsAndSyntheticFields(Set<Field> fields) {
|
||||
Iterator<Field> iterator = fields.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Field field = iterator.next();
|
||||
if ((Modifier.isFinal(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) || field.isSynthetic() || Modifier.isTransient(field.getModifiers())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getFieldValue(Field field, Object o) {
|
||||
boolean isAccessible = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
Object value = null;
|
||||
try {
|
||||
value = field.get(o);
|
||||
} catch (IllegalAccessException ignored) {
|
||||
}
|
||||
field.setAccessible(isAccessible);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private ObjectValueWriter() {}
|
||||
}
|
|
@ -1,429 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
/**
|
||||
* <p>Provides access to the keys and tables in a TOML data source.</p>
|
||||
*
|
||||
* <p>All getters can fall back to default values if they have been provided as a constructor argument.
|
||||
* Getters for simple values (String, Date, etc.) will return null if no matching key exists.
|
||||
* {@link #getList(String)}, {@link #getTable(String)} and {@link #getTables(String)} return empty values if there is no matching key.</p>
|
||||
*
|
||||
* <p>All read methods throw an {@link IllegalStateException} if the TOML is incorrect.</p>
|
||||
*
|
||||
* <p>Example usage:</p>
|
||||
* <pre><code>
|
||||
* Toml toml = new Toml().read(getTomlFile());
|
||||
* String name = toml.getString("name");
|
||||
* Long port = toml.getLong("server.ip"); // compound key. Is equivalent to:
|
||||
* Long port2 = toml.getTable("server").getLong("ip");
|
||||
* MyConfig config = toml.to(MyConfig.class);
|
||||
* </code></pre>
|
||||
*
|
||||
*/
|
||||
public class Toml {
|
||||
|
||||
private static final Gson DEFAULT_GSON = new Gson();
|
||||
|
||||
private Map<String, Object> values = new HashMap<String, Object>();
|
||||
private final Toml defaults;
|
||||
|
||||
/**
|
||||
* Creates Toml instance with no defaults.
|
||||
*/
|
||||
public Toml() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaults fallback values used when the requested key or table is not present in the TOML source that has been read.
|
||||
*/
|
||||
public Toml(Toml defaults) {
|
||||
this(defaults, new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from file.
|
||||
*
|
||||
* @param file The File to be read. Expected to be encoded as UTF-8.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If file contains invalid TOML
|
||||
*/
|
||||
public Toml read(File file) {
|
||||
try {
|
||||
return read(new InputStreamReader(new FileInputStream(file), "UTF8"));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from inputStream.
|
||||
*
|
||||
* @param inputStream Closed after it has been read.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If file contains invalid TOML
|
||||
*/
|
||||
public Toml read(InputStream inputStream) {
|
||||
return read(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from reader.
|
||||
*
|
||||
* @param reader Closed after it has been read.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If file contains invalid TOML
|
||||
*/
|
||||
public Toml read(Reader reader) {
|
||||
BufferedReader bufferedReader = null;
|
||||
try {
|
||||
bufferedReader = new BufferedReader(reader);
|
||||
|
||||
StringBuilder w = new StringBuilder();
|
||||
String line = bufferedReader.readLine();
|
||||
while (line != null) {
|
||||
w.append(line).append('\n');
|
||||
line = bufferedReader.readLine();
|
||||
}
|
||||
read(w.toString());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
bufferedReader.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from otherToml.
|
||||
*
|
||||
* @param otherToml
|
||||
* @return this instance
|
||||
*/
|
||||
public Toml read(Toml otherToml) {
|
||||
this.values = otherToml.values;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from tomlString.
|
||||
*
|
||||
* @param tomlString String to be read.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If tomlString is not valid TOML
|
||||
*/
|
||||
public Toml read(String tomlString) throws IllegalStateException {
|
||||
Results results = TomlParser.run(tomlString);
|
||||
if (results.errors.hasErrors()) {
|
||||
throw new IllegalStateException(results.errors.toString());
|
||||
}
|
||||
|
||||
this.values = results.consume();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getString(String key) {
|
||||
return (String) get(key);
|
||||
}
|
||||
|
||||
public String getString(String key, String defaultValue) {
|
||||
String val = getString(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
public Long getLong(String key) {
|
||||
return (Long) get(key);
|
||||
}
|
||||
|
||||
public Long getLong(String key, Long defaultValue) {
|
||||
Long val = getLong(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a TOML key
|
||||
* @param <T> type of list items
|
||||
* @return <code>null</code> if the key is not found
|
||||
*/
|
||||
public <T> List<T> getList(String key) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> list = (List<T>) get(key);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a TOML key
|
||||
* @param defaultValue a list of default values
|
||||
* @param <T> type of list items
|
||||
* @return <code>null</code> is the key is not found
|
||||
*/
|
||||
public <T> List<T> getList(String key, List<T> defaultValue) {
|
||||
List<T> list = getList(key);
|
||||
|
||||
return list != null ? list : defaultValue;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String key) {
|
||||
return (Boolean) get(key);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String key, Boolean defaultValue) {
|
||||
Boolean val = getBoolean(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
public Date getDate(String key) {
|
||||
return (Date) get(key);
|
||||
}
|
||||
|
||||
public Date getDate(String key, Date defaultValue) {
|
||||
Date val = getDate(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
public Double getDouble(String key) {
|
||||
return (Double) get(key);
|
||||
}
|
||||
|
||||
public Double getDouble(String key, Double defaultValue) {
|
||||
Double val = getDouble(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key A table name, not including square brackets.
|
||||
* @return A new Toml instance or <code>null</code> if no value is found for key.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Toml getTable(String key) {
|
||||
Map<String, Object> map = (Map<String, Object>) get(key);
|
||||
|
||||
return map != null ? new Toml(null, map) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key Name of array of tables, not including square brackets.
|
||||
* @return A {@link List} of Toml instances or <code>null</code> if no value is found for key.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Toml> getTables(String key) {
|
||||
List<Map<String, Object>> tableArray = (List<Map<String, Object>>) get(key);
|
||||
|
||||
if (tableArray == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<Toml> tables = new ArrayList<Toml>();
|
||||
|
||||
for (Map<String, Object> table : tableArray) {
|
||||
tables.add(new Toml(null, table));
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present
|
||||
*/
|
||||
public boolean contains(String key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present and is a primitive
|
||||
*/
|
||||
public boolean containsPrimitive(String key) {
|
||||
Object object = get(key);
|
||||
|
||||
return object != null && !(object instanceof Map) && !(object instanceof List);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present and is a table
|
||||
*/
|
||||
public boolean containsTable(String key) {
|
||||
Object object = get(key);
|
||||
|
||||
return object != null && (object instanceof Map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present and is a table array
|
||||
*/
|
||||
public boolean containsTableArray(String key) {
|
||||
Object object = get(key);
|
||||
|
||||
return object != null && (object instanceof List);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return values.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Populates an instance of targetClass with the values of this Toml instance.
|
||||
* The target's field names must match keys or tables.
|
||||
* Keys not present in targetClass will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* <p>Tables are recursively converted to custom classes or to {@link Map Map<String, Object>}.</p>
|
||||
*
|
||||
* <p>In addition to straight-forward conversion of TOML primitives, the following are also available:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>Integer -> int, long (or wrapper), {@link java.math.BigInteger}</li>
|
||||
* <li>Float -> float, double (or wrapper), {@link java.math.BigDecimal}</li>
|
||||
* <li>One-letter String -> char, {@link Character}</li>
|
||||
* <li>String -> {@link String}, enum, {@link java.net.URI}, {@link java.net.URL}</li>
|
||||
* <li>Multiline and Literal Strings -> {@link String}</li>
|
||||
* <li>Array -> {@link List}, {@link Set}, array. The generic type can be anything that can be converted.</li>
|
||||
* <li>Table -> Custom class, {@link Map Map<String, Object>}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param targetClass Class to deserialize TOML to.
|
||||
* @param <T> type of targetClass.
|
||||
* @return A new instance of targetClass.
|
||||
*/
|
||||
public <T> T to(Class<T> targetClass) {
|
||||
JsonElement json = DEFAULT_GSON.toJsonTree(toMap());
|
||||
|
||||
if (targetClass == JsonElement.class) {
|
||||
return targetClass.cast(json);
|
||||
}
|
||||
|
||||
return DEFAULT_GSON.fromJson(json, targetClass);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
HashMap<String, Object> valuesCopy = new HashMap<String, Object>(values);
|
||||
|
||||
if (defaults != null) {
|
||||
for (Map.Entry<String, Object> entry : defaults.values.entrySet()) {
|
||||
if (!valuesCopy.containsKey(entry.getKey())) {
|
||||
valuesCopy.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valuesCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a {@link Set} of Map.Entry instances. Modifications to the {@link Set} are not reflected in this Toml instance. Entries are immutable, so {@link Map.Entry#setValue(Object)} throws an UnsupportedOperationException.
|
||||
*/
|
||||
public Set<Map.Entry<String,Object>> entrySet() {
|
||||
Set<Map.Entry<String, Object>> entries = new LinkedHashSet<Map.Entry<String, Object>>();
|
||||
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
Class<? extends Object> entryClass = entry.getValue().getClass();
|
||||
|
||||
if (Map.class.isAssignableFrom(entryClass)) {
|
||||
entries.add(new Toml.Entry(entry.getKey(), getTable(entry.getKey())));
|
||||
} else if (List.class.isAssignableFrom(entryClass)) {
|
||||
List<?> value = (List<?>) entry.getValue();
|
||||
if (!value.isEmpty() && value.get(0) instanceof Map) {
|
||||
entries.add(new Toml.Entry(entry.getKey(), getTables(entry.getKey())));
|
||||
} else {
|
||||
entries.add(new Toml.Entry(entry.getKey(), value));
|
||||
}
|
||||
} else {
|
||||
entries.add(new Toml.Entry(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
private class Entry implements Map.Entry<String, Object> {
|
||||
|
||||
private final String key;
|
||||
private final Object value;
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(Object value) {
|
||||
throw new UnsupportedOperationException("TOML entry values cannot be changed.");
|
||||
}
|
||||
|
||||
private Entry(String key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object get(String key) {
|
||||
if (values.containsKey(key)) {
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
Object current = new HashMap<String, Object>(values);
|
||||
|
||||
Keys.Key[] keys = Keys.split(key);
|
||||
|
||||
for (Keys.Key k : keys) {
|
||||
if (k.index == -1 && current instanceof Map && ((Map<String, Object>) current).containsKey(k.path)) {
|
||||
return ((Map<String, Object>) current).get(k.path);
|
||||
}
|
||||
|
||||
current = ((Map<String, Object>) current).get(k.name);
|
||||
|
||||
if (k.index > -1 && current != null) {
|
||||
if (k.index >= ((List<?>) current).size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
current = ((List<?>) current).get(k.index);
|
||||
}
|
||||
|
||||
if (current == null) {
|
||||
return defaults != null ? defaults.get(key) : null;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
private Toml(Toml defaults, Map<String, Object> values) {
|
||||
this.values = values;
|
||||
this.defaults = defaults;
|
||||
}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.MapValueWriter.MAP_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.ObjectValueWriter.OBJECT_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.ValueWriters.WRITERS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* <p>Converts Objects to TOML</p>
|
||||
*
|
||||
* <p>An input Object can comprise arbitrarily nested combinations of Java primitive types,
|
||||
* other {@link Object}s, {@link Map}s, {@link List}s, and Arrays. {@link Object}s and {@link Map}s
|
||||
* are output to TOML tables, and {@link List}s and Array to TOML arrays.</p>
|
||||
*
|
||||
* <p>Example usage:</p>
|
||||
* <pre><code>
|
||||
* class AClass {
|
||||
* int anInt = 1;
|
||||
* int[] anArray = { 2, 3 };
|
||||
* }
|
||||
*
|
||||
* String tomlString = new TomlWriter().write(new AClass());
|
||||
* </code></pre>
|
||||
*/
|
||||
public class TomlWriter {
|
||||
|
||||
public static class Builder {
|
||||
private int keyIndentation;
|
||||
private int tableIndentation;
|
||||
private int arrayDelimiterPadding = 0;
|
||||
private TimeZone timeZone = TimeZone.getTimeZone("UTC");
|
||||
private boolean showFractionalSeconds = false;
|
||||
|
||||
public TomlWriter.Builder indentValuesBy(int spaces) {
|
||||
this.keyIndentation = spaces;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TomlWriter.Builder indentTablesBy(int spaces) {
|
||||
this.tableIndentation = spaces;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TomlWriter.Builder timeZone(TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param spaces number of spaces to put between opening square bracket and first item and between closing square bracket and last item
|
||||
* @return this TomlWriter.Builder instance
|
||||
*/
|
||||
public TomlWriter.Builder padArrayDelimitersBy(int spaces) {
|
||||
this.arrayDelimiterPadding = spaces;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TomlWriter build() {
|
||||
return new TomlWriter(keyIndentation, tableIndentation, arrayDelimiterPadding, timeZone, showFractionalSeconds);
|
||||
}
|
||||
|
||||
public TomlWriter.Builder showFractionalSeconds() {
|
||||
this.showFractionalSeconds = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final IndentationPolicy indentationPolicy;
|
||||
private final DatePolicy datePolicy;
|
||||
|
||||
/**
|
||||
* Creates a TomlWriter instance.
|
||||
*/
|
||||
public TomlWriter() {
|
||||
this(0, 0, 0, TimeZone.getTimeZone("UTC"), false);
|
||||
}
|
||||
|
||||
private TomlWriter(int keyIndentation, int tableIndentation, int arrayDelimiterPadding, TimeZone timeZone, boolean showFractionalSeconds) {
|
||||
this.indentationPolicy = new IndentationPolicy(keyIndentation, tableIndentation, arrayDelimiterPadding);
|
||||
this.datePolicy = new DatePolicy(timeZone, showFractionalSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object into TOML String.
|
||||
*
|
||||
* @param from the object to be written
|
||||
* @return a string containing the TOML representation of the given Object
|
||||
*/
|
||||
public String write(Object from) {
|
||||
try {
|
||||
StringWriter output = new StringWriter();
|
||||
write(from, output);
|
||||
|
||||
return output.toString();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object in TOML to a {@link File}. Output is encoded as UTF-8.
|
||||
*
|
||||
* @param from the object to be written
|
||||
* @param target the File to which the TOML will be written
|
||||
* @throws IOException if any file operations fail
|
||||
*/
|
||||
public void write(Object from, File target) throws IOException {
|
||||
OutputStream outputStream = new FileOutputStream(target);
|
||||
try {
|
||||
write(from, outputStream);
|
||||
} finally {
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object in TOML to a {@link OutputStream}. Output is encoded as UTF-8.
|
||||
*
|
||||
* @param from the object to be written
|
||||
* @param target the OutputStream to which the TOML will be written. The stream is NOT closed after being written to.
|
||||
* @throws IOException if target.write() fails
|
||||
*/
|
||||
public void write(Object from, OutputStream target) throws IOException {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(target, "UTF-8");
|
||||
write(from, writer);
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object in TOML to a {@link Writer}. You MUST ensure that the {@link Writer}s's encoding is set to UTF-8 for the TOML to be valid.
|
||||
*
|
||||
* @param from the object to be written. Can be a Map or a custom type. Must not be null.
|
||||
* @param target the Writer to which TOML will be written. The Writer is not closed.
|
||||
* @throws IOException if target.write() fails
|
||||
* @throws IllegalArgumentException if from is of an invalid type
|
||||
*/
|
||||
public void write(Object from, Writer target) throws IOException {
|
||||
ValueWriter valueWriter = WRITERS.findWriterFor(from);
|
||||
if (valueWriter == MAP_VALUE_WRITER || valueWriter == OBJECT_VALUE_WRITER) {
|
||||
WriterContext context = new WriterContext(indentationPolicy, datePolicy, target);
|
||||
valueWriter.write(from, context);
|
||||
} else {
|
||||
throw new IllegalArgumentException("An object of class " + from.getClass().getSimpleName() + " cannot produce valid TOML. Please pass in a Map or a custom type.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.ArrayValueReader.ARRAY_VALUE_READER;
|
||||
import static com.moandjiezana.toml.BooleanValueReaderWriter.BOOLEAN_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.DateValueReaderWriter.DATE_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.InlineTableValueReader.INLINE_TABLE_VALUE_READER;
|
||||
import static com.moandjiezana.toml.LiteralStringValueReader.LITERAL_STRING_VALUE_READER;
|
||||
import static com.moandjiezana.toml.MultilineLiteralStringValueReader.MULTILINE_LITERAL_STRING_VALUE_READER;
|
||||
import static com.moandjiezana.toml.MultilineStringValueReader.MULTILINE_STRING_VALUE_READER;
|
||||
import static com.moandjiezana.toml.NumberValueReaderWriter.NUMBER_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.StringValueReaderWriter.STRING_VALUE_READER_WRITER;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class ValueReaders {
|
||||
|
||||
static final ValueReaders VALUE_READERS = new ValueReaders();
|
||||
|
||||
Object convert(String value, AtomicInteger index, Context context) {
|
||||
String substring = value.substring(index.get());
|
||||
for (ValueReader valueParser : READERS) {
|
||||
if (valueParser.canRead(substring)) {
|
||||
return valueParser.read(value, index, context);
|
||||
}
|
||||
}
|
||||
|
||||
Results.Errors errors = new Results.Errors();
|
||||
errors.invalidValue(context.identifier.getName(), substring, context.line.get());
|
||||
return errors;
|
||||
}
|
||||
|
||||
private ValueReaders() {}
|
||||
|
||||
private static final ValueReader[] READERS = {
|
||||
MULTILINE_STRING_VALUE_READER, MULTILINE_LITERAL_STRING_VALUE_READER, LITERAL_STRING_VALUE_READER, STRING_VALUE_READER_WRITER, DATE_VALUE_READER_WRITER, NUMBER_VALUE_READER_WRITER, BOOLEAN_VALUE_READER_WRITER, ARRAY_VALUE_READER, INLINE_TABLE_VALUE_READER
|
||||
};
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.BooleanValueReaderWriter.BOOLEAN_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.DateValueReaderWriter.DATE_PARSER_JDK_6;
|
||||
import static com.moandjiezana.toml.DateValueReaderWriter.DATE_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.MapValueWriter.MAP_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.NumberValueReaderWriter.NUMBER_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.ObjectValueWriter.OBJECT_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER;
|
||||
import static com.moandjiezana.toml.StringValueReaderWriter.STRING_VALUE_READER_WRITER;
|
||||
import static com.moandjiezana.toml.TableArrayValueWriter.TABLE_ARRAY_VALUE_WRITER;
|
||||
|
||||
class ValueWriters {
|
||||
|
||||
static final ValueWriters WRITERS = new ValueWriters();
|
||||
|
||||
ValueWriter findWriterFor(Object value) {
|
||||
for (ValueWriter valueWriter : VALUE_WRITERS) {
|
||||
if (valueWriter.canWrite(value)) {
|
||||
return valueWriter;
|
||||
}
|
||||
}
|
||||
|
||||
return OBJECT_VALUE_WRITER;
|
||||
}
|
||||
|
||||
private ValueWriters() {}
|
||||
|
||||
private static DateValueReaderWriter getPlatformSpecificDateConverter() {
|
||||
String specificationVersion = Runtime.class.getPackage().getSpecificationVersion();
|
||||
return specificationVersion != null && specificationVersion.startsWith("1.6") ? DATE_PARSER_JDK_6 : DATE_VALUE_READER_WRITER;
|
||||
}
|
||||
|
||||
private static final ValueWriter[] VALUE_WRITERS = {
|
||||
STRING_VALUE_READER_WRITER, NUMBER_VALUE_READER_WRITER, BOOLEAN_VALUE_READER_WRITER, getPlatformSpecificDateConverter(),
|
||||
MAP_VALUE_WRITER, PRIMITIVE_ARRAY_VALUE_WRITER, TABLE_ARRAY_VALUE_WRITER
|
||||
};
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
|
||||
class WriterContext {
|
||||
private String arrayKey = null;
|
||||
private boolean isArrayOfTable = false;
|
||||
private boolean empty = true;
|
||||
private final String key;
|
||||
private final String currentTableIndent;
|
||||
private final String currentFieldIndent;
|
||||
private final Writer output;
|
||||
private final IndentationPolicy indentationPolicy;
|
||||
private final DatePolicy datePolicy;
|
||||
|
||||
WriterContext(IndentationPolicy indentationPolicy, DatePolicy datePolicy, Writer output) {
|
||||
this("", "", output, indentationPolicy, datePolicy);
|
||||
}
|
||||
|
||||
WriterContext pushTable(String newKey) {
|
||||
String newIndent = "";
|
||||
if (!key.isEmpty()) {
|
||||
newIndent = growIndent(indentationPolicy);
|
||||
}
|
||||
|
||||
String fullKey = key.isEmpty() ? newKey : key + "." + newKey;
|
||||
|
||||
WriterContext subContext = new WriterContext(fullKey, newIndent, output, indentationPolicy, datePolicy);
|
||||
if (!empty) {
|
||||
subContext.empty = false;
|
||||
}
|
||||
|
||||
return subContext;
|
||||
}
|
||||
|
||||
WriterContext pushTableFromArray() {
|
||||
WriterContext subContext = new WriterContext(key, currentTableIndent, output, indentationPolicy, datePolicy);
|
||||
if (!empty) {
|
||||
subContext.empty = false;
|
||||
}
|
||||
subContext.setIsArrayOfTable(true);
|
||||
|
||||
return subContext;
|
||||
}
|
||||
|
||||
WriterContext write(String s) {
|
||||
try {
|
||||
output.write(s);
|
||||
if (empty && !s.isEmpty()) {
|
||||
empty = false;
|
||||
}
|
||||
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
void write(char[] chars) {
|
||||
for (char c : chars) {
|
||||
write(c);
|
||||
}
|
||||
}
|
||||
|
||||
WriterContext write(char c) {
|
||||
try {
|
||||
output.write(c);
|
||||
empty = false;
|
||||
|
||||
return this;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
void writeKey() {
|
||||
if (key.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
write('\n');
|
||||
}
|
||||
|
||||
write(currentTableIndent);
|
||||
|
||||
if (isArrayOfTable) {
|
||||
write("[[").write(key).write("]]\n");
|
||||
} else {
|
||||
write('[').write(key).write("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void writeArrayDelimiterPadding() {
|
||||
for (int i = 0; i < indentationPolicy.getArrayDelimiterPadding(); i++) {
|
||||
write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
void indent() {
|
||||
if (!key.isEmpty()) {
|
||||
write(currentFieldIndent);
|
||||
}
|
||||
}
|
||||
|
||||
DatePolicy getDatePolicy() {
|
||||
return datePolicy;
|
||||
}
|
||||
|
||||
WriterContext setIsArrayOfTable(boolean isArrayOfTable) {
|
||||
this.isArrayOfTable = isArrayOfTable;
|
||||
return this;
|
||||
}
|
||||
|
||||
WriterContext setArrayKey(String arrayKey) {
|
||||
this.arrayKey = arrayKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
String getContextPath() {
|
||||
return key.isEmpty() ? arrayKey : key + "." + arrayKey;
|
||||
}
|
||||
|
||||
private String growIndent(IndentationPolicy indentationPolicy) {
|
||||
return currentTableIndent + fillStringWithSpaces(indentationPolicy.getTableIndent());
|
||||
}
|
||||
|
||||
private String fillStringWithSpaces(int count) {
|
||||
char[] chars = new char[count];
|
||||
Arrays.fill(chars, ' ');
|
||||
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
private WriterContext(String key, String tableIndent, Writer output, IndentationPolicy indentationPolicy, DatePolicy datePolicy) {
|
||||
this.key = key;
|
||||
this.output = output;
|
||||
this.indentationPolicy = indentationPolicy;
|
||||
this.currentTableIndent = tableIndent;
|
||||
this.datePolicy = datePolicy;
|
||||
this.currentFieldIndent = tableIndent + fillStringWithSpaces(this.indentationPolicy.getKeyValueIndent());
|
||||
}
|
||||
}
|
|
@ -1,29 +1,26 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.ValueReaders.VALUE_READERS;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class ArrayValueReader implements ValueReader {
|
||||
|
||||
static final ArrayValueReader ARRAY_VALUE_READER = new ArrayValueReader();
|
||||
public class ArrayValueReader implements ValueReader {
|
||||
|
||||
public static final ArrayValueReader ARRAY_VALUE_READER = new ArrayValueReader();
|
||||
@Override
|
||||
public boolean canRead(String s) {
|
||||
return s.startsWith("[");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(String s, AtomicInteger index, Context context) {
|
||||
public Object read(String s, AtomicInteger index, dev.plex.toml.Context context) {
|
||||
AtomicInteger line = context.line;
|
||||
int startLine = line.get();
|
||||
int startIndex = index.get();
|
||||
List<Object> arrayItems = new ArrayList<Object>();
|
||||
boolean terminated = false;
|
||||
boolean inComment = false;
|
||||
Results.Errors errors = new Results.Errors();
|
||||
dev.plex.toml.Results.Errors errors = new dev.plex.toml.Results.Errors();
|
||||
|
||||
for (int i = index.incrementAndGet(); i < s.length(); i = index.incrementAndGet()) {
|
||||
|
||||
|
@ -38,8 +35,8 @@ class ArrayValueReader implements ValueReader {
|
|||
continue;
|
||||
} else if (c == '[') {
|
||||
Object converted = read(s, index, context);
|
||||
if (converted instanceof Results.Errors) {
|
||||
errors.add((Results.Errors) converted);
|
||||
if (converted instanceof dev.plex.toml.Results.Errors) {
|
||||
errors.add((dev.plex.toml.Results.Errors) converted);
|
||||
} else if (!isHomogenousArray(converted, arrayItems)) {
|
||||
errors.heterogenous(context.identifier.getName(), line.get());
|
||||
} else {
|
||||
|
@ -50,9 +47,9 @@ class ArrayValueReader implements ValueReader {
|
|||
terminated = true;
|
||||
break;
|
||||
} else {
|
||||
Object converted = VALUE_READERS.convert(s, index, context);
|
||||
if (converted instanceof Results.Errors) {
|
||||
errors.add((Results.Errors) converted);
|
||||
Object converted = ValueReaders.VALUE_READERS.convert(s, index, context);
|
||||
if (converted instanceof dev.plex.toml.Results.Errors) {
|
||||
errors.add((dev.plex.toml.Results.Errors) converted);
|
||||
} else if (!isHomogenousArray(converted, arrayItems)) {
|
||||
errors.heterogenous(context.identifier.getName(), line.get());
|
||||
} else {
|
|
@ -1,13 +1,14 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import static com.moandjiezana.toml.ValueWriters.WRITERS;
|
||||
import static dev.plex.toml.ValueWriters.WRITERS;
|
||||
|
||||
abstract class ArrayValueWriter implements ValueWriter {
|
||||
public abstract class ArrayValueWriter implements dev.plex.toml.ValueWriter
|
||||
{
|
||||
static protected boolean isArrayish(Object value) {
|
||||
return value instanceof Collection || value.getClass().isArray();
|
||||
}
|
||||
|
@ -20,7 +21,7 @@ abstract class ArrayValueWriter implements ValueWriter {
|
|||
static boolean isArrayOfPrimitive(Object array) {
|
||||
Object first = peek(array);
|
||||
if (first != null) {
|
||||
ValueWriter valueWriter = WRITERS.findWriterFor(first);
|
||||
dev.plex.toml.ValueWriter valueWriter = WRITERS.findWriterFor(first);
|
||||
return valueWriter.isPrimitiveType() || isArrayish(first);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
abstract class Container {
|
||||
public abstract class Container {
|
||||
|
||||
abstract boolean accepts(String key);
|
||||
abstract void put(String key, Object value);
|
||||
|
@ -32,7 +32,7 @@ abstract class Container {
|
|||
|
||||
@Override
|
||||
boolean accepts(String key) {
|
||||
return !values.containsKey(key) || values.get(key) instanceof Container.TableArray;
|
||||
return !values.containsKey(key) || values.get(key) instanceof TableArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,10 +58,10 @@ abstract class Container {
|
|||
*/
|
||||
Map<String, Object> consume() {
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
if (entry.getValue() instanceof Container.Table) {
|
||||
entry.setValue(((Container.Table) entry.getValue()).consume());
|
||||
} else if (entry.getValue() instanceof Container.TableArray) {
|
||||
entry.setValue(((Container.TableArray) entry.getValue()).getValues());
|
||||
if (entry.getValue() instanceof Table) {
|
||||
entry.setValue(((Table) entry.getValue()).consume());
|
||||
} else if (entry.getValue() instanceof TableArray) {
|
||||
entry.setValue(((TableArray) entry.getValue()).getValues());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,10 +75,10 @@ abstract class Container {
|
|||
}
|
||||
|
||||
static class TableArray extends Container {
|
||||
private final List<Container.Table> values = new ArrayList<Container.Table>();
|
||||
private final List<Table> values = new ArrayList<Table>();
|
||||
|
||||
TableArray() {
|
||||
values.add(new Container.Table());
|
||||
values.add(new Table());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -88,7 +88,7 @@ abstract class Container {
|
|||
|
||||
@Override
|
||||
void put(String key, Object value) {
|
||||
values.add((Container.Table) value);
|
||||
values.add((Table) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,13 +102,13 @@ abstract class Container {
|
|||
|
||||
List<Map<String, Object>> getValues() {
|
||||
ArrayList<Map<String, Object>> unwrappedValues = new ArrayList<Map<String,Object>>();
|
||||
for (Container.Table table : values) {
|
||||
for (Table table : values) {
|
||||
unwrappedValues.add(table.consume());
|
||||
}
|
||||
return unwrappedValues;
|
||||
}
|
||||
|
||||
Container.Table getCurrent() {
|
||||
Table getCurrent() {
|
||||
return values.get(values.size() - 1);
|
||||
}
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class Context {
|
||||
final Identifier identifier;
|
||||
public class Context {
|
||||
final dev.plex.toml.Identifier identifier;
|
||||
final AtomicInteger line;
|
||||
final Results.Errors errors;
|
||||
|
||||
public Context(Identifier identifier, AtomicInteger line, Results.Errors errors) {
|
||||
public Context(dev.plex.toml.Identifier identifier, AtomicInteger line, Results.Errors errors) {
|
||||
this.identifier = identifier;
|
||||
this.line = line;
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
public Context with(Identifier identifier) {
|
||||
public Context with(dev.plex.toml.Identifier identifier) {
|
||||
return new Context(identifier, line, errors);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.TimeZone;
|
||||
|
||||
class DatePolicy {
|
||||
public class DatePolicy {
|
||||
|
||||
private final TimeZone timeZone;
|
||||
private final boolean showFractionalSeconds;
|
|
@ -1,4 +1,4 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -7,7 +7,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class DateValueReaderWriter implements ValueReader, ValueWriter {
|
||||
public class DateValueReaderWriter implements ValueReader, ValueWriter {
|
||||
|
||||
static final DateValueReaderWriter DATE_VALUE_READER_WRITER = new DateValueReaderWriter();
|
||||
static final DateValueReaderWriter DATE_PARSER_JDK_6 = new DateConverterJdk6();
|
||||
|
@ -50,7 +50,7 @@ class DateValueReaderWriter implements ValueReader, ValueWriter {
|
|||
|
||||
String s = sb.toString();
|
||||
Matcher matcher = DATE_REGEX.matcher(s);
|
||||
|
||||
|
||||
if (!matcher.matches()) {
|
||||
Results.Errors errors = new Results.Errors();
|
||||
errors.invalidValue(context.identifier.getName(), s, context.line.get());
|
|
@ -0,0 +1,331 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
public class Identifier
|
||||
{
|
||||
|
||||
static final Identifier INVALID = new Identifier("", null);
|
||||
|
||||
private static final String ALLOWED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_-";
|
||||
|
||||
private final String name;
|
||||
private final Type type;
|
||||
|
||||
static Identifier from(String name, Context context)
|
||||
{
|
||||
Type type;
|
||||
boolean valid;
|
||||
name = name.trim();
|
||||
if (name.startsWith("[["))
|
||||
{
|
||||
type = Type.TABLE_ARRAY;
|
||||
valid = isValidTableArray(name, context);
|
||||
} else if (name.startsWith("["))
|
||||
{
|
||||
type = Type.TABLE;
|
||||
valid = isValidTable(name, context);
|
||||
} else
|
||||
{
|
||||
type = Type.KEY;
|
||||
valid = isValidKey(name, context);
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
return Identifier.INVALID;
|
||||
}
|
||||
|
||||
return new Identifier(extractName(name), type);
|
||||
}
|
||||
|
||||
private Identifier(String name, Type type)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
String getBareName()
|
||||
{
|
||||
if (isKey())
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
if (isTable())
|
||||
{
|
||||
return name.substring(1, name.length() - 1);
|
||||
}
|
||||
|
||||
return name.substring(2, name.length() - 2);
|
||||
}
|
||||
|
||||
boolean isKey()
|
||||
{
|
||||
return type == Type.KEY;
|
||||
}
|
||||
|
||||
boolean isTable()
|
||||
{
|
||||
return type == Type.TABLE;
|
||||
}
|
||||
|
||||
boolean isTableArray()
|
||||
{
|
||||
return type == Type.TABLE_ARRAY;
|
||||
}
|
||||
|
||||
private static enum Type
|
||||
{
|
||||
KEY, TABLE, TABLE_ARRAY;
|
||||
}
|
||||
|
||||
private static String extractName(String raw)
|
||||
{
|
||||
boolean quoted = false;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < raw.length(); i++)
|
||||
{
|
||||
char c = raw.charAt(i);
|
||||
if (c == '"' && (i == 0 || raw.charAt(i - 1) != '\\'))
|
||||
{
|
||||
quoted = !quoted;
|
||||
sb.append('"');
|
||||
} else if (quoted || !Character.isWhitespace(c))
|
||||
{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
return StringValueReaderWriter.STRING_VALUE_READER_WRITER.replaceUnicodeCharacters(sb.toString());
|
||||
}
|
||||
|
||||
private static boolean isValidKey(String name, Context context)
|
||||
{
|
||||
if (name.trim().isEmpty())
|
||||
{
|
||||
context.errors.invalidKey(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
for (int i = 0; i < name.length(); i++)
|
||||
{
|
||||
char c = name.charAt(i);
|
||||
|
||||
if (c == '"' && (i == 0 || name.charAt(i - 1) != '\\'))
|
||||
{
|
||||
if (!quoted && i > 0 && name.charAt(i - 1) != '.')
|
||||
{
|
||||
context.errors.invalidKey(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
quoted = !quoted;
|
||||
} else if (!quoted && (ALLOWED_CHARS.indexOf(c) == -1))
|
||||
{
|
||||
context.errors.invalidKey(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isValidTable(String name, Context context)
|
||||
{
|
||||
boolean valid = true;
|
||||
|
||||
if (!name.endsWith("]"))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
String trimmed = name.substring(1, name.length() - 1).trim();
|
||||
if (trimmed.isEmpty() || trimmed.charAt(0) == '.' || trimmed.endsWith("."))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
context.errors.invalidTable(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
boolean dotAllowed = false;
|
||||
boolean quoteAllowed = true;
|
||||
boolean charAllowed = true;
|
||||
|
||||
for (int i = 0; i < trimmed.length(); i++)
|
||||
{
|
||||
char c = trimmed.charAt(i);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (Keys.isQuote(c))
|
||||
{
|
||||
if (!quoteAllowed)
|
||||
{
|
||||
valid = false;
|
||||
} else if (quoted && trimmed.charAt(i - 1) != '\\')
|
||||
{
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else if (!quoted)
|
||||
{
|
||||
quoted = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else if (quoted)
|
||||
{
|
||||
continue;
|
||||
} else if (c == '.')
|
||||
{
|
||||
if (dotAllowed)
|
||||
{
|
||||
charAllowed = true;
|
||||
dotAllowed = false;
|
||||
quoteAllowed = true;
|
||||
} else
|
||||
{
|
||||
context.errors.emptyImplicitTable(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
} else if (Character.isWhitespace(c))
|
||||
{
|
||||
char prev = trimmed.charAt(i - 1);
|
||||
if (!Character.isWhitespace(prev) && prev != '.')
|
||||
{
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (charAllowed && ALLOWED_CHARS.indexOf(c) > -1)
|
||||
{
|
||||
charAllowed = true;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
context.errors.invalidTable(name, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isValidTableArray(String line, Context context)
|
||||
{
|
||||
boolean valid = true;
|
||||
|
||||
if (!line.endsWith("]]"))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
String trimmed = line.substring(2, line.length() - 2).trim();
|
||||
if (trimmed.isEmpty() || trimmed.charAt(0) == '.' || trimmed.endsWith("."))
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
context.errors.invalidTableArray(line, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean quoted = false;
|
||||
boolean dotAllowed = false;
|
||||
boolean quoteAllowed = true;
|
||||
boolean charAllowed = true;
|
||||
|
||||
for (int i = 0; i < trimmed.length(); i++)
|
||||
{
|
||||
char c = trimmed.charAt(i);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
if (!quoteAllowed)
|
||||
{
|
||||
valid = false;
|
||||
} else if (quoted && trimmed.charAt(i - 1) != '\\')
|
||||
{
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else if (!quoted)
|
||||
{
|
||||
quoted = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else if (quoted)
|
||||
{
|
||||
continue;
|
||||
} else if (c == '.')
|
||||
{
|
||||
if (dotAllowed)
|
||||
{
|
||||
charAllowed = true;
|
||||
dotAllowed = false;
|
||||
quoteAllowed = true;
|
||||
} else
|
||||
{
|
||||
context.errors.emptyImplicitTable(line, context.line.get());
|
||||
return false;
|
||||
}
|
||||
} else if (Character.isWhitespace(c))
|
||||
{
|
||||
char prev = trimmed.charAt(i - 1);
|
||||
if (!Character.isWhitespace(prev) && prev != '.' && prev != '"')
|
||||
{
|
||||
charAllowed = false;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (charAllowed && ALLOWED_CHARS.indexOf(c) > -1)
|
||||
{
|
||||
charAllowed = true;
|
||||
dotAllowed = true;
|
||||
quoteAllowed = false;
|
||||
} else
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
context.errors.invalidTableArray(line, context.line.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class IdentifierConverter {
|
||||
public class IdentifierConverter {
|
||||
|
||||
static final IdentifierConverter IDENTIFIER_CONVERTER = new IdentifierConverter();
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
/**
|
||||
* Controls how a {@link TomlWriter} indents tables and key/value pairs.
|
||||
*
|
||||
* The default policy is to not indent.
|
||||
*/
|
||||
class IndentationPolicy {
|
||||
public class IndentationPolicy {
|
||||
private final int tableIndent;
|
||||
private final int keyValueIndent;
|
||||
private final int arrayDelimiterPadding;
|
|
@ -1,11 +1,10 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.ValueReaders.VALUE_READERS;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class InlineTableValueReader implements ValueReader {
|
||||
class InlineTableValueReader implements dev.plex.toml.ValueReader
|
||||
{
|
||||
|
||||
static final InlineTableValueReader INLINE_TABLE_VALUE_READER = new InlineTableValueReader();
|
||||
|
||||
|
@ -15,7 +14,7 @@ class InlineTableValueReader implements ValueReader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object read(String s, AtomicInteger sharedIndex, Context context) {
|
||||
public Object read(String s, AtomicInteger sharedIndex, dev.plex.toml.Context context) {
|
||||
AtomicInteger line = context.line;
|
||||
int startLine = line.get();
|
||||
int startIndex = sharedIndex.get();
|
||||
|
@ -24,16 +23,16 @@ class InlineTableValueReader implements ValueReader {
|
|||
boolean terminated = false;
|
||||
StringBuilder currentKey = new StringBuilder();
|
||||
HashMap<String, Object> results = new HashMap<String, Object>();
|
||||
Results.Errors errors = new Results.Errors();
|
||||
dev.plex.toml.Results.Errors errors = new dev.plex.toml.Results.Errors();
|
||||
|
||||
for (int i = sharedIndex.incrementAndGet(); sharedIndex.get() < s.length(); i = sharedIndex.incrementAndGet()) {
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (inValue && !Character.isWhitespace(c)) {
|
||||
Object converted = VALUE_READERS.convert(s, sharedIndex, context.with(Identifier.from(currentKey.toString(), context)));
|
||||
Object converted = dev.plex.toml.ValueReaders.VALUE_READERS.convert(s, sharedIndex, context.with(dev.plex.toml.Identifier.from(currentKey.toString(), context)));
|
||||
|
||||
if (converted instanceof Results.Errors) {
|
||||
errors.add((Results.Errors) converted);
|
||||
if (converted instanceof dev.plex.toml.Results.Errors) {
|
||||
errors.add((dev.plex.toml.Results.Errors) converted);
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -21,7 +21,7 @@ class Keys {
|
|||
}
|
||||
}
|
||||
|
||||
static Keys.Key[] split(String key) {
|
||||
static Key[] split(String key) {
|
||||
List<Key> splitKey = new ArrayList<Key>();
|
||||
StringBuilder current = new StringBuilder();
|
||||
boolean quoted = false;
|
|
@ -0,0 +1,47 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class LiteralStringValueReader implements ValueReader
|
||||
{
|
||||
public static final LiteralStringValueReader LITERAL_STRING_VALUE_READER = new LiteralStringValueReader();
|
||||
@Override
|
||||
public boolean canRead(String s)
|
||||
{
|
||||
return s.startsWith("'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(String s, AtomicInteger index, dev.plex.toml.Context context)
|
||||
{
|
||||
int startLine = context.line.get();
|
||||
boolean terminated = false;
|
||||
int startIndex = index.incrementAndGet();
|
||||
|
||||
for (int i = index.get(); i < s.length(); i = index.incrementAndGet())
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
|
||||
if (c == '\'')
|
||||
{
|
||||
terminated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!terminated)
|
||||
{
|
||||
Results.Errors errors = new Results.Errors();
|
||||
errors.unterminated(context.identifier.getName(), s.substring(startIndex), startLine);
|
||||
return errors;
|
||||
}
|
||||
|
||||
String substring = s.substring(startIndex, index.get());
|
||||
|
||||
return substring;
|
||||
}
|
||||
|
||||
private LiteralStringValueReader()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class MapValueWriter implements dev.plex.toml.ValueWriter
|
||||
{
|
||||
static final dev.plex.toml.ValueWriter MAP_VALUE_WRITER = new MapValueWriter();
|
||||
|
||||
private static final Pattern REQUIRED_QUOTING_PATTERN = Pattern.compile("^.*[^A-Za-z\\d_-].*$");
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value)
|
||||
{
|
||||
return value instanceof Map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context)
|
||||
{
|
||||
File file = null;
|
||||
if (context.file != null)
|
||||
{
|
||||
file = context.file;
|
||||
}
|
||||
|
||||
Map<?, ?> from = (Map<?, ?>) value;
|
||||
|
||||
Toml toml = null;
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
toml = new Toml().read(file);
|
||||
}
|
||||
|
||||
if (hasPrimitiveValues(from, context))
|
||||
{
|
||||
if (context.hasRun)
|
||||
{
|
||||
if (toml != null)
|
||||
{
|
||||
if (!toml.getValues().containsKey(context.key))
|
||||
{
|
||||
context.writeKey();
|
||||
}
|
||||
} else
|
||||
{
|
||||
context.writeKey();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Render primitive types and arrays of primitive first so they are
|
||||
// grouped under the same table (if there is one)
|
||||
for (Map.Entry<?, ?> entry : from.entrySet())
|
||||
{
|
||||
Object key = entry.getKey();
|
||||
Object fromValue = entry.getValue();
|
||||
if (fromValue == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context.hasRun && toml != null)
|
||||
{
|
||||
if (context.key != null)
|
||||
{
|
||||
if (key.toString().equalsIgnoreCase(context.key)) continue;
|
||||
if (toml.contains(context.key + "." + key)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
dev.plex.toml.ValueWriter valueWriter = dev.plex.toml.ValueWriters.WRITERS.findWriterFor(fromValue);
|
||||
if (valueWriter.isPrimitiveType())
|
||||
{
|
||||
context.indent();
|
||||
context.write(quoteKey(key)).write(" = ");
|
||||
valueWriter.write(fromValue, context);
|
||||
context.write('\n');
|
||||
} else if (valueWriter == dev.plex.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER)
|
||||
{
|
||||
context.indent();
|
||||
context.setArrayKey(key.toString());
|
||||
context.write(quoteKey(key)).write(" = ");
|
||||
valueWriter.write(fromValue, context);
|
||||
context.write('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Now render (sub)tables and arrays of tables
|
||||
for (Object key : from.keySet())
|
||||
{
|
||||
Object fromValue = from.get(key);
|
||||
if (fromValue == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context.hasRun && toml != null)
|
||||
{
|
||||
if (context.key != null)
|
||||
{
|
||||
if (key.toString().equalsIgnoreCase(context.key)) continue;
|
||||
if (toml.contains(context.key + "." + key)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
dev.plex.toml.ValueWriter valueWriter = dev.plex.toml.ValueWriters.WRITERS.findWriterFor(fromValue);
|
||||
if (valueWriter == this || valueWriter == dev.plex.toml.ObjectValueWriter.OBJECT_VALUE_WRITER || valueWriter == dev.plex.toml.TableArrayValueWriter.TABLE_ARRAY_VALUE_WRITER)
|
||||
{
|
||||
WriterContext context1 = context.pushTable(quoteKey(key));
|
||||
context1.parentName = key.toString();
|
||||
context1.hasRun = true;
|
||||
context1.file = context.file;
|
||||
valueWriter.write(fromValue, context1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String quoteKey(Object key)
|
||||
{
|
||||
String stringKey = key.toString();
|
||||
Matcher matcher = REQUIRED_QUOTING_PATTERN.matcher(stringKey);
|
||||
if (matcher.matches())
|
||||
{
|
||||
stringKey = "\"" + stringKey + "\"";
|
||||
}
|
||||
|
||||
return stringKey;
|
||||
}
|
||||
|
||||
private static boolean hasPrimitiveValues(Map<?, ?> values, WriterContext context)
|
||||
{
|
||||
for (Object key : values.keySet())
|
||||
{
|
||||
Object fromValue = values.get(key);
|
||||
if (fromValue == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
dev.plex.toml.ValueWriter valueWriter = dev.plex.toml.ValueWriters.WRITERS.findWriterFor(fromValue);
|
||||
if (valueWriter.isPrimitiveType() || valueWriter == dev.plex.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private MapValueWriter()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class MultilineLiteralStringValueReader implements ValueReader {
|
||||
class MultilineLiteralStringValueReader implements ValueReader
|
||||
{
|
||||
|
||||
static final MultilineLiteralStringValueReader MULTILINE_LITERAL_STRING_VALUE_READER = new MultilineLiteralStringValueReader();
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class MultilineStringValueReader implements ValueReader {
|
||||
class MultilineStringValueReader implements ValueReader
|
||||
{
|
||||
|
||||
static final MultilineStringValueReader MULTILINE_STRING_VALUE_READER = new MultilineStringValueReader();
|
||||
|
||||
|
@ -12,7 +13,7 @@ class MultilineStringValueReader implements ValueReader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object read(String s, AtomicInteger index, Context context) {
|
||||
public Object read(String s, AtomicInteger index, dev.plex.toml.Context context) {
|
||||
AtomicInteger line = context.line;
|
||||
int startLine = line.get();
|
||||
int originalStartIndex = index.get();
|
||||
|
@ -37,15 +38,15 @@ class MultilineStringValueReader implements ValueReader {
|
|||
}
|
||||
|
||||
if (endIndex == -1) {
|
||||
Results.Errors errors = new Results.Errors();
|
||||
dev.plex.toml.Results.Errors errors = new dev.plex.toml.Results.Errors();
|
||||
errors.unterminated(context.identifier.getName(), s.substring(originalStartIndex), startLine);
|
||||
return errors;
|
||||
}
|
||||
|
||||
s = s.substring(startIndex, endIndex);
|
||||
s = s.replaceAll("\\\\\\s+", "");
|
||||
s = StringValueReaderWriter.STRING_VALUE_READER_WRITER.replaceUnicodeCharacters(s);
|
||||
s = StringValueReaderWriter.STRING_VALUE_READER_WRITER.replaceSpecialCharacters(s);
|
||||
s = dev.plex.toml.StringValueReaderWriter.STRING_VALUE_READER_WRITER.replaceUnicodeCharacters(s);
|
||||
s = dev.plex.toml.StringValueReaderWriter.STRING_VALUE_READER_WRITER.replaceSpecialCharacters(s);
|
||||
|
||||
return s;
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class NumberValueReaderWriter implements ValueReader, ValueWriter {
|
||||
class NumberValueReaderWriter implements dev.plex.toml.ValueReader, dev.plex.toml.ValueWriter
|
||||
{
|
||||
static final NumberValueReaderWriter NUMBER_VALUE_READER_WRITER = new NumberValueReaderWriter();
|
||||
|
||||
@Override
|
||||
|
@ -13,7 +14,7 @@ class NumberValueReaderWriter implements ValueReader, ValueWriter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object read(String s, AtomicInteger index, Context context) {
|
||||
public Object read(String s, AtomicInteger index, dev.plex.toml.Context context) {
|
||||
boolean signable = true;
|
||||
boolean dottable = false;
|
||||
boolean exponentable = false;
|
||||
|
@ -77,7 +78,7 @@ class NumberValueReaderWriter implements ValueReader, ValueWriter {
|
|||
|
||||
return Double.parseDouble(exponentString[0]) * Math.pow(10, Double.parseDouble(exponentString[1]));
|
||||
} else {
|
||||
Results.Errors errors = new Results.Errors();
|
||||
dev.plex.toml.Results.Errors errors = new dev.plex.toml.Results.Errors();
|
||||
errors.invalidValue(context.identifier.getName(), sb.toString(), context.line.get());
|
||||
return errors;
|
||||
}
|
||||
|
@ -89,7 +90,7 @@ class NumberValueReaderWriter implements ValueReader, ValueWriter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context) {
|
||||
public void write(Object value, dev.plex.toml.WriterContext context) {
|
||||
context.write(value.toString());
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
|
||||
class ObjectValueWriter implements ValueWriter
|
||||
{
|
||||
static final ValueWriter OBJECT_VALUE_WRITER = new ObjectValueWriter();
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Object value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Object value, WriterContext context)
|
||||
{
|
||||
Map<String, Object> to = new LinkedHashMap<String, Object>();
|
||||
Set<Field> fields = getFields(value.getClass());
|
||||
for (Field field : fields)
|
||||
{
|
||||
if (field.isAnnotationPresent(SerializedName.class))
|
||||
{
|
||||
to.put(field.getDeclaredAnnotation(SerializedName.class).value(), getFieldValue(field, value));
|
||||
} else {
|
||||
to.put(field.getName(), getFieldValue(field, value));
|
||||
}
|
||||
}
|
||||
|
||||
MapValueWriter.MAP_VALUE_WRITER.write(to, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimitiveType()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Set<Field> getFields(Class<?> cls)
|
||||
{
|
||||
Set<Field> fields = new LinkedHashSet<Field>(Arrays.asList(cls.getDeclaredFields()));
|
||||
while (cls != Object.class)
|
||||
{
|
||||
fields.addAll(Arrays.asList(cls.getDeclaredFields()));
|
||||
cls = cls.getSuperclass();
|
||||
}
|
||||
removeConstantsAndSyntheticFields(fields);
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
private static void removeConstantsAndSyntheticFields(Set<Field> fields)
|
||||
{
|
||||
Iterator<Field> iterator = fields.iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Field field = iterator.next();
|
||||
if ((Modifier.isFinal(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) || field.isSynthetic() || Modifier.isTransient(field.getModifiers()))
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getFieldValue(Field field, Object o)
|
||||
{
|
||||
boolean isAccessible = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
Object value = null;
|
||||
try
|
||||
{
|
||||
value = field.get(o);
|
||||
} catch (IllegalAccessException ignored)
|
||||
{
|
||||
}
|
||||
field.setAccessible(isAccessible);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private ObjectValueWriter()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.ValueWriters.WRITERS;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class PrimitiveArrayValueWriter extends ArrayValueWriter {
|
||||
class PrimitiveArrayValueWriter extends ArrayValueWriter
|
||||
{
|
||||
static final ValueWriter PRIMITIVE_ARRAY_VALUE_WRITER = new PrimitiveArrayValueWriter();
|
||||
|
||||
@Override
|
||||
|
@ -24,10 +23,10 @@ class PrimitiveArrayValueWriter extends ArrayValueWriter {
|
|||
|
||||
for (Object value : values) {
|
||||
if (first) {
|
||||
firstWriter = WRITERS.findWriterFor(value);
|
||||
firstWriter = ValueWriters.WRITERS.findWriterFor(value);
|
||||
first = false;
|
||||
} else {
|
||||
ValueWriter writer = WRITERS.findWriterFor(value);
|
||||
ValueWriter writer = ValueWriters.WRITERS.findWriterFor(value);
|
||||
if (writer != firstWriter) {
|
||||
throw new IllegalStateException(
|
||||
context.getContextPath() +
|
||||
|
@ -38,7 +37,7 @@ class PrimitiveArrayValueWriter extends ArrayValueWriter {
|
|||
context.write(", ");
|
||||
}
|
||||
|
||||
WRITERS.findWriterFor(value).write(value, context);
|
||||
ValueWriters.WRITERS.findWriterFor(value).write(value, context);
|
||||
}
|
||||
|
||||
context.writeArrayDelimiterPadding();
|
|
@ -1,11 +1,6 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class Results {
|
||||
|
@ -60,7 +55,7 @@ class Results {
|
|||
.append(key);
|
||||
}
|
||||
|
||||
void invalidTextAfterIdentifier(Identifier identifier, char text, int line) {
|
||||
void invalidTextAfterIdentifier(dev.plex.toml.Identifier identifier, char text, int line) {
|
||||
sb.append("Invalid text after key ")
|
||||
.append(identifier.getName())
|
||||
.append(" on line ")
|
||||
|
@ -143,9 +138,9 @@ class Results {
|
|||
if (path == null) {
|
||||
startTable(key, line);
|
||||
} else if (path.isEmpty()) {
|
||||
startTables(Identifier.from(key, null), line);
|
||||
startTables(dev.plex.toml.Identifier.from(key, null), line);
|
||||
} else {
|
||||
startTables(Identifier.from(path, null), line);
|
||||
startTables(dev.plex.toml.Identifier.from(path, null), line);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> valueMap = (Map<String, Object>) value;
|
||||
|
@ -164,13 +159,13 @@ class Results {
|
|||
}
|
||||
}
|
||||
|
||||
void startTableArray(Identifier identifier, AtomicInteger line) {
|
||||
void startTableArray(dev.plex.toml.Identifier identifier, AtomicInteger line) {
|
||||
String tableName = identifier.getBareName();
|
||||
while (stack.size() > 1) {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
Keys.Key[] tableParts = Keys.split(tableName);
|
||||
dev.plex.toml.Keys.Key[] tableParts = dev.plex.toml.Keys.split(tableName);
|
||||
for (int i = 0; i < tableParts.length; i++) {
|
||||
String tablePart = tableParts[i].name;
|
||||
Container currentContainer = stack.peek();
|
||||
|
@ -203,14 +198,14 @@ class Results {
|
|||
}
|
||||
}
|
||||
|
||||
void startTables(Identifier id, AtomicInteger line) {
|
||||
void startTables(dev.plex.toml.Identifier id, AtomicInteger line) {
|
||||
String tableName = id.getBareName();
|
||||
|
||||
while (stack.size() > 1) {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
Keys.Key[] tableParts = Keys.split(tableName);
|
||||
dev.plex.toml.Keys.Key[] tableParts = dev.plex.toml.Keys.split(tableName);
|
||||
for (int i = 0; i < tableParts.length; i++) {
|
||||
String tablePart = tableParts[i].name;
|
||||
Container currentContainer = stack.peek();
|
|
@ -1,4 +1,4 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
@ -6,7 +6,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class StringValueReaderWriter implements ValueReader, ValueWriter {
|
||||
class StringValueReaderWriter implements ValueReader, ValueWriter
|
||||
{
|
||||
|
||||
static final StringValueReaderWriter STRING_VALUE_READER_WRITER = new StringValueReaderWriter();
|
||||
private static final Pattern UNICODE_REGEX = Pattern.compile("\\\\[uU](.{4})");
|
|
@ -1,10 +1,11 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.ValueWriters.WRITERS;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
class TableArrayValueWriter extends ArrayValueWriter {
|
||||
import static dev.plex.toml.ValueWriters.WRITERS;
|
||||
|
||||
class TableArrayValueWriter extends ArrayValueWriter
|
||||
{
|
||||
static final ValueWriter TABLE_ARRAY_VALUE_WRITER = new TableArrayValueWriter();
|
||||
|
||||
@Override
|
|
@ -0,0 +1,481 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>Provides access to the keys and tables in a TOML data source.</p>
|
||||
*
|
||||
* <p>All getters can fall back to default values if they have been provided as a constructor argument.
|
||||
* Getters for simple values (String, Date, etc.) will return null if no matching key exists.
|
||||
* {@link #getList(String)}, {@link #getTable(String)} and {@link #getTables(String)} return empty values if there is no matching key.</p>
|
||||
*
|
||||
* <p>All read methods throw an {@link IllegalStateException} if the TOML is incorrect.</p>
|
||||
*
|
||||
* <p>Example usage:</p>
|
||||
* <pre><code>
|
||||
* Toml toml = new Toml().read(getTomlFile());
|
||||
* String name = toml.getString("name");
|
||||
* Long port = toml.getLong("server.ip"); // compound key. Is equivalent to:
|
||||
* Long port2 = toml.getTable("server").getLong("ip");
|
||||
* MyConfig config = toml.to(MyConfig.class);
|
||||
* </code></pre>
|
||||
*/
|
||||
public class Toml
|
||||
{
|
||||
|
||||
private static final Gson DEFAULT_GSON = new Gson();
|
||||
|
||||
@Getter
|
||||
private Map<String, Object> values = new HashMap<String, Object>();
|
||||
private final Toml defaults;
|
||||
|
||||
/**
|
||||
* Creates Toml instance with no defaults.
|
||||
*/
|
||||
public Toml()
|
||||
{
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param defaults fallback values used when the requested key or table is not present in the TOML source that has been read.
|
||||
*/
|
||||
public Toml(Toml defaults)
|
||||
{
|
||||
this(defaults, new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from file.
|
||||
*
|
||||
* @param file The File to be read. Expected to be encoded as UTF-8.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If file contains invalid TOML
|
||||
*/
|
||||
public Toml read(File file)
|
||||
{
|
||||
try
|
||||
{
|
||||
return read(new InputStreamReader(new FileInputStream(file), "UTF8"));
|
||||
} catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from inputStream.
|
||||
*
|
||||
* @param inputStream Closed after it has been read.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If file contains invalid TOML
|
||||
*/
|
||||
public Toml read(InputStream inputStream)
|
||||
{
|
||||
return read(new InputStreamReader(inputStream));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from reader.
|
||||
*
|
||||
* @param reader Closed after it has been read.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If file contains invalid TOML
|
||||
*/
|
||||
public Toml read(Reader reader)
|
||||
{
|
||||
BufferedReader bufferedReader = null;
|
||||
try
|
||||
{
|
||||
bufferedReader = new BufferedReader(reader);
|
||||
|
||||
StringBuilder w = new StringBuilder();
|
||||
String line = bufferedReader.readLine();
|
||||
while (line != null)
|
||||
{
|
||||
w.append(line).append('\n');
|
||||
line = bufferedReader.readLine();
|
||||
}
|
||||
read(w.toString());
|
||||
} catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
} finally
|
||||
{
|
||||
try
|
||||
{
|
||||
bufferedReader.close();
|
||||
} catch (IOException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from otherToml.
|
||||
*
|
||||
* @param otherToml
|
||||
* @return this instance
|
||||
*/
|
||||
public Toml read(Toml otherToml)
|
||||
{
|
||||
this.values = otherToml.values;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current Toml instance with values from tomlString.
|
||||
*
|
||||
* @param tomlString String to be read.
|
||||
* @return this instance
|
||||
* @throws IllegalStateException If tomlString is not valid TOML
|
||||
*/
|
||||
public Toml read(String tomlString) throws IllegalStateException
|
||||
{
|
||||
dev.plex.toml.Results results = dev.plex.toml.TomlParser.run(tomlString);
|
||||
if (results.errors.hasErrors())
|
||||
{
|
||||
throw new IllegalStateException(results.errors.toString());
|
||||
}
|
||||
|
||||
this.values = results.consume();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getString(String key)
|
||||
{
|
||||
return (String) get(key);
|
||||
}
|
||||
|
||||
public String getString(String key, String defaultValue)
|
||||
{
|
||||
String val = getString(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
public Long getLong(String key)
|
||||
{
|
||||
return (Long) get(key);
|
||||
}
|
||||
|
||||
public Long getLong(String key, Long defaultValue)
|
||||
{
|
||||
Long val = getLong(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a TOML key
|
||||
* @param <T> type of list items
|
||||
* @return <code>null</code> if the key is not found
|
||||
*/
|
||||
public <T> List<T> getList(String key)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> list = (List<T>) get(key);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a TOML key
|
||||
* @param defaultValue a list of default values
|
||||
* @param <T> type of list items
|
||||
* @return <code>null</code> is the key is not found
|
||||
*/
|
||||
public <T> List<T> getList(String key, List<T> defaultValue)
|
||||
{
|
||||
List<T> list = getList(key);
|
||||
|
||||
return list != null ? list : defaultValue;
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String key)
|
||||
{
|
||||
return (Boolean) get(key);
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String key, Boolean defaultValue)
|
||||
{
|
||||
Boolean val = getBoolean(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
public Date getDate(String key)
|
||||
{
|
||||
return (Date) get(key);
|
||||
}
|
||||
|
||||
public Date getDate(String key, Date defaultValue)
|
||||
{
|
||||
Date val = getDate(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
public Double getDouble(String key)
|
||||
{
|
||||
return (Double) get(key);
|
||||
}
|
||||
|
||||
public Double getDouble(String key, Double defaultValue)
|
||||
{
|
||||
Double val = getDouble(key);
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key A table name, not including square brackets.
|
||||
* @return A new Toml instance or <code>null</code> if no value is found for key.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Toml getTable(String key)
|
||||
{
|
||||
Map<String, Object> map = (Map<String, Object>) get(key);
|
||||
|
||||
return map != null ? new Toml(null, map) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key Name of array of tables, not including square brackets.
|
||||
* @return A {@link List} of Toml instances or <code>null</code> if no value is found for key.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Toml> getTables(String key)
|
||||
{
|
||||
List<Map<String, Object>> tableArray = (List<Map<String, Object>>) get(key);
|
||||
|
||||
if (tableArray == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<Toml> tables = new ArrayList<Toml>();
|
||||
|
||||
for (Map<String, Object> table : tableArray)
|
||||
{
|
||||
tables.add(new Toml(null, table));
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present
|
||||
*/
|
||||
public boolean contains(String key)
|
||||
{
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present and is a primitive
|
||||
*/
|
||||
public boolean containsPrimitive(String key)
|
||||
{
|
||||
Object object = get(key);
|
||||
|
||||
return object != null && !(object instanceof Map) && !(object instanceof List);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present and is a table
|
||||
*/
|
||||
public boolean containsTable(String key)
|
||||
{
|
||||
Object object = get(key);
|
||||
|
||||
return object != null && (object instanceof Map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a key name, can be compound (eg. a.b.c)
|
||||
* @return true if key is present and is a table array
|
||||
*/
|
||||
public boolean containsTableArray(String key)
|
||||
{
|
||||
Object object = get(key);
|
||||
|
||||
return object != null && (object instanceof List);
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return values.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Populates an instance of targetClass with the values of this Toml instance.
|
||||
* The target's field names must match keys or tables.
|
||||
* Keys not present in targetClass will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* <p>Tables are recursively converted to custom classes or to {@link Map Map<String, Object>}.</p>
|
||||
*
|
||||
* <p>In addition to straight-forward conversion of TOML primitives, the following are also available:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>Integer -> int, long (or wrapper), {@link java.math.BigInteger}</li>
|
||||
* <li>Float -> float, double (or wrapper), {@link java.math.BigDecimal}</li>
|
||||
* <li>One-letter String -> char, {@link Character}</li>
|
||||
* <li>String -> {@link String}, enum, {@link java.net.URI}, {@link java.net.URL}</li>
|
||||
* <li>Multiline and Literal Strings -> {@link String}</li>
|
||||
* <li>Array -> {@link List}, {@link Set}, array. The generic type can be anything that can be converted.</li>
|
||||
* <li>Table -> Custom class, {@link Map Map<String, Object>}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param targetClass Class to deserialize TOML to.
|
||||
* @param <T> type of targetClass.
|
||||
* @return A new instance of targetClass.
|
||||
*/
|
||||
public <T> T to(Class<T> targetClass)
|
||||
{
|
||||
JsonElement json = DEFAULT_GSON.toJsonTree(toMap());
|
||||
|
||||
if (targetClass == JsonElement.class)
|
||||
{
|
||||
return targetClass.cast(json);
|
||||
}
|
||||
|
||||
return DEFAULT_GSON.fromJson(json, targetClass);
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap()
|
||||
{
|
||||
HashMap<String, Object> valuesCopy = new HashMap<String, Object>(values);
|
||||
|
||||
if (defaults != null)
|
||||
{
|
||||
for (Map.Entry<String, Object> entry : defaults.values.entrySet())
|
||||
{
|
||||
if (!valuesCopy.containsKey(entry.getKey()))
|
||||
{
|
||||
valuesCopy.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return valuesCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a {@link Set} of Map.Entry instances. Modifications to the {@link Set} are not reflected in this Toml instance. Entries are immutable, so {@link Map.Entry#setValue(Object)} throws an UnsupportedOperationException.
|
||||
*/
|
||||
public Set<Map.Entry<String, Object>> entrySet()
|
||||
{
|
||||
Set<Map.Entry<String, Object>> entries = new LinkedHashSet<Map.Entry<String, Object>>();
|
||||
|
||||
for (Map.Entry<String, Object> entry : values.entrySet())
|
||||
{
|
||||
Class<? extends Object> entryClass = entry.getValue().getClass();
|
||||
|
||||
if (Map.class.isAssignableFrom(entryClass))
|
||||
{
|
||||
entries.add(new Entry(entry.getKey(), getTable(entry.getKey())));
|
||||
} else if (List.class.isAssignableFrom(entryClass))
|
||||
{
|
||||
List<?> value = (List<?>) entry.getValue();
|
||||
if (!value.isEmpty() && value.get(0) instanceof Map)
|
||||
{
|
||||
entries.add(new Entry(entry.getKey(), getTables(entry.getKey())));
|
||||
} else
|
||||
{
|
||||
entries.add(new Entry(entry.getKey(), value));
|
||||
}
|
||||
} else
|
||||
{
|
||||
entries.add(new Entry(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
private class Entry implements Map.Entry<String, Object>
|
||||
{
|
||||
|
||||
private final String key;
|
||||
private final Object value;
|
||||
|
||||
@Override
|
||||
public String getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(Object value)
|
||||
{
|
||||
throw new UnsupportedOperationException("TOML entry values cannot be changed.");
|
||||
}
|
||||
|
||||
private Entry(String key, Object value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object get(String key)
|
||||
{
|
||||
if (values.containsKey(key))
|
||||
{
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
Object current = new HashMap<>(values);
|
||||
|
||||
dev.plex.toml.Keys.Key[] keys = dev.plex.toml.Keys.split(key);
|
||||
|
||||
for (dev.plex.toml.Keys.Key k : keys)
|
||||
{
|
||||
if (k.index == -1 && current instanceof Map && ((Map<String, Object>) current).containsKey(k.path))
|
||||
{
|
||||
return ((Map<String, Object>) current).get(k.path);
|
||||
}
|
||||
|
||||
current = ((Map<String, Object>) current).get(k.name);
|
||||
|
||||
if (k.index > -1 && current != null)
|
||||
{
|
||||
if (k.index >= ((List<?>) current).size())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
current = ((List<?>) current).get(k.index);
|
||||
}
|
||||
|
||||
if (current == null)
|
||||
{
|
||||
return defaults != null ? defaults.get(key) : null;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
private Toml(Toml defaults, Map<String, Object> values)
|
||||
{
|
||||
this.values = values;
|
||||
this.defaults = defaults;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static com.moandjiezana.toml.IdentifierConverter.IDENTIFIER_CONVERTER;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class TomlParser {
|
||||
|
||||
static Results run(String tomlString) {
|
||||
final Results results = new Results();
|
||||
static dev.plex.toml.Results run(String tomlString) {
|
||||
final dev.plex.toml.Results results = new dev.plex.toml.Results();
|
||||
|
||||
if (tomlString.isEmpty()) {
|
||||
return results;
|
||||
|
@ -16,7 +14,7 @@ class TomlParser {
|
|||
AtomicInteger index = new AtomicInteger();
|
||||
boolean inComment = false;
|
||||
AtomicInteger line = new AtomicInteger(1);
|
||||
Identifier identifier = null;
|
||||
dev.plex.toml.Identifier identifier = null;
|
||||
Object value = null;
|
||||
|
||||
for (int i = index.get(); i < tomlString.length(); i = index.incrementAndGet()) {
|
||||
|
@ -29,9 +27,9 @@ class TomlParser {
|
|||
if (c == '#' && !inComment) {
|
||||
inComment = true;
|
||||
} else if (!Character.isWhitespace(c) && !inComment && identifier == null) {
|
||||
Identifier id = IDENTIFIER_CONVERTER.convert(tomlString, index, new Context(null, line, results.errors));
|
||||
dev.plex.toml.Identifier id = dev.plex.toml.IdentifierConverter.IDENTIFIER_CONVERTER.convert(tomlString, index, new dev.plex.toml.Context(null, line, results.errors));
|
||||
|
||||
if (id != Identifier.INVALID) {
|
||||
if (id != dev.plex.toml.Identifier.INVALID) {
|
||||
if (id.isKey()) {
|
||||
identifier = id;
|
||||
} else if (id.isTable()) {
|
||||
|
@ -46,10 +44,10 @@ class TomlParser {
|
|||
value = null;
|
||||
line.incrementAndGet();
|
||||
} else if (!inComment && identifier != null && identifier.isKey() && value == null && !Character.isWhitespace(c)) {
|
||||
value = ValueReaders.VALUE_READERS.convert(tomlString, index, new Context(identifier, line, results.errors));
|
||||
value = ValueReaders.VALUE_READERS.convert(tomlString, index, new dev.plex.toml.Context(identifier, line, results.errors));
|
||||
|
||||
if (value instanceof Results.Errors) {
|
||||
results.errors.add((Results.Errors) value);
|
||||
if (value instanceof dev.plex.toml.Results.Errors) {
|
||||
results.errors.add((dev.plex.toml.Results.Errors) value);
|
||||
} else {
|
||||
results.addValue(identifier.getName(), value, line);
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static dev.plex.toml.ValueWriters.WRITERS;
|
||||
|
||||
/**
|
||||
* <p>Converts Objects to TOML</p>
|
||||
*
|
||||
* <p>An input Object can comprise arbitrarily nested combinations of Java primitive types,
|
||||
* other {@link Object}s, {@link Map}s, {@link List}s, and Arrays. {@link Object}s and {@link Map}s
|
||||
* are output to TOML tables, and {@link List}s and Array to TOML arrays.</p>
|
||||
*
|
||||
* <p>Example usage:</p>
|
||||
* <pre><code>
|
||||
* class AClass {
|
||||
* int anInt = 1;
|
||||
* int[] anArray = { 2, 3 };
|
||||
* }
|
||||
*
|
||||
* String tomlString = new TomlWriter().write(new AClass());
|
||||
* </code></pre>
|
||||
*/
|
||||
public class TomlWriter
|
||||
{
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
private int keyIndentation;
|
||||
private int tableIndentation;
|
||||
private int arrayDelimiterPadding = 0;
|
||||
private TimeZone timeZone = TimeZone.getTimeZone("UTC");
|
||||
private boolean showFractionalSeconds = false;
|
||||
|
||||
public Builder indentValuesBy(int spaces)
|
||||
{
|
||||
this.keyIndentation = spaces;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder indentTablesBy(int spaces)
|
||||
{
|
||||
this.tableIndentation = spaces;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder timeZone(TimeZone timeZone)
|
||||
{
|
||||
this.timeZone = timeZone;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param spaces number of spaces to put between opening square bracket and first item and between closing square bracket and last item
|
||||
* @return this TomlWriter.Builder instance
|
||||
*/
|
||||
public Builder padArrayDelimitersBy(int spaces)
|
||||
{
|
||||
this.arrayDelimiterPadding = spaces;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public TomlWriter build()
|
||||
{
|
||||
return new TomlWriter(keyIndentation, tableIndentation, arrayDelimiterPadding, timeZone, showFractionalSeconds);
|
||||
}
|
||||
|
||||
public Builder showFractionalSeconds()
|
||||
{
|
||||
this.showFractionalSeconds = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private final IndentationPolicy indentationPolicy;
|
||||
private final dev.plex.toml.DatePolicy datePolicy;
|
||||
|
||||
/**
|
||||
* Creates a TomlWriter instance.
|
||||
*/
|
||||
public TomlWriter()
|
||||
{
|
||||
this(0, 0, 0, TimeZone.getTimeZone("UTC"), false);
|
||||
}
|
||||
|
||||
private TomlWriter(int keyIndentation, int tableIndentation, int arrayDelimiterPadding, TimeZone timeZone, boolean showFractionalSeconds)
|
||||
{
|
||||
this.indentationPolicy = new IndentationPolicy(keyIndentation, tableIndentation, arrayDelimiterPadding);
|
||||
this.datePolicy = new dev.plex.toml.DatePolicy(timeZone, showFractionalSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object into TOML String.
|
||||
*
|
||||
* @param from the object to be written
|
||||
* @return a string containing the TOML representation of the given Object
|
||||
*/
|
||||
public String write(Object from)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringWriter output = new StringWriter();
|
||||
write(from, output, null);
|
||||
|
||||
return output.toString();
|
||||
} catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object in TOML to a {@link File}. Output is encoded as UTF-8.
|
||||
*
|
||||
* @param from the object to be written
|
||||
* @param target the File to which the TOML will be written
|
||||
* @throws IOException if any file operations fail
|
||||
*/
|
||||
public void write(Object from, File target) throws IOException
|
||||
{
|
||||
OutputStream outputStream = new FileOutputStream(target, true);
|
||||
try
|
||||
{
|
||||
write(from, outputStream, target);
|
||||
} finally
|
||||
{
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object in TOML to a {@link OutputStream}. Output is encoded as UTF-8.
|
||||
*
|
||||
* @param from the object to be written
|
||||
* @param target the OutputStream to which the TOML will be written. The stream is NOT closed after being written to.
|
||||
* @throws IOException if target.write() fails
|
||||
*/
|
||||
public void write(Object from, OutputStream target, @Nullable File file) throws IOException
|
||||
{
|
||||
OutputStreamWriter writer = new OutputStreamWriter(target, "UTF-8");
|
||||
write(from, writer, file);
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an Object in TOML to a {@link Writer}. You MUST ensure that the {@link Writer}s's encoding is set to UTF-8 for the TOML to be valid.
|
||||
*
|
||||
* @param from the object to be written. Can be a Map or a custom type. Must not be null.
|
||||
* @param target the Writer to which TOML will be written. The Writer is not closed.
|
||||
* @throws IOException if target.write() fails
|
||||
* @throws IllegalArgumentException if from is of an invalid type
|
||||
*/
|
||||
public void write(Object from, Writer target, @Nullable File file) throws IOException
|
||||
{
|
||||
dev.plex.toml.ValueWriter valueWriter = WRITERS.findWriterFor(from);
|
||||
if (valueWriter == MapValueWriter.MAP_VALUE_WRITER || valueWriter == dev.plex.toml.ObjectValueWriter.OBJECT_VALUE_WRITER)
|
||||
{
|
||||
WriterContext context = new WriterContext(indentationPolicy, datePolicy, target);
|
||||
if (file != null && file.exists())
|
||||
{
|
||||
context.file = file;
|
||||
}
|
||||
valueWriter.write(from, context);
|
||||
} else
|
||||
{
|
||||
throw new IllegalArgumentException("An object of class " + from.getClass().getSimpleName() + " cannot produce valid TOML. Please pass in a Map or a custom type.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -15,7 +15,7 @@ interface ValueReader {
|
|||
* @param s must already have been validated by {@link #canRead(String)}
|
||||
* @param index where to start in s
|
||||
* @param line current line number, used for error reporting
|
||||
* @return a value or a {@link Results.Errors}
|
||||
* @return a value or a {@link dev.plex.toml.Results.Errors}
|
||||
*/
|
||||
Object read(String s, AtomicInteger index, Context context);
|
||||
Object read(String s, AtomicInteger index, dev.plex.toml.Context context);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static dev.plex.toml.ArrayValueReader.ARRAY_VALUE_READER;
|
||||
import static dev.plex.toml.BooleanValueReaderWriter.BOOLEAN_VALUE_READER_WRITER;
|
||||
import static dev.plex.toml.DateValueReaderWriter.DATE_VALUE_READER_WRITER;
|
||||
import static dev.plex.toml.LiteralStringValueReader.LITERAL_STRING_VALUE_READER;
|
||||
import static dev.plex.toml.MultilineLiteralStringValueReader.MULTILINE_LITERAL_STRING_VALUE_READER;
|
||||
import static dev.plex.toml.MultilineStringValueReader.MULTILINE_STRING_VALUE_READER;
|
||||
import static dev.plex.toml.StringValueReaderWriter.STRING_VALUE_READER_WRITER;
|
||||
|
||||
class ValueReaders {
|
||||
|
||||
static final ValueReaders VALUE_READERS = new ValueReaders();
|
||||
|
||||
Object convert(String value, AtomicInteger index, dev.plex.toml.Context context) {
|
||||
String substring = value.substring(index.get());
|
||||
for (dev.plex.toml.ValueReader valueParser : READERS) {
|
||||
if (valueParser.canRead(substring)) {
|
||||
return valueParser.read(value, index, context);
|
||||
}
|
||||
}
|
||||
|
||||
dev.plex.toml.Results.Errors errors = new dev.plex.toml.Results.Errors();
|
||||
errors.invalidValue(context.identifier.getName(), substring, context.line.get());
|
||||
return errors;
|
||||
}
|
||||
|
||||
private ValueReaders() {}
|
||||
|
||||
private static final dev.plex.toml.ValueReader[] READERS = {
|
||||
MULTILINE_STRING_VALUE_READER, MULTILINE_LITERAL_STRING_VALUE_READER, LITERAL_STRING_VALUE_READER, STRING_VALUE_READER_WRITER, DATE_VALUE_READER_WRITER, NumberValueReaderWriter.NUMBER_VALUE_READER_WRITER, BOOLEAN_VALUE_READER_WRITER, ARRAY_VALUE_READER, InlineTableValueReader.INLINE_TABLE_VALUE_READER
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.moandjiezana.toml;
|
||||
package dev.plex.toml;
|
||||
|
||||
interface ValueWriter {
|
||||
boolean canWrite(Object value);
|
|
@ -0,0 +1,28 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
class ValueWriters {
|
||||
|
||||
static final ValueWriters WRITERS = new ValueWriters();
|
||||
|
||||
ValueWriter findWriterFor(Object value) {
|
||||
for (ValueWriter valueWriter : VALUE_WRITERS) {
|
||||
if (valueWriter.canWrite(value)) {
|
||||
return valueWriter;
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectValueWriter.OBJECT_VALUE_WRITER;
|
||||
}
|
||||
|
||||
private ValueWriters() {}
|
||||
|
||||
private static dev.plex.toml.DateValueReaderWriter getPlatformSpecificDateConverter() {
|
||||
String specificationVersion = Runtime.class.getPackage().getSpecificationVersion();
|
||||
return specificationVersion != null && specificationVersion.startsWith("1.6") ? dev.plex.toml.DateValueReaderWriter.DATE_PARSER_JDK_6 : dev.plex.toml.DateValueReaderWriter.DATE_VALUE_READER_WRITER;
|
||||
}
|
||||
|
||||
private static final ValueWriter[] VALUE_WRITERS = {
|
||||
StringValueReaderWriter.STRING_VALUE_READER_WRITER, NumberValueReaderWriter.NUMBER_VALUE_READER_WRITER, dev.plex.toml.BooleanValueReaderWriter.BOOLEAN_VALUE_READER_WRITER, getPlatformSpecificDateConverter(),
|
||||
MapValueWriter.MAP_VALUE_WRITER, dev.plex.toml.PrimitiveArrayValueWriter.PRIMITIVE_ARRAY_VALUE_WRITER, TableArrayValueWriter.TABLE_ARRAY_VALUE_WRITER
|
||||
};
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
package dev.plex.toml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
|
||||
class WriterContext
|
||||
{
|
||||
private String arrayKey = null;
|
||||
private boolean isArrayOfTable = false;
|
||||
private boolean empty = true;
|
||||
public final String key;
|
||||
private final String currentTableIndent;
|
||||
private final String currentFieldIndent;
|
||||
private final Writer output;
|
||||
private final dev.plex.toml.IndentationPolicy indentationPolicy;
|
||||
private final dev.plex.toml.DatePolicy datePolicy;
|
||||
|
||||
public File file;
|
||||
public String parentName;
|
||||
public boolean hasRun = false;
|
||||
|
||||
WriterContext(dev.plex.toml.IndentationPolicy indentationPolicy, dev.plex.toml.DatePolicy datePolicy, Writer output)
|
||||
{
|
||||
this("", "", output, indentationPolicy, datePolicy);
|
||||
}
|
||||
|
||||
WriterContext pushTable(String newKey)
|
||||
{
|
||||
String newIndent = "";
|
||||
if (!key.isEmpty())
|
||||
{
|
||||
newIndent = growIndent(indentationPolicy);
|
||||
}
|
||||
|
||||
String fullKey = key.isEmpty() ? newKey : key + "." + newKey;
|
||||
|
||||
WriterContext subContext = new WriterContext(fullKey, newIndent, output, indentationPolicy, datePolicy);
|
||||
if (!empty)
|
||||
{
|
||||
subContext.empty = false;
|
||||
}
|
||||
|
||||
return subContext;
|
||||
}
|
||||
|
||||
WriterContext pushTableFromArray()
|
||||
{
|
||||
WriterContext subContext = new WriterContext(key, currentTableIndent, output, indentationPolicy, datePolicy);
|
||||
if (!empty)
|
||||
{
|
||||
subContext.empty = false;
|
||||
}
|
||||
subContext.setIsArrayOfTable(true);
|
||||
|
||||
return subContext;
|
||||
}
|
||||
|
||||
WriterContext write(String s)
|
||||
{
|
||||
try
|
||||
{
|
||||
output.write(s);
|
||||
if (empty && !s.isEmpty())
|
||||
{
|
||||
empty = false;
|
||||
}
|
||||
|
||||
return this;
|
||||
} catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
void write(char[] chars)
|
||||
{
|
||||
for (char c : chars)
|
||||
{
|
||||
write(c);
|
||||
}
|
||||
}
|
||||
|
||||
WriterContext write(char c)
|
||||
{
|
||||
try
|
||||
{
|
||||
output.write(c);
|
||||
empty = false;
|
||||
|
||||
return this;
|
||||
} catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
void writeKey()
|
||||
{
|
||||
if (key.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty)
|
||||
{
|
||||
write('\n');
|
||||
}
|
||||
|
||||
write(currentTableIndent);
|
||||
|
||||
if (isArrayOfTable)
|
||||
{
|
||||
write("[[").write(key).write("]]\n");
|
||||
} else
|
||||
{
|
||||
write('[').write(key).write("]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void writeArrayDelimiterPadding()
|
||||
{
|
||||
for (int i = 0; i < indentationPolicy.getArrayDelimiterPadding(); i++)
|
||||
{
|
||||
write(' ');
|
||||
}
|
||||
}
|
||||
|
||||
void indent()
|
||||
{
|
||||
if (!key.isEmpty())
|
||||
{
|
||||
write(currentFieldIndent);
|
||||
}
|
||||
}
|
||||
|
||||
dev.plex.toml.DatePolicy getDatePolicy()
|
||||
{
|
||||
return datePolicy;
|
||||
}
|
||||
|
||||
WriterContext setIsArrayOfTable(boolean isArrayOfTable)
|
||||
{
|
||||
this.isArrayOfTable = isArrayOfTable;
|
||||
return this;
|
||||
}
|
||||
|
||||
WriterContext setArrayKey(String arrayKey)
|
||||
{
|
||||
this.arrayKey = arrayKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
String getContextPath()
|
||||
{
|
||||
return key.isEmpty() ? arrayKey : key + "." + arrayKey;
|
||||
}
|
||||
|
||||
private String growIndent(dev.plex.toml.IndentationPolicy indentationPolicy)
|
||||
{
|
||||
return currentTableIndent + fillStringWithSpaces(indentationPolicy.getTableIndent());
|
||||
}
|
||||
|
||||
private String fillStringWithSpaces(int count)
|
||||
{
|
||||
char[] chars = new char[count];
|
||||
Arrays.fill(chars, ' ');
|
||||
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
private WriterContext(String key, String tableIndent, Writer output, dev.plex.toml.IndentationPolicy indentationPolicy, dev.plex.toml.DatePolicy datePolicy)
|
||||
{
|
||||
this.key = key;
|
||||
this.output = output;
|
||||
this.indentationPolicy = indentationPolicy;
|
||||
this.currentTableIndent = tableIndent;
|
||||
this.datePolicy = datePolicy;
|
||||
this.currentFieldIndent = tableIndent + fillStringWithSpaces(this.indentationPolicy.getKeyValueIndent());
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.moandjiezana.toml.testutils.Utils;
|
||||
|
||||
public class ArrayTest {
|
||||
|
||||
@Test
|
||||
public void should_get_array() throws Exception {
|
||||
Toml toml = new Toml().read("list = [\"a\", \"b\", \"c\"]");
|
||||
|
||||
assertEquals(asList("a", "b", "c"), toml.<String>getList("list"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_if_no_value_for_key() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
|
||||
assertNull(toml.getList("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_allow_multiline_array() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_allow_multiline_array"));
|
||||
|
||||
assertEquals(asList("a", "b", "c"), toml.<String>getList("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_get_nested_arrays() throws Exception {
|
||||
Toml clients = new Toml().read("data = [ [\"gamma\", \"delta\"], [1, 2]] # just an update to make sure parsers support it");
|
||||
|
||||
assertEquals(asList(asList("gamma", "delta"), asList(1L, 2L)), clients.<String>getList("data"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_deeply_nested_arrays() throws Exception {
|
||||
List<List<?>> data = new Toml().read("data = [[[1], [2]], [3, 4]]").getList("data");
|
||||
|
||||
assertThat(data, hasSize(2));
|
||||
assertEquals(Arrays.asList(1L), data.get(0).get(0));
|
||||
assertEquals(asList(2L), data.get(0).get(1));
|
||||
assertEquals(asList(3L, 4L), data.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_get_nested_arrays_with_no_space_between_outer_and_inner_array() throws Exception {
|
||||
Toml clients = new Toml().read("data = [[\"gamma\", \"delta\"], [1, 2]] # just an update to make sure parsers support it");
|
||||
|
||||
assertEquals(asList(asList("gamma", "delta"), asList(1L, 2L)), clients.<String>getList("data"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_ignore_comma_at_end_of_array() throws Exception {
|
||||
Toml toml = new Toml().read("key=[1,2,3,]");
|
||||
|
||||
assertEquals(asList(1L, 2L, 3L), toml.<Long>getList("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_mixed_string_types() throws Exception {
|
||||
Toml toml = new Toml().read("key = [\"a\", 'b', \"\"\"c\"\"\", '''d''']");
|
||||
|
||||
assertThat(toml.<String>getList("key"), contains("a", "b", "c", "d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_array_terminator_in_strings() throws Exception {
|
||||
Toml toml = new Toml().read("key = [\"a]\", 'b]', \"\"\"c]\"\"\", '''d]''']");
|
||||
|
||||
assertThat(toml.<String>getList("key"), contains("a]", "b]", "c]", "d]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_array_of_inline_tables() throws Exception {
|
||||
Toml toml = new Toml().read(getClass().getResourceAsStream("should_support_array_of_inline_tables.toml"));
|
||||
|
||||
assertThat(toml.getList("points"), hasSize(4));
|
||||
assertEquals(1, toml.getLong("points[0].x").longValue());
|
||||
assertEquals(2, toml.getLong("points[0].y").longValue());
|
||||
assertEquals(3, toml.getLong("points[0].z").longValue());
|
||||
assertEquals(7, toml.getLong("points[1].x").longValue());
|
||||
assertEquals(8, toml.getLong("points[1].y").longValue());
|
||||
assertEquals(9, toml.getLong("points[1].z").longValue());
|
||||
assertEquals(2, toml.getLong("points[2].x").longValue());
|
||||
assertEquals(4, toml.getLong("points[2].y").longValue());
|
||||
assertEquals(8, toml.getLong("points[2].z").longValue());
|
||||
assertEquals("3", toml.getString("points[3].x"));
|
||||
assertEquals("6", toml.getString("points[3].y"));
|
||||
assertEquals("12", toml.getString("points[3].z"));
|
||||
}
|
||||
|
||||
private File file(String file) {
|
||||
return Utils.file(getClass(), file);
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BareKeysTest {
|
||||
|
||||
@Test
|
||||
public void should_ignore_spaces_around_key_segments() throws Exception {
|
||||
Toml toml = new Toml().read("[ a . b . c ] \n key = \"a\"");
|
||||
|
||||
assertEquals("a", toml.getString("a.b.c.key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_underscores_in_key_names() throws Exception {
|
||||
Toml toml = new Toml().read("a_a = 1");
|
||||
|
||||
assertEquals(1, toml.getLong("a_a").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_underscores_in_table_names() throws Exception {
|
||||
Toml toml = new Toml().read("[group_a]\na = 1");
|
||||
|
||||
assertEquals(1, toml.getLong("group_a.a").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_numbers_in_key_names() throws Exception {
|
||||
Toml toml = new Toml().read("a1 = 1");
|
||||
|
||||
assertEquals(1, toml.getLong("a1").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_numbers_in_table_names() throws Exception {
|
||||
Toml toml = new Toml().read("[group1]\na = 1");
|
||||
|
||||
assertEquals(1, toml.getLong("group1.a").intValue());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_characters_outside_accept_range_are_used_in_table_name() throws Exception {
|
||||
new Toml().read("[~]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_characters_outside_accept_range_are_used_in_table_array_name() throws Exception {
|
||||
new Toml().read("[[~]]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_dots_in_key_name() throws Exception {
|
||||
new Toml().read("a.b = 1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_characters_outside_accept_range_are_used_in_key_name() throws Exception {
|
||||
new Toml().read("~ = 1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_sharp_sign_in_table_name() throws Exception {
|
||||
new Toml().read("[group#]\nkey=1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_spaces_in_table_name() throws Exception {
|
||||
new Toml().read("[valid key]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_sharp_sign_in_table_array_name() throws Exception {
|
||||
new Toml().read("[[group#]]\nkey=1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_spaces_in_table_array_name() throws Exception {
|
||||
new Toml().read("[[valid key]]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_question_marks_in_key_name() throws Exception {
|
||||
new Toml().read("key?=true");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_empty_table_name() {
|
||||
new Toml().read("[]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_nested_table_name_ending_with_empty_table_name() {
|
||||
new Toml().read("[a.]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_nested_table_name_containing_empty_table_name() {
|
||||
new Toml().read("[a..b]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_nested_table_name_starting_with_empty_table_name() {
|
||||
new Toml().read("[.b]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_nested_table_array_name_ending_with_empty_table_name() {
|
||||
new Toml().read("[[a.]]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_nested_table_array_name_containing_empty_table_name() {
|
||||
new Toml().read("[[a..b]]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_nested_table_array_name_starting_with_empty_table_name() {
|
||||
new Toml().read("[[.b]]");
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BooleanTest {
|
||||
|
||||
@Test
|
||||
public void should_get_boolean() throws Exception {
|
||||
Toml toml = new Toml().read("bool_false = false\nbool_true = true");
|
||||
|
||||
assertFalse(toml.getBoolean("bool_false"));
|
||||
assertTrue(toml.getBoolean("bool_true"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_invalid_boolean_true() {
|
||||
new Toml().read("answer = true abc");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_invalid_boolean_false() {
|
||||
new Toml().read("answer = false abc");
|
||||
}
|
||||
}
|
|
@ -1,218 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BurntSushiInvalidTest {
|
||||
private InputStream inputToml;
|
||||
|
||||
@Test
|
||||
public void key_empty() throws Exception {
|
||||
runInvalidTest("key-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_hash() throws Exception {
|
||||
runInvalidTest("key-hash");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_newline() throws Exception {
|
||||
runInvalidTest("key-newline");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_open_bracket() throws Exception {
|
||||
runInvalidTest("key-open-bracket");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_single_open_bracket() throws Exception {
|
||||
runInvalidTest("key-single-open-bracket");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_start_bracket() throws Exception {
|
||||
runInvalidTest("key-start-bracket");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_two_equals() throws Exception {
|
||||
runInvalidTest("key-two-equals");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_bad_byte_escape() throws Exception {
|
||||
runInvalidTest("string-bad-byte-escape");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_bad_escape() throws Exception {
|
||||
runInvalidTest("string-bad-escape");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_byte_escapes() throws Exception {
|
||||
runInvalidTest("string-byte-escapes");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_no_close() throws Exception {
|
||||
runInvalidTest("string-no-close");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_implicit() throws Exception {
|
||||
runInvalidTest("table-array-implicit");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_malformed_bracket() throws Exception {
|
||||
runInvalidTest("table-array-malformed-bracket");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_malformed_empty() throws Exception {
|
||||
runInvalidTest("table-array-malformed-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_empty() throws Exception {
|
||||
runInvalidTest("table-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_nested_brackets_close() throws Exception {
|
||||
runInvalidTest("table-nested-brackets-close");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_nested_brackets_open() throws Exception {
|
||||
runInvalidTest("table-nested-brackets-open");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty_implicit_table() {
|
||||
runInvalidTest("empty-implicit-table");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty_table() throws Exception {
|
||||
runInvalidTest("empty-table");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void array_mixed_types_ints_and_floats() throws Exception {
|
||||
runInvalidTest("array-mixed-types-ints-and-floats");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void array_mixed_types_arrays_and_ints() throws Exception {
|
||||
runInvalidTest("array-mixed-types-arrays-and-ints");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void array_mixed_types_strings_and_ints() throws Exception {
|
||||
runInvalidTest("array-mixed-types-strings-and-ints");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime_malformed_no_leads() throws Exception {
|
||||
runInvalidTest("datetime-malformed-no-leads");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime_malformed_no_secs() throws Exception {
|
||||
runInvalidTest("datetime-malformed-no-secs");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime_malformed_no_t() throws Exception {
|
||||
runInvalidTest("datetime-malformed-no-t");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime_malformed_no_z() throws Exception {
|
||||
runInvalidTest("datetime-malformed-no-z");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime_malformed_with_milli() throws Exception {
|
||||
runInvalidTest("datetime-malformed-with-milli");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicate_key_table() throws Exception {
|
||||
runInvalidTest("duplicate-key-table");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicate_keys() throws Exception {
|
||||
runInvalidTest("duplicate-keys");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicate_tables() throws Exception {
|
||||
runInvalidTest("duplicate-tables");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void float_no_leading_zero() throws Exception {
|
||||
runInvalidTest("float-no-leading-zero");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void float_no_trailing_digits() throws Exception {
|
||||
runInvalidTest("float-no-trailing-digits");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text_after_array_entries() throws Exception {
|
||||
runInvalidTest("text-after-array-entries");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text_after_integer() throws Exception {
|
||||
runInvalidTest("text-after-integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text_after_string() throws Exception {
|
||||
runInvalidTest("text-after-string");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text_after_table() throws Exception {
|
||||
runInvalidTest("text-after-table");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text_before_array_separator() throws Exception {
|
||||
runInvalidTest("text-before-array-separator");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void text_in_array() throws Exception {
|
||||
runInvalidTest("text-in-array");
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws IOException {
|
||||
inputToml.close();
|
||||
}
|
||||
|
||||
private void runInvalidTest(String testName) {
|
||||
inputToml = getClass().getResourceAsStream("burntsushi/invalid/" + testName + ".toml");
|
||||
|
||||
try {
|
||||
new Toml().read(inputToml);
|
||||
Assert.fail("Should have rejected invalid input!");
|
||||
} catch (IllegalStateException e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,214 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.junit.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BurntSushiValidEncoderTest {
|
||||
|
||||
@Test
|
||||
public void array_empty() throws Exception {
|
||||
runEncoder("array-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrays_hetergeneous() throws Exception {
|
||||
runEncoder("arrays-hetergeneous");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrays_nested() throws Exception {
|
||||
runEncoder("arrays-nested");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime() throws Exception {
|
||||
runEncoder("datetime");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty() throws Exception {
|
||||
runEncoder("empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void example() throws Exception {
|
||||
runEncoder("example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void float_() throws Exception {
|
||||
runEncoder("float");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void implicit_and_explicit_before() throws Exception {
|
||||
runEncoder("implicit-and-explicit-before");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicit_groups() throws Exception {
|
||||
runEncoder("implicit-groups");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void long_float() throws Exception {
|
||||
runEncoder("long-float");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void long_integer() throws Exception {
|
||||
runEncoder("long-integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_special_chars_modified() throws Exception {
|
||||
runEncoder("key-special-chars-modified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integer() throws Exception {
|
||||
runEncoder("integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_empty() throws Exception {
|
||||
runEncoder("string-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_escapes_modified() throws Exception {
|
||||
runEncoder("string-escapes-modified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_simple() throws Exception {
|
||||
runEncoder("string-simple");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_implicit() throws Exception {
|
||||
runEncoder("table-array-implicit");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_many() throws Exception {
|
||||
runEncoder("table-array-many");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_nest_modified() throws Exception {
|
||||
// Modified to remove stray spaces in the expected TOML
|
||||
runEncoder("table-array-nest-modified",
|
||||
new TomlWriter.Builder().indentTablesBy(2).build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_one() throws Exception {
|
||||
runEncoder("table-array-one");
|
||||
}
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
private void runEncoder(String testName) {
|
||||
runEncoder(testName, new TomlWriter());
|
||||
}
|
||||
|
||||
private void runEncoder(String testName, TomlWriter tomlWriter) {
|
||||
InputStream inputTomlStream = getClass().getResourceAsStream("burntsushi/valid/" + testName + ".toml");
|
||||
String expectedToml = convertStreamToString(inputTomlStream).replaceAll("\r\n", "\n");
|
||||
|
||||
Reader inputJsonReader = new InputStreamReader(getClass().getResourceAsStream("burntsushi/valid/" + testName + ".json"));
|
||||
JsonElement jsonInput = GSON.fromJson(inputJsonReader, JsonElement.class);
|
||||
Map<String, Object> enriched = enrichJson(jsonInput.getAsJsonObject());
|
||||
|
||||
String encoded = tomlWriter.write(enriched);
|
||||
assertEquals(expectedToml, encoded);
|
||||
}
|
||||
|
||||
// Enrich toml-test JSON trees into native Java types, suiteable
|
||||
// for consumption by TomlWriter.
|
||||
private Map<String, Object> enrichJson(JsonObject jsonObject) {
|
||||
Map<String, Object> enriched = new LinkedHashMap<String, Object>();
|
||||
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
|
||||
enriched.put(entry.getKey(), enrichJsonElement(entry.getValue()));
|
||||
}
|
||||
|
||||
return enriched;
|
||||
}
|
||||
|
||||
Object enrichJsonElement(JsonElement jsonElement) {
|
||||
if (jsonElement.isJsonObject()) {
|
||||
JsonObject jsonObject = jsonElement.getAsJsonObject();
|
||||
if (jsonObject.has("type") && jsonObject.has("value")) {
|
||||
return enrichPrimitive(jsonObject);
|
||||
}
|
||||
return enrichJson(jsonElement.getAsJsonObject());
|
||||
} else if (jsonElement.isJsonArray()) {
|
||||
List<Object> tables = new LinkedList<Object>();
|
||||
for (JsonElement arrayElement : jsonElement.getAsJsonArray()) {
|
||||
tables.add(enrichJsonElement(arrayElement));
|
||||
}
|
||||
|
||||
return tables;
|
||||
}
|
||||
|
||||
throw new AssertionError("received unexpected JsonElement: " + jsonElement);
|
||||
}
|
||||
|
||||
private Object enrichPrimitive(JsonObject jsonObject) {
|
||||
String type = jsonObject.getAsJsonPrimitive("type").getAsString();
|
||||
if ("bool".equals(type)) {
|
||||
return jsonObject.getAsJsonPrimitive("value").getAsBoolean();
|
||||
} else if ("integer".equals(type)) {
|
||||
return jsonObject.getAsJsonPrimitive("value").getAsBigInteger();
|
||||
} else if ("float".equals(type)) {
|
||||
return jsonObject.getAsJsonPrimitive("value").getAsDouble();
|
||||
} else if ("string".equals(type)) {
|
||||
return jsonObject.getAsJsonPrimitive("value").getAsString();
|
||||
} else if ("datetime".equals(type)) {
|
||||
DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
String dateString = jsonObject.getAsJsonPrimitive("value").getAsString();
|
||||
try {
|
||||
return iso8601Format.parse(dateString);
|
||||
} catch (ParseException e) {
|
||||
throw new AssertionError("failed to parse datetime '" + dateString + "': " + e.getMessage());
|
||||
}
|
||||
} else if ("array".equals(type)) {
|
||||
JsonArray jsonArray = jsonObject.getAsJsonArray("value");
|
||||
List<Object> enriched = new LinkedList<Object>();
|
||||
for (JsonElement arrayElement : jsonArray) {
|
||||
enriched.add(enrichJsonElement(arrayElement));
|
||||
}
|
||||
|
||||
return enriched;
|
||||
}
|
||||
|
||||
throw new AssertionError("enrichPrimitive: received unknown type " + type);
|
||||
}
|
||||
|
||||
static String convertStreamToString(java.io.InputStream is) {
|
||||
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,361 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
public class BurntSushiValidTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void array_empty() throws Exception {
|
||||
run("array-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void array_nospaces() throws Exception {
|
||||
run("array-nospaces");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrays_hetergeneous() throws Exception {
|
||||
run("arrays-hetergeneous");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrays_nested() throws Exception {
|
||||
run("arrays-nested");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void arrays() throws Exception {
|
||||
run("arrays");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bool() throws Exception {
|
||||
run("bool");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comments_everywhere() throws Exception {
|
||||
run("comments-everywhere");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void datetime() throws Exception {
|
||||
run("datetime");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty() throws Exception {
|
||||
run("empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void example() throws Exception {
|
||||
run("example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void float_() throws Exception {
|
||||
run("float");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicit_and_explicit_after() throws Exception {
|
||||
run("implicit-and-explicit-after");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicit_and_explicit_before() throws Exception {
|
||||
run("implicit-and-explicit-before");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void implicit_groups() throws Exception {
|
||||
run("implicit-groups");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void integer() throws Exception {
|
||||
run("integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_equals_nospace() throws Exception {
|
||||
run("key-equals-nospace");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void key_space() throws Exception {
|
||||
run("key-space");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_space_modified() throws Exception {
|
||||
run("key-space-modified");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void key_special_chars() throws Exception {
|
||||
run("key-special-chars");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_special_chars_modified() throws Exception {
|
||||
run("key-special-chars-modified");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void keys_with_dots() throws Exception {
|
||||
run("keys-with-dots");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keys_with_dots_modified() throws Exception {
|
||||
run("keys-with-dots-modified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void long_float() throws Exception {
|
||||
run("long-float");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void long_integer() throws Exception {
|
||||
run("long-integer");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void multiline_string() throws Exception {
|
||||
run("multiline-string");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiline_string_modified() throws Exception {
|
||||
run("multiline-string-modified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void raw_multiline_string() throws Exception {
|
||||
run("raw-multiline-string");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void raw_string() throws Exception {
|
||||
run("raw-string");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_empty() throws Exception {
|
||||
run("string-empty");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void string_escapes() throws Exception {
|
||||
run("string-escapes-modified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_escapes_modified() throws Exception {
|
||||
run("string-escapes-modified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_simple() throws Exception {
|
||||
run("string-simple");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void string_with_pound() throws Exception {
|
||||
run("string-with-pound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_implicit() throws Exception {
|
||||
run("table-array-implicit");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_many() throws Exception {
|
||||
run("table-array-many");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_nest() throws Exception {
|
||||
run("table-array-nest");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_array_one() throws Exception {
|
||||
run("table-array-one");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_empty() throws Exception {
|
||||
run("table-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_sub_empty() throws Exception {
|
||||
run("table-sub-empty");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void table_whitespace() throws Exception {
|
||||
run("table-whitespace");
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void table_with_pound() throws Exception {
|
||||
run("table-with-pound");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unicode_escape() throws Exception {
|
||||
run("unicode-escape");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unicode_literal() throws Exception {
|
||||
run("unicode-literal");
|
||||
}
|
||||
|
||||
private void run(String testName) {
|
||||
InputStream inputTomlStream = getClass().getResourceAsStream("burntsushi/valid/" + testName + ".toml");
|
||||
// InputStream inputToml = getClass().getResourceAsStream("burntsushi/valid/" + testName + ".toml");
|
||||
String inputToml = convertStreamToString(inputTomlStream).replaceAll("\r\n", "\n");
|
||||
Reader expectedJsonReader = new InputStreamReader(getClass().getResourceAsStream("burntsushi/valid/" + testName + ".json"));
|
||||
JsonElement expectedJson = GSON.fromJson(expectedJsonReader, JsonElement.class);
|
||||
|
||||
Toml toml = new Toml().read(inputToml);
|
||||
JsonElement actual = TEST_GSON.toJsonTree(toml).getAsJsonObject().get("values");
|
||||
|
||||
assertEquals(expectedJson, actual);
|
||||
|
||||
try {
|
||||
inputTomlStream.close();
|
||||
} catch (IOException e) {}
|
||||
|
||||
try {
|
||||
expectedJsonReader.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
static String convertStreamToString(java.io.InputStream is) {
|
||||
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
|
||||
return s.hasNext() ? s.next() : "";
|
||||
}
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
private static final Gson TEST_GSON = new GsonBuilder()
|
||||
.registerTypeAdapter(Boolean.class, serialize(Boolean.class))
|
||||
.registerTypeAdapter(String.class, serialize(String.class))
|
||||
.registerTypeAdapter(Long.class, serialize(Long.class))
|
||||
.registerTypeAdapter(Double.class, serialize(Double.class))
|
||||
.registerTypeAdapter(Date.class, new JsonSerializer<Date>() {
|
||||
@Override
|
||||
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
return context.serialize(new Value("datetime", iso8601Format.format(src)));
|
||||
}
|
||||
})
|
||||
.registerTypeHierarchyAdapter(List.class, new JsonSerializer<List<?>>() {
|
||||
@Override
|
||||
public JsonElement serialize(List<?> src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonArray array = new JsonArray();
|
||||
for (Object o : src) {
|
||||
array.add(context.serialize(o));
|
||||
}
|
||||
|
||||
if (!src.isEmpty() && src.get(0) instanceof Map) {
|
||||
return array;
|
||||
}
|
||||
|
||||
JsonObject object = new JsonObject();
|
||||
object.add("type", new JsonPrimitive("array"));
|
||||
object.add("value", array);
|
||||
|
||||
return object;
|
||||
}
|
||||
})
|
||||
.registerTypeAdapter(Value.class, new JsonSerializer<Value>() {
|
||||
@Override
|
||||
public JsonElement serialize(Value src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
JsonObject object = new JsonObject();
|
||||
object.add("type", new JsonPrimitive(src.type));
|
||||
object.add("value", new JsonPrimitive(src.value));
|
||||
|
||||
return object;
|
||||
}
|
||||
})
|
||||
.create();
|
||||
|
||||
private static class Value {
|
||||
public final String type;
|
||||
public final String value;
|
||||
|
||||
public Value(String type, String value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> JsonSerializer<T> serialize(final Class<T> aClass) {
|
||||
return new JsonSerializer<T>() {
|
||||
@Override
|
||||
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return context.serialize(new Value(toTomlType(aClass), src.toString()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static String toTomlType(Class<?> aClass) {
|
||||
if (aClass == String.class) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
if (aClass == Double.class) {
|
||||
return "float";
|
||||
}
|
||||
|
||||
if (aClass == Long.class) {
|
||||
return "integer";
|
||||
}
|
||||
|
||||
if (aClass == Date.class) {
|
||||
return "datetime";
|
||||
}
|
||||
|
||||
if (aClass == Boolean.class) {
|
||||
return "bool";
|
||||
}
|
||||
|
||||
return "array";
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ContainsTest {
|
||||
|
||||
@Test
|
||||
public void should_contain_top_level_of_any_type() throws Exception {
|
||||
Toml toml = new Toml().read("a = 1 \n [b] \n b1 = 1 \n [[c]] \n c1 = 1");
|
||||
|
||||
assertTrue(toml.contains("a"));
|
||||
assertTrue(toml.contains("b"));
|
||||
assertTrue(toml.contains("c"));
|
||||
assertFalse(toml.contains("d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_contain_nested_of_any_type() throws Exception {
|
||||
Toml toml = new Toml().read("[a] \n a1 = 1 \n [[b]] \n b1 = 1 \n [[b]] \n b1 = 2 \n b2 = 3");
|
||||
|
||||
assertTrue(toml.contains("a.a1"));
|
||||
assertTrue(toml.contains("b[0].b1"));
|
||||
assertTrue(toml.contains("b[1].b1"));
|
||||
assertFalse(toml.contains("b[2].b1"));
|
||||
assertFalse(toml.contains("c.d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_contain_primitive() throws Exception {
|
||||
Toml toml = new Toml().read("a = 1 \n [b] \n b1 = 1 \n [[c]] \n c1 = 1");
|
||||
|
||||
assertTrue(toml.containsPrimitive("a"));
|
||||
assertTrue(toml.containsPrimitive("b.b1"));
|
||||
assertTrue(toml.containsPrimitive("c[0].c1"));
|
||||
assertFalse(toml.containsPrimitive("b"));
|
||||
assertFalse(toml.containsPrimitive("c"));
|
||||
assertFalse(toml.containsPrimitive("d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_contain_table() throws Exception {
|
||||
Toml toml = new Toml().read("a = 1 \n [b] \n b1 = 1 \n [b.b2] \n [[c]] \n c1 = 1 \n [c.c2]");
|
||||
|
||||
assertTrue(toml.containsTable("b"));
|
||||
assertTrue(toml.containsTable("b.b2"));
|
||||
assertTrue(toml.containsTable("c[0].c2"));
|
||||
assertFalse(toml.containsTable("a"));
|
||||
assertFalse(toml.containsTable("b.b1"));
|
||||
assertFalse(toml.containsTable("c"));
|
||||
assertFalse(toml.containsTable("c[0].c1"));
|
||||
assertFalse(toml.containsTable("d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_contain_table_array() throws Exception {
|
||||
Toml toml = new Toml().read("a = 1 \n [b] \n b1 = 1 \n [[c]] \n c1 = 1 \n [c.c2] \n [[c]] \n [[c.c3]] \n c4 = 4");
|
||||
|
||||
assertTrue(toml.containsTableArray("c"));
|
||||
assertTrue(toml.containsTableArray("c[1].c3"));
|
||||
assertFalse(toml.containsTableArray("a"));
|
||||
assertFalse(toml.containsTableArray("b"));
|
||||
assertFalse(toml.containsTableArray("b.b1"));
|
||||
assertFalse(toml.containsTableArray("c[1].c3[0].c4"));
|
||||
assertFalse(toml.containsTableArray("d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_contain_when_parent_table_is_missing() throws Exception {
|
||||
Toml toml = new Toml().read("a = \"1\"");
|
||||
|
||||
assertFalse(toml.contains("b.b1"));
|
||||
assertFalse(toml.containsPrimitive("b.b1"));
|
||||
assertFalse(toml.containsTable("b.b1"));
|
||||
assertFalse(toml.containsTableArray("b.b1"));
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class DateTest {
|
||||
|
||||
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
|
||||
@Test
|
||||
public void should_get_date() throws Exception {
|
||||
Toml toml = new Toml().read("a_date = 2011-11-10T13:12:00Z");
|
||||
|
||||
Calendar calendar = Calendar.getInstance(UTC);
|
||||
calendar.set(2011, Calendar.NOVEMBER, 10, 13, 12, 00);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
assertEquals(calendar.getTime(), toml.getDate("a_date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_date_with_offset() throws Exception {
|
||||
Toml toml = new Toml().read("a_date = 1979-05-27T00:32:00-07:00");
|
||||
|
||||
Calendar calendar = Calendar.getInstance(UTC);
|
||||
calendar.set(1979, Calendar.MAY, 27, 7, 32, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
assertEquals(calendar.getTime(), toml.getDate("a_date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_date_with_positive_offset() throws Exception {
|
||||
Toml toml = new Toml().read("a_date = 1979-05-27T07:32:00+07:00");
|
||||
|
||||
Calendar calendar = Calendar.getInstance(UTC);
|
||||
calendar.set(1979, Calendar.MAY, 27, 0, 32, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
assertEquals(calendar.getTime(), toml.getDate("a_date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_date_with_fractional_seconds() throws Exception {
|
||||
Toml toml = new Toml().read("a_date = 1979-05-27T00:32:00.999Z");
|
||||
|
||||
Calendar calendar = Calendar.getInstance(UTC);
|
||||
calendar.set(1979, Calendar.MAY, 27, 0, 32, 00);
|
||||
calendar.set(Calendar.MILLISECOND, 999);
|
||||
|
||||
assertEquals(calendar.getTime(), toml.getDate("a_date"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_date_with_fractional_seconds_and_offset() throws Exception {
|
||||
Toml toml = new Toml().read("a_date = 1979-05-27T00:32:00.999-07:00");
|
||||
|
||||
Calendar calendar = Calendar.getInstance(UTC);
|
||||
calendar.set(1979, Calendar.MAY, 27, 7, 32, 00);
|
||||
calendar.set(Calendar.MILLISECOND, 999);
|
||||
|
||||
assertEquals(calendar.getTime(), toml.getDate("a_date"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_non_existant_date() throws Exception {
|
||||
new Toml().read("d = 2012-13-01T15:00:00Z");
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class DefaultValueTest {
|
||||
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
|
||||
private static final Calendar CALENDAR = Calendar.getInstance(UTC);
|
||||
private static final Date _2011_11_10;
|
||||
private static final Date _2012_11_10;
|
||||
|
||||
static {
|
||||
CALENDAR.set(2011, Calendar.NOVEMBER, 10, 13, 12, 00);
|
||||
CALENDAR.set(Calendar.MILLISECOND, 0);
|
||||
_2011_11_10 = CALENDAR.getTime();
|
||||
CALENDAR.set(Calendar.YEAR, 2012);
|
||||
_2012_11_10 = CALENDAR.getTime();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_string() throws Exception {
|
||||
Toml toml = new Toml().read("s = \"string value\"");
|
||||
assertEquals("string value", toml.getString("s", "default string value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_string_default_value() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
assertEquals("default string value", toml.getString("s", "default string value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_long() throws Exception {
|
||||
Toml toml = new Toml().read("n = 1001");
|
||||
assertEquals(Long.valueOf(1001), toml.getLong("n", 1002L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_long_default_value() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
assertEquals(Long.valueOf(1002), toml.getLong("n", 1002L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_double() throws Exception {
|
||||
Toml toml = new Toml().read("n = 0.5");
|
||||
assertEquals(Double.valueOf(0.5), toml.getDouble("n", Double.valueOf(0.6)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_double_default_value() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
assertEquals(Double.valueOf(0.6), toml.getDouble("n", Double.valueOf(0.6)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_boolean() throws Exception {
|
||||
Toml toml = new Toml().read("b = true");
|
||||
assertEquals(Boolean.TRUE, toml.getBoolean("b", Boolean.FALSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_boolean_default_value() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
assertEquals(Boolean.FALSE, toml.getBoolean("b", Boolean.FALSE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_date() throws Exception {
|
||||
Toml toml = new Toml().read("d = 2011-11-10T13:12:00Z");
|
||||
|
||||
assertEquals(_2011_11_10, toml.getDate("d", _2012_11_10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_date_default_value() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
|
||||
assertEquals(_2012_11_10, toml.getDate("d", _2012_11_10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_array() throws Exception {
|
||||
Toml toml = new Toml().read("a = [1, 2, 3]\n b = []");
|
||||
|
||||
assertEquals(asList(1L, 2L, 3L), toml.getList("a", asList(3L, 2L, 1L)));
|
||||
assertEquals(Collections.emptyList(), toml.getList("b", asList(3L, 2L, 1L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_empty_array() throws Exception {
|
||||
Toml toml = new Toml().read("a = []");
|
||||
|
||||
assertEquals(Collections.emptyList(), toml.getList("a", asList(3L, 2L, 1L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_array_default_value() throws Exception {
|
||||
Toml toml = new Toml();
|
||||
|
||||
assertEquals(asList(3L, 2L, 1L), toml.getList("a", asList(3L, 2L, 1L)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_prefer_default_from_constructor() throws Exception {
|
||||
Toml defaults = new Toml().read("n = 1\n d = 1.1\n b = true\n date = 2011-11-10T13:12:00Z\n s = 'a'\n a = [1, 2, 3]");
|
||||
Toml toml = new Toml(defaults).read("");
|
||||
|
||||
assertEquals(1, toml.getLong("n", 2L).intValue());
|
||||
assertEquals(1.1, toml.getDouble("d", 2.2), 0);
|
||||
assertTrue(toml.getBoolean("b", false));
|
||||
assertEquals(_2011_11_10, toml.getDate("date", _2012_11_10));
|
||||
assertEquals("a", toml.getString("s", "b"));
|
||||
assertEquals(asList(1L, 2L, 3L), toml.getList("a", asList(3L, 2L, 1L)));
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class ErrorMessagesTest {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException e = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void invalid_table() throws Exception {
|
||||
e.expectMessage("Invalid table definition on line 1: [in valid]");
|
||||
|
||||
new Toml().read("[in valid]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicate_table() throws Exception {
|
||||
e.expectMessage("Duplicate table definition on line 2: [again]");
|
||||
|
||||
new Toml().read("[again]\n[again]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void empty_implicit_table_name() throws Exception {
|
||||
e.expectMessage("Invalid table definition due to empty implicit table name: [a..b]");
|
||||
|
||||
new Toml().read("[a..b]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void duplicate_key() throws Exception {
|
||||
e.expectMessage("Duplicate key on line 2: k");
|
||||
|
||||
new Toml().read("k = 1\n k = 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalid_key() throws Exception {
|
||||
e.expectMessage("Key is not followed by an equals sign on line 1: k\" = 1");
|
||||
|
||||
new Toml().read("k\" = 1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalid_table_array() throws Exception {
|
||||
e.expectMessage("Invalid table array definition on line 1: [[in valid]]");
|
||||
|
||||
new Toml().read("[[in valid]]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalid_value() throws Exception {
|
||||
e.expectMessage("Invalid text after key k on line 1");
|
||||
|
||||
new Toml().read("k = 1 t");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unterminated_multiline_literal_string() throws Exception {
|
||||
e.expectMessage("Unterminated value on line 1: k = '''abc");
|
||||
|
||||
new Toml().read("k = '''abc");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unterminated_multiline_string() throws Exception {
|
||||
e.expectMessage("Unterminated value on line 1: k = \"\"\"abc\"\"");
|
||||
|
||||
new Toml().read("k = \"\"\"abc\"\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unterminated_array() throws Exception {
|
||||
e.expectMessage("Unterminated value on line 1: k = [\"abc\"");
|
||||
|
||||
new Toml().read("k = [\"abc\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unterminated_inline_table() throws Exception {
|
||||
e.expectMessage("Unterminated value on line 1: k = { a = \"abc\"");
|
||||
|
||||
new Toml().read("k = { a = \"abc\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_without_equals() throws Exception {
|
||||
e.expectMessage("Key is not followed by an equals sign on line 2: k");
|
||||
|
||||
new Toml().read("\nk\n=3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void heterogeneous_array() throws Exception {
|
||||
e.expectMessage("k becomes a heterogeneous array on line 2");
|
||||
|
||||
new Toml().read("k = [ 1,\n 1.1 ]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void key_in_root_is_overwritten_by_table() throws Exception {
|
||||
e.expectMessage("Key already exists for table defined on line 2: [a]");
|
||||
|
||||
new Toml().read("a=1\n [a]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void table_is_overwritten_by_key() throws Exception {
|
||||
e.expectMessage("Table already exists for key defined on line 3: b");
|
||||
|
||||
new Toml().read("[a.b]\n [a]\n b=1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_display_correct_line_number_with_literal_multiline_string() throws Exception {
|
||||
e.expectMessage("on line 8");
|
||||
|
||||
new Toml().read("[table]\n\n k = '''abc\n\ndef\n'''\n # comment \n j = 4.\n l = 5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_display_correct_line_number_with_multiline_string() throws Exception {
|
||||
e.expectMessage("on line 9");
|
||||
|
||||
new Toml().read("[table]\n\n k = \"\"\"\nabc\n\ndef\n\"\"\"\n # comment \n j = 4.\n l = 5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_display_correct_line_number_with_array() throws Exception {
|
||||
e.expectMessage("on line 10");
|
||||
|
||||
new Toml().read("[table]\n\n k = [\"\"\"\nabc\n\ndef\n\"\"\"\n, \n # comment \n j = 4.,\n l = 5\n]");
|
||||
}
|
||||
}
|
|
@ -1,236 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class InlineTableTest {
|
||||
|
||||
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
|
||||
@Rule
|
||||
public ExpectedException e = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void should_read_empty_inline_table() throws Exception {
|
||||
Toml toml = new Toml().read("key = {}");
|
||||
|
||||
assertTrue(toml.getTable("key").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_inline_table_with_strings() throws Exception {
|
||||
Toml toml = new Toml().read("name = { first = \"Tom\", last = \"Preston-Werner\"}");
|
||||
|
||||
assertEquals("Tom", toml.getTable("name").getString("first"));
|
||||
assertEquals("Preston-Werner", toml.getString("name.last"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_inline_table_with_integers() throws Exception {
|
||||
Toml toml = new Toml().read("point = { x = 1, y = 2 }");
|
||||
|
||||
assertEquals(1, toml.getTable("point").getLong("x").longValue());
|
||||
assertEquals(2, toml.getLong("point.y").longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_inline_table_with_floats() throws Exception {
|
||||
Toml toml = new Toml().read("point = { x = 1.5, y = 2.3 }");
|
||||
|
||||
assertEquals(1.5, toml.getTable("point").getDouble("x").doubleValue(), 0);
|
||||
assertEquals(2.3, toml.getDouble("point.y").doubleValue(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_inline_table_with_booleans() throws Exception {
|
||||
Toml toml = new Toml().read("point = { x = false, y = true }");
|
||||
|
||||
assertTrue(toml.getTable("point").getBoolean("y"));
|
||||
assertFalse(toml.getBoolean("point.x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_inline_table_with_dates() throws Exception {
|
||||
Toml toml = new Toml().read("point = { x = 2015-02-09T22:05:00Z, y = 2015-02-09T21:05:00Z }");
|
||||
|
||||
Calendar x = Calendar.getInstance(UTC);
|
||||
x.set(2015, Calendar.FEBRUARY, 9, 22, 5, 00);
|
||||
x.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Calendar y = Calendar.getInstance(UTC);
|
||||
y.set(2015, Calendar.FEBRUARY, 9, 21, 5, 00);
|
||||
y.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
assertEquals(x.getTime(), toml.getTable("point").getDate("x"));
|
||||
assertEquals(y.getTime(), toml.getDate("point.y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_arrays() throws Exception {
|
||||
Toml toml = new Toml().read("arrays = { integers = [1, 2, 3], strings = [\"a\", \"b\", \"c\"] }");
|
||||
|
||||
assertThat(toml.<Long>getList("arrays.integers"), contains(1L, 2L, 3L));
|
||||
assertThat(toml.<String>getList("arrays.strings"), contains("a", "b", "c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_nested_arrays() throws Exception {
|
||||
Toml toml = new Toml().read("arrays = { nested = [[1, 2, 3], [4, 5, 6]] }").getTable("arrays");
|
||||
|
||||
List<List<Long>> nested = toml.<List<Long>>getList("nested");
|
||||
assertThat(nested, hasSize(2));
|
||||
assertThat(nested.get(0), contains(1L, 2L, 3L));
|
||||
assertThat(nested.get(1), contains(4L, 5L, 6L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_mixed_inline_table() throws Exception {
|
||||
Toml toml = new Toml().read("point = { date = 2015-02-09T22:05:00Z, bool = true, integer = 123, float = 123.456, string = \"abc\", list = [5, 6, 7, 8] }").getTable("point");
|
||||
|
||||
|
||||
Calendar date = Calendar.getInstance(UTC);
|
||||
date.set(2015, Calendar.FEBRUARY, 9, 22, 5, 00);
|
||||
date.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
assertEquals(date.getTime(), toml.getDate("date"));
|
||||
assertTrue(toml.getBoolean("bool"));
|
||||
assertEquals(123, toml.getLong("integer").intValue());
|
||||
assertEquals(123.456, toml.getDouble("float"), 0);
|
||||
assertEquals("abc", toml.getString("string"));
|
||||
assertThat(toml.<Long>getList("list"), contains(5L, 6L, 7L, 8L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_nested_inline_tables() throws Exception {
|
||||
Toml tables = new Toml().read("tables = { t1 = { t1_1 = 1, t1_2 = 2}, t2 = { t2_1 = { t2_1_1 = \"a\" }} }").getTable("tables");
|
||||
|
||||
assertEquals(1L, tables.getLong("t1.t1_1").longValue());
|
||||
assertEquals(2L, tables.getLong("t1.t1_2").longValue());
|
||||
assertEquals("a", tables.getString("t2.t2_1.t2_1_1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_all_string_types() throws Exception {
|
||||
Toml strings = new Toml().read("strings = { literal = 'ab]\"c', multiline = \"\"\"de]\"f\"\"\", multiline_literal = '''gh]\"i''' }").getTable("strings");
|
||||
|
||||
assertEquals("ab]\"c", strings.getString("literal"));
|
||||
assertEquals("de]\"f", strings.getString("multiline"));
|
||||
assertEquals("gh]\"i", strings.getString("multiline_literal"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_inline_table_in_regular_table() throws Exception {
|
||||
Toml toml = new Toml().read("[tbl]\n tbl = { tbl = 1 }");
|
||||
|
||||
assertEquals(1, toml.getLong("tbl.tbl.tbl").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_mix_with_tables() throws Exception {
|
||||
Toml toml = new Toml().read("t = { k = 1 }\n [b]\n k = 2\n t = { k = 3}");
|
||||
|
||||
assertEquals(1, toml.getLong("t.k").intValue());
|
||||
assertEquals(2, toml.getLong("b.k").intValue());
|
||||
assertEquals(3, toml.getLong("b.t.k").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_add_properties_to_existing_inline_table() throws Exception {
|
||||
Toml toml = new Toml().read("[a]\n b = {k = 1}\n [a.b.c]\n k = 2");
|
||||
|
||||
assertEquals(1, toml.getLong("a.b.k").intValue());
|
||||
assertEquals(2, toml.getLong("a.b.c.k").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_mix_with_table_arrays() throws Exception {
|
||||
Toml toml = new Toml().read("t = { k = 1 }\n [[b]]\n t = { k = 2 }\n [[b]]\n t = { k = 3 }");
|
||||
|
||||
assertEquals(1, toml.getLong("t.k").intValue());
|
||||
assertEquals(2, toml.getLong("b[0].t.k").intValue());
|
||||
assertEquals(3, toml.getLong("b[1].t.k").intValue());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_invalid_key() throws Exception {
|
||||
new Toml().read("tbl = { a. = 1 }");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_unterminated() throws Exception {
|
||||
new Toml().read("tbl = { a = 1 ");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_invalid_value() throws Exception {
|
||||
new Toml().read("tbl = { a = abc }");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_key_duplicated_inside_inline_table() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Duplicate key on line 1: a");
|
||||
|
||||
new Toml().read("tbl = { a = 1, a = 2 }");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_duplicated_by_other_key() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Table already exists for key defined on line 2: tbl");
|
||||
|
||||
new Toml().read("tbl = { a = 1 }\n tbl = 1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_duplicated_by_other_inline_table() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Duplicate table definition on line 2: [tbl]");
|
||||
|
||||
new Toml().read("tbl = { a = 1 }\n tbl = {}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_duplicated_by_top_level_table() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Duplicate table definition on line 2: [tbl]");
|
||||
|
||||
new Toml().read("tbl = {}\n [tbl]");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_duplicates_second_level_table() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Duplicate table definition on line 3: [a.b]");
|
||||
|
||||
new Toml().read("[a.b]\n [a]\n b = {}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_inline_table_duplicates_table() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Duplicate table definition on line 3: [a.b]");
|
||||
|
||||
new Toml().read("[a.b]\n [a]\n b = {}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_second_level_table_duplicates_inline_table() throws Exception {
|
||||
e.expect(IllegalStateException.class);
|
||||
e.expectMessage("Duplicate table definition on line 3: [a.b]");
|
||||
|
||||
new Toml().read("[a]\n b = {}\n [a.b]");
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import com.moandjiezana.toml.testutils.Utils;
|
||||
|
||||
public class IterationTest {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void should_iterate_over_primitive() throws Exception {
|
||||
Toml toml = new Toml().read(file("long"));
|
||||
Map.Entry<String, Object> entry = toml.entrySet().iterator().next();
|
||||
|
||||
assertEquals("long", entry.getKey());
|
||||
assertEquals(2L, entry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_iterate_over_list() throws Exception {
|
||||
Toml toml = new Toml().read(file("list"));
|
||||
Map.Entry<String, Object> entry = toml.entrySet().iterator().next();
|
||||
|
||||
assertEquals("list", entry.getKey());
|
||||
assertThat((List<String>) entry.getValue(), contains("a", "b", "c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_iterate_over_empty_list() throws Exception {
|
||||
Toml toml = new Toml().read("list = []");
|
||||
Map.Entry<String, Object> entry = toml.entrySet().iterator().next();
|
||||
|
||||
assertEquals("list", entry.getKey());
|
||||
assertThat((List<String>) entry.getValue(), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_iterate_over_table() throws Exception {
|
||||
Toml toml = new Toml().read(file("table"));
|
||||
Map.Entry<String, Object> entry = toml.entrySet().iterator().next();
|
||||
|
||||
assertEquals("table", entry.getKey());
|
||||
assertEquals("a", ((Toml) entry.getValue()).getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_iterate_over_table_array() throws Exception {
|
||||
Toml toml = new Toml().read(file("table_array"));
|
||||
|
||||
Map.Entry<String, Object> entry = toml.entrySet().iterator().next();
|
||||
List<Toml> tableArray = (List<Toml>) entry.getValue();
|
||||
|
||||
assertEquals("table_array", entry.getKey());
|
||||
assertThat(tableArray, contains(instanceOf(Toml.class), instanceOf(Toml.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_iterate_over_multiple_entries() throws Exception {
|
||||
Toml toml = new Toml().read(file("multiple"));
|
||||
|
||||
Map<String, Object> entries = new HashMap<String, Object>();
|
||||
for (Map.Entry<String, Object> entry : toml.entrySet()) {
|
||||
entries.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
assertThat(entries.keySet(), containsInAnyOrder("a", "b", "c", "e"));
|
||||
assertThat(entries, hasEntry("a", (Object) "a"));
|
||||
assertThat(entries, hasEntry("b", (Object) asList(1L, 2L, 3L)));
|
||||
assertTrue(((Toml) entries.get("c")).getBoolean("d"));
|
||||
assertThat(((List<Toml>) entries.get("e")), hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_support_setValue_method() throws Exception {
|
||||
Map.Entry<String, Object> entry = new Toml().read("a = 1").entrySet().iterator().next();
|
||||
|
||||
expectedException.expect(UnsupportedOperationException.class);
|
||||
entry.setValue(2L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_iterate_over_empty_toml() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
|
||||
assertThat(toml.entrySet(), empty());
|
||||
}
|
||||
|
||||
private File file(String name) {
|
||||
return Utils.file(getClass(), "/IteratorTest/" + name);
|
||||
}
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class NumberTest {
|
||||
@Test
|
||||
public void should_get_number() throws Exception {
|
||||
Toml toml = new Toml().read("b = 1001");
|
||||
|
||||
assertEquals(1001, toml.getLong("b").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_negative_number() throws Exception {
|
||||
Toml toml = new Toml().read("b = -1001");
|
||||
|
||||
assertEquals(-1001, toml.getLong("b").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_number_with_plus_sign() throws Exception {
|
||||
Toml toml = new Toml().read("a = +1001\nb = 1001");
|
||||
|
||||
assertEquals(toml.getLong("b"), toml.getLong("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_double() throws Exception {
|
||||
Toml toml = new Toml().read("double = 5.25");
|
||||
|
||||
assertEquals(5.25D, toml.getDouble("double").doubleValue(), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_negative_double() throws Exception {
|
||||
Toml toml = new Toml().read("double = -5.25");
|
||||
|
||||
assertEquals(-5.25D, toml.getDouble("double").doubleValue(), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_double_with_a_plus_sign() throws Exception {
|
||||
Toml toml = new Toml().read("double = +5.25");
|
||||
|
||||
assertEquals(5.25D, toml.getDouble("double").doubleValue(), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_exponent() throws Exception {
|
||||
Toml toml = new Toml().read("lower_case = 1e6\nupper_case = 2E6\nwith_plus = 5e+22\nboth_plus = +5E+22\nnegative = -2E-2\nfractional = 6.626e-34");
|
||||
|
||||
assertEquals(1e6, toml.getDouble("lower_case"), 0.0);
|
||||
assertEquals(2E6, toml.getDouble("upper_case"), 0.0);
|
||||
assertEquals(5e22, toml.getDouble("with_plus"), 0.0);
|
||||
assertEquals(5e22, toml.getDouble("both_plus"), 0.0);
|
||||
assertEquals(-2e-2, toml.getDouble("negative"), 0.0);
|
||||
assertEquals(6.626D * Math.pow(10, -34), toml.getDouble("fractional"), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_integer_with_underscores() throws Exception {
|
||||
Toml toml = new Toml().read("val = 100_000_000");
|
||||
|
||||
assertEquals(100000000L, toml.getLong("val").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_float_with_underscores() throws Exception {
|
||||
Toml toml = new Toml().read("val = 100_000.123_456");
|
||||
|
||||
assertEquals(100000.123456, toml.getDouble("val").doubleValue(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_exponent_with_underscores() throws Exception {
|
||||
Toml toml = new Toml().read("val = 1_5e1_00");
|
||||
|
||||
assertEquals(15e100, toml.getDouble("val").doubleValue(), 0.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_irregular_underscores() throws Exception {
|
||||
Toml toml = new Toml().read("val = 1_2_3_4_5");
|
||||
|
||||
assertEquals(12345L, toml.getLong("val").longValue());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_invalid_number() throws Exception {
|
||||
new Toml().read("a = 200-");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_illegal_characters_after_float() throws Exception {
|
||||
new Toml().read("number = 3.14 pi");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_illegal_characters_after_integer() throws Exception {
|
||||
new Toml().read("number = 314 pi");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_float_without_leading_0() {
|
||||
new Toml().read("answer = .12345");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_negative_float_without_leading_0() {
|
||||
new Toml().read("answer = -.12345");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_float_with_sign_after_dot() {
|
||||
new Toml().read("answer = 1.-1");
|
||||
new Toml().read("answer = 1.+1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_float_without_digits_after_dot() {
|
||||
new Toml().read("answer = 1.");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_negative_float_without_digits_after_dot() {
|
||||
new Toml().read("answer = -1.");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_exponent_without_digits_after_dot() {
|
||||
new Toml().read("answer = 1.E1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_negative_exponent_without_digits_after_dot() {
|
||||
new Toml().read("answer = -1.E1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_exponent_with_dot_in_exponent_part() {
|
||||
new Toml().read("answer = -1E1.0");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_exponent_without_numbers_after_E() {
|
||||
new Toml().read("answer = -1E");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_exponent_with_two_E() {
|
||||
new Toml().read("answer = -1E1E1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_float_with_two_dots() {
|
||||
new Toml().read("answer = 1.1.1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_at_beginning() {
|
||||
new Toml().read("answer = _1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_at_end() {
|
||||
new Toml().read("answer = 1_");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_two_underscores_in_a_row() {
|
||||
new Toml().read("answer = 1__1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_after_minus_sign() {
|
||||
new Toml().read("answer = -_1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_after_plus_sign() {
|
||||
new Toml().read("answer = +_1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_before_dot() {
|
||||
new Toml().read("answer = 1_.1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_after_dot() {
|
||||
new Toml().read("answer = 1._1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_before_E() {
|
||||
new Toml().read("answer = 1_E1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_after_E() {
|
||||
new Toml().read("answer = 1E_1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_underscore_followed_by_whitespace() {
|
||||
new Toml().read("answer = _ 1");
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class QuotedKeysTest {
|
||||
|
||||
@Test
|
||||
public void should_accept_quoted_key_for_value() throws Exception {
|
||||
Toml toml = new Toml().read("\"127.0.0.1\" = \"localhost\" \n \"character encoding\" = \"UTF-8\" \n \"ʎǝʞ\" = \"value\"");
|
||||
|
||||
assertEquals("localhost", toml.getString("\"127.0.0.1\""));
|
||||
assertEquals("UTF-8", toml.getString("\"character encoding\""));
|
||||
assertEquals("value", toml.getString("\"ʎǝʞ\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_quoted_key_for_table_name() throws Exception {
|
||||
Toml toml = new Toml().read("[\"abc def\"]\n val = 1");
|
||||
|
||||
assertEquals(1L, toml.getTable("\"abc def\"").getLong("val").longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_partially_quoted_table_name() throws Exception {
|
||||
Toml toml = new Toml().read("[dog.\"tater.man\"] \n type = \"pug0\" \n[dog.tater] \n type = \"pug1\"\n[dog.tater.man] \n type = \"pug2\"");
|
||||
Toml dogs = toml.getTable("dog");
|
||||
|
||||
assertEquals("pug0", dogs.getTable("\"tater.man\"").getString("type"));
|
||||
assertEquals("pug1", dogs.getTable("tater").getString("type"));
|
||||
assertEquals("pug2", dogs.getTable("tater").getTable("man").getString("type"));
|
||||
assertEquals("pug0", toml.getString("dog.\"tater.man\".type"));
|
||||
assertEquals("pug2", toml.getString("dog.tater.man.type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_conserve_quoted_key_in_map() throws Exception {
|
||||
Toml toml = new Toml().read("[dog.\"tater.man\"] \n type = \"pug0\" \n[dog.tater] \n type = \"pug1\"\n[dog.tater.man] \n type = \"pug2\"");
|
||||
Toml dogs = toml.getTable("dog");
|
||||
|
||||
Map<String, Map<String, Object>> map = dogs.to(Map.class);
|
||||
|
||||
assertEquals("pug0", map.get("\"tater.man\"").get("type"));
|
||||
assertEquals("pug1", map.get("tater").get("type"));
|
||||
assertEquals("pug2", ((Map<String, Object>) map.get("tater").get("man")).get("type"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_quoted_keys_to_map_but_not_to_object_fields() throws Exception {
|
||||
Quoted quoted = new Toml().read("\"ʎǝʞ\" = \"value\" \n[map] \n \"ʎǝʞ\" = \"value\"").to(Quoted.class);
|
||||
|
||||
assertNull(quoted.ʎǝʞ);
|
||||
assertEquals("value", quoted.map.get("\"ʎǝʞ\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_table_array_index_with_quoted_key() throws Exception {
|
||||
Toml toml = new Toml().read("[[ dog. \" type\" ]] \n name = \"type0\" \n [[dog.\" type\"]] \n name = \"type1\"");
|
||||
|
||||
assertEquals("type0", toml.getString("dog.\" type\"[0].name"));
|
||||
assertEquals("type1", toml.getString("dog.\" type\"[1].name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_table_array_index_with_dot_in_quoted_key() throws Exception {
|
||||
Toml toml = new Toml().read("[[ dog. \"a.type\" ]] \n name = \"type0\"");
|
||||
|
||||
assertEquals("type0", toml.getString("dog.\"a.type\"[0].name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_quoted_key_containing_square_brackets() throws Exception {
|
||||
Toml toml = new Toml().read("[dog.\" type[abc]\"] \n name = \"type0\" \n [dog.\" type[1]\"] \n \"name[]\" = \"type1\"");
|
||||
|
||||
assertEquals("type0", toml.getString("dog.\" type[abc]\".name"));
|
||||
assertEquals("type1", toml.getString("dog.\" type[1]\".\"name[]\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_quoted_key_containing_escaped_quote() throws Exception {
|
||||
Toml toml = new Toml().read("[dog.\"ty\\\"pe\"] \n \"na\\\"me\" = \"type0\"");
|
||||
|
||||
assertEquals("type0", toml.getString("dog.\"ty\\\"pe\".\"na\\\"me\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_fully_quoted_table_name() throws Exception {
|
||||
Toml toml = new Toml().read("[\"abc.def\"] \n key = 1");
|
||||
|
||||
assertEquals(1, toml.getLong("\"abc.def\".key").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_whitespace_around_key_segments() throws Exception {
|
||||
Toml toml = new Toml().read("[ dog. \"type\". breed ] \n name = \"type0\"");
|
||||
|
||||
assertEquals("type0", toml.getString("dog.\"type\".breed.name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_unicode() throws Exception {
|
||||
Toml toml = new Toml().read("[[\"\\u00B1\"]]\n \"\\u00B1\" = \"a\"\n [\"\\u00B11\"]\n \"±\" = 1");
|
||||
|
||||
assertThat(toml.getTables("\"±\""), hasSize(1));
|
||||
assertEquals("a", toml.getTables("\"±\"").get(0).getString("\"±\""));
|
||||
assertEquals(1, toml.getTable("\"±1\"").getLong("\"±\"").intValue());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_malformed_quoted_key() throws Exception {
|
||||
new Toml().read("k\"ey\" = 1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_malformed_quoted_table() throws Exception {
|
||||
new Toml().read("[a\"bc\"]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_malformed_quoted_nested_table() throws Exception {
|
||||
new Toml().read("[a.a\"bc\"]");
|
||||
}
|
||||
|
||||
private static class Quoted {
|
||||
|
||||
String ʎǝʞ;
|
||||
|
||||
Map<String, Object> map;
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RealWorldTest {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void should_parse_example() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("example.toml").getFile()));
|
||||
|
||||
// printMap(root);
|
||||
|
||||
assertEquals("TOML Example", toml.getString("title"));
|
||||
|
||||
Toml owner = toml.getTable("owner");
|
||||
assertEquals("Tom Preston-Werner", owner.getString("name"));
|
||||
assertEquals("GitHub", owner.getString("organization"));
|
||||
assertEquals("GitHub Cofounder & CEO\nLikes tater tots and beer.", owner.getString("bio"));
|
||||
|
||||
Calendar dob = Calendar.getInstance();
|
||||
dob.set(1979, Calendar.MAY, 27, 7, 32, 0);
|
||||
dob.set(Calendar.MILLISECOND, 0);
|
||||
dob.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
assertEquals(dob.getTime(), owner.getDate("dob"));
|
||||
|
||||
Toml database = toml.getTable("database");
|
||||
assertEquals("192.168.1.1", database.getString("server"));
|
||||
assertEquals(5000L, database.getLong("connection_max").longValue());
|
||||
assertTrue(database.getBoolean("enabled"));
|
||||
assertEquals(Arrays.asList(8001L, 8001L, 8002L), database.<Long>getList("ports"));
|
||||
|
||||
Toml servers = toml.getTable("servers");
|
||||
Toml alphaServers = servers.getTable("alpha");
|
||||
assertEquals("10.0.0.1", alphaServers.getString("ip"));
|
||||
assertEquals("eqdc10", alphaServers.getString("dc"));
|
||||
Toml betaServers = servers.getTable("beta");
|
||||
assertEquals("10.0.0.2", betaServers.getString("ip"));
|
||||
assertEquals("eqdc10", betaServers.getString("dc"));
|
||||
assertEquals("中国", betaServers.getString("country"));
|
||||
|
||||
Toml clients = toml.getTable("clients");
|
||||
assertEquals(asList(asList("gamma", "delta"), asList(1L, 2L)), clients.<String>getList("data"));
|
||||
assertEquals(asList("alpha", "omega"), clients.<String>getList("hosts"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_parse_hard_example() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("hard_example.toml").getFile()));
|
||||
|
||||
assertEquals("You'll hate me after this - #", toml.getString("the.test_string"));
|
||||
assertEquals(asList("] ", " # "), toml.<String>getList("the.hard.test_array"));
|
||||
assertEquals(asList("Test #11 ]proved that", "Experiment #9 was a success"), toml.<String>getList("the.hard.test_array2"));
|
||||
assertEquals(" Same thing, but with a string #", toml.getString("the.hard.another_test_string"));
|
||||
assertEquals(" And when \"'s are in the string, along with # \"", toml.getString("the.hard.harder_test_string"));
|
||||
Toml theHardBit = toml.getTable("the.hard.\"bit#\"");
|
||||
assertEquals("You don't think some user won't do that?", theHardBit.getString("\"what?\""));
|
||||
assertEquals(asList("]"), theHardBit.<String>getList("multi_line_array"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void should_parse_current_version_example() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("example-v0.4.0.toml").getFile()));
|
||||
|
||||
assertEquals("value", toml.getString("table.key"));
|
||||
assertEquals("another value", toml.getString("table.subtable.key"));
|
||||
assertNotNull(toml.getTable("x.y.z").getTable("w"));
|
||||
assertEquals("Tom", toml.getString("table.inline.name.first"));
|
||||
assertEquals("Preston-Werner", toml.getString("table.inline.name.last"));
|
||||
assertEquals(1, toml.getLong("table.inline.point.x").intValue());
|
||||
assertEquals(2, toml.getLong("table.inline.point.y").intValue());
|
||||
// assertEquals("pug", toml.getString("dog.tater.type"));
|
||||
assertEquals("I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF.", toml.getString("string.basic.basic"));
|
||||
assertEquals("One\nTwo", toml.getString("string.multiline.key3"));
|
||||
assertEquals(toml.getString("string.multiline.key3"), toml.getString("string.multiline.key1"));
|
||||
assertEquals(toml.getString("string.multiline.key3"), toml.getString("string.multiline.key2"));
|
||||
assertEquals("The quick brown fox jumps over the lazy dog.", toml.getString("string.multiline.continued.key1"));
|
||||
assertEquals("The quick brown fox jumps over the lazy dog.", toml.getString("string.multiline.continued.key2"));
|
||||
assertEquals(toml.getString("string.multilined.singleline.key3"), toml.getString("string.multilined.singleline.key1"));
|
||||
assertEquals(toml.getString("string.multilined.singleline.key3"), toml.getString("string.multilined.singleline.key2"));
|
||||
assertEquals("C:\\Users\\nodejs\\templates", toml.getString("string.literal.winpath"));
|
||||
assertEquals("\\\\ServerX\\admin$\\system32\\", toml.getString("string.literal.winpath2"));
|
||||
assertEquals("Tom \"Dubs\" Preston-Werner", toml.getString("string.literal.quoted"));
|
||||
assertEquals("<\\i\\c*\\s*>", toml.getString("string.literal.regex"));
|
||||
assertEquals("I [dw]on't need \\d{2} apples", toml.getString("string.literal.multiline.regex2"));
|
||||
assertEquals("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", toml.getString("string.literal.multiline.lines"));
|
||||
assertEquals(99, toml.getLong("integer.key1").intValue());
|
||||
assertEquals(42, toml.getLong("integer.key2").intValue());
|
||||
assertEquals(0, toml.getLong("integer.key3").intValue());
|
||||
assertEquals(-17, toml.getLong("integer.key4").intValue());
|
||||
assertEquals(1000, toml.getLong("integer.underscores.key1").intValue());
|
||||
assertEquals(5349221, toml.getLong("integer.underscores.key2").longValue());
|
||||
assertEquals(12345, toml.getLong("integer.underscores.key3").intValue());
|
||||
assertEquals(1.0, toml.getDouble("float.fractional.key1").doubleValue(), 0);
|
||||
assertEquals(3.1415, toml.getDouble("float.fractional.key2").doubleValue(), 0);
|
||||
assertEquals(-0.01, toml.getDouble("float.fractional.key3").doubleValue(), 0);
|
||||
assertEquals(5e+22, toml.getDouble("float.exponent.key1").doubleValue(), 0);
|
||||
assertEquals(1e6, toml.getDouble("float.exponent.key2").longValue(), 0);
|
||||
assertEquals(-2E-2, toml.getDouble("float.exponent.key3").doubleValue(), 0);
|
||||
assertEquals(6.626e-34, toml.getDouble("float.both.key").doubleValue(), 0);
|
||||
assertTrue(toml.getBoolean("boolean.True"));
|
||||
assertFalse(toml.getBoolean("boolean.False"));
|
||||
assertThat(toml.<Long>getList("array.key1"), contains(1L, 2L, 3L));
|
||||
assertThat(toml.<String>getList("array.key2"), contains("red", "yellow", "green"));
|
||||
assertEquals(asList(asList(1L, 2L), asList(3L, 4L, 5L)), toml.<List<Long>>getList("array.key3"));
|
||||
assertEquals(asList(asList(1L, 2L), asList("a", "b", "c")), toml.<List<Long>>getList("array.key4"));
|
||||
assertThat(toml.<Long>getList("array.key5"), contains(1L, 2L, 3L));
|
||||
assertThat(toml.<Long>getList("array.key6"), contains(1L, 2L));
|
||||
assertEquals("Hammer", toml.getString("products[0].name"));
|
||||
assertEquals(738594937, toml.getLong("products[0].sku").intValue());
|
||||
assertNotNull(toml.getTable("products[1]"));
|
||||
assertEquals("Nail", toml.getString("products[2].name"));
|
||||
assertEquals(284758393, toml.getLong("products[2].sku").intValue());
|
||||
assertEquals("gray", toml.getString("products[2].color"));
|
||||
assertEquals("apple", toml.getString("fruit[0].name"));
|
||||
assertEquals("red", toml.getString("fruit[0].physical.color"));
|
||||
assertEquals("round", toml.getString("fruit[0].physical.shape"));
|
||||
assertEquals("red delicious", toml.getString("fruit[0].variety[0].name"));
|
||||
assertEquals("granny smith", toml.getString("fruit[0].variety[1].name"));
|
||||
assertEquals("banana", toml.getString("fruit[1].name"));
|
||||
assertEquals("plantain", toml.getString("fruit[1].variety[0].name"));
|
||||
|
||||
Calendar dob = Calendar.getInstance();
|
||||
dob.set(1979, Calendar.MAY, 27, 7, 32, 0);
|
||||
dob.set(Calendar.MILLISECOND, 0);
|
||||
dob.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
assertEquals(dob.getTime(), toml.getDate("datetime.key1"));
|
||||
assertEquals(dob.getTime(), toml.getDate("datetime.key2"));
|
||||
dob.set(Calendar.MILLISECOND, 999);
|
||||
assertEquals(dob.getTime(), toml.getDate("datetime.key3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_allow_keys_with_same_name_in_different_tables() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("should_allow_keys_with_same_name_in_different_tables.toml").getFile()));
|
||||
|
||||
assertTrue(toml.getTable("siteInfo.local.sh").getBoolean("enable"));
|
||||
assertFalse(toml.getTable("siteInfo.localMobile.sh").getBoolean("enable"));
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.moandjiezana.toml.testutils.Utils;
|
||||
|
||||
public class StringTest {
|
||||
|
||||
@Test
|
||||
public void should_get_string() throws Exception {
|
||||
Toml toml = new Toml().read("a = \"a\"");
|
||||
|
||||
assertEquals("a", toml.getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_empty_string() {
|
||||
Toml toml = new Toml().read("a = \"\"");
|
||||
assertEquals("", toml.getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_empty_string_with_trailing_new_line() {
|
||||
Toml toml = new Toml().read("a = \"\"\n");
|
||||
assertEquals("", toml.getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_basic_multiline_string() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_get_basic_multiline_string"));
|
||||
|
||||
assertEquals(toml.getString("ref"), toml.getString("one_line"));
|
||||
assertEquals(toml.getString("ref"), toml.getString("many_lines"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_multiline_string_without_new_lines() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_get_multiline_string_without_new_lines"));
|
||||
|
||||
assertEquals(toml.getString("ref"), toml.getString("multi1"));
|
||||
assertEquals(toml.getString("ref"), toml.getString("multi2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_literal_string() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_get_literal_string"));
|
||||
|
||||
assertEquals("C:\\Users\\nodejs\\templates", toml.getString("winpath"));
|
||||
assertEquals("\\\\ServerX\\admin$\\system32\\", toml.getString("winpath2"));
|
||||
assertEquals("Tom \"Dubs\" Preston-Werner", toml.getString("quoted"));
|
||||
assertEquals("<\\i\\c*\\s*>", toml.getString("regex"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_multiline_literal_string() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_get_multiline_literal_string"));
|
||||
|
||||
assertTrue(toml.getString("empty_line").isEmpty());
|
||||
assertEquals(toml.getString("regex2_ref"), toml.getString("regex2"));
|
||||
assertEquals(toml.getString("lines_ref"), toml.getString("lines"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_special_characters_in_strings() {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("should_support_special_characters_in_strings.toml").getFile()));
|
||||
|
||||
assertEquals("\" \t \n \r \\ \b \f", toml.getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_unicode_characters_in_strings() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("should_support_special_characters_in_strings.toml").getFile()));
|
||||
|
||||
assertEquals("more or less ±", toml.getString("unicode_key"));
|
||||
assertEquals("more or less ±", toml.getString("unicode_key_uppercase"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_reserved_special_character_in_strings() throws Exception {
|
||||
new Toml().read("key=\"\\m\"");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_escaped_slash() throws Exception {
|
||||
new Toml().read("key=\"\\/\"");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_text_after_literal_string() {
|
||||
new Toml().read("a = ' ' jdkf");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_unterminated_literal_string() throws Exception {
|
||||
new Toml().read("a = 'some text");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_multiline_literal_string_with_malformed_comment() throws Exception {
|
||||
new Toml().read("a = '''some\n text\n''\nb = '''1'''");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_unterminated_multiline_literal_string() throws Exception {
|
||||
new Toml().read("a = '''some\n text\n''");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_unterminated_multiline_literal_string_on_single_line() throws Exception {
|
||||
new Toml().read("a = '''some text''");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_text_outside_multiline_string() {
|
||||
new Toml().read("a = \"\"\" \"\"\" jdkf");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_unterminated_multiline_string() throws Exception {
|
||||
new Toml().read("a = \"\"\"some text\"\"");
|
||||
}
|
||||
|
||||
private File file(String file) {
|
||||
return Utils.file(getClass(), file);
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TableArrayTest {
|
||||
|
||||
@Test
|
||||
public void should_parse_table_array() throws Exception {
|
||||
Toml toml = new Toml().read(file("products_table_array"));
|
||||
|
||||
List<Toml> products = toml.getTables("products");
|
||||
|
||||
assertEquals(3, products.size());
|
||||
|
||||
assertEquals("Hammer", products.get(0).getString("name"));
|
||||
assertEquals(738594937L, products.get(0).getLong("sku").longValue());
|
||||
|
||||
Assert.assertNull(products.get(1).getString("name"));
|
||||
assertNull(products.get(1).getLong("sku"));
|
||||
|
||||
assertEquals("Nail", products.get(2).getString("name"));
|
||||
assertEquals(284758393L, products.get(2).getLong("sku").longValue());
|
||||
assertEquals("gray", products.get(2).getString("color"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_parse_table_array_out_of_order() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_parse_table_array_out_of_order"));
|
||||
|
||||
List<Toml> tables = toml.getTables("product");
|
||||
List<Toml> employees = toml.getTables("employee");
|
||||
|
||||
assertThat(tables, hasSize(2));
|
||||
assertThat(tables.get(0).getDouble("price"), equalTo(9.99));
|
||||
assertThat(tables.get(1).getString("type"), equalTo("ZX80"));
|
||||
assertThat(employees, hasSize(1));
|
||||
assertThat(employees.get(0).getString("name"), equalTo("Marinus van der Lubbe"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_parse_nested_table_arrays() throws Exception {
|
||||
Toml toml = new Toml().read(file("fruit_table_array"));
|
||||
|
||||
List<Toml> fruits = toml.getTables("fruit");
|
||||
|
||||
assertEquals(2, fruits.size());
|
||||
|
||||
Toml apple = fruits.get(0);
|
||||
assertEquals("apple", apple.getString("name"));
|
||||
assertEquals("red", apple.getTable("physical").getString("color"));
|
||||
assertEquals("round", apple.getTable("physical").getString("shape"));
|
||||
assertEquals(2, apple.getTables("variety").size());
|
||||
|
||||
Toml banana = fruits.get(1);
|
||||
assertEquals("banana", banana.getString("name"));
|
||||
assertEquals(1, banana.getTables("variety").size());
|
||||
assertEquals("plantain", banana.getTables("variety").get(0).getString("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_create_array_ancestors_as_tables() throws Exception {
|
||||
Toml toml = new Toml().read("[[a.b.c]]\n id=3");
|
||||
|
||||
assertEquals(3, toml.getTable("a").getTable("b").getTables("c").get(0).getLong("id").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_navigate_array_with_compound_key() throws Exception {
|
||||
Toml toml = new Toml().read(file("fruit_table_array"));
|
||||
|
||||
List<Toml> appleVarieties = toml.getTables("fruit[0].variety");
|
||||
Toml appleVariety = toml.getTable("fruit[0].variety[1]");
|
||||
String bananaVariety = toml.getString("fruit[1].variety[0].name");
|
||||
|
||||
assertEquals(2, appleVarieties.size());
|
||||
assertEquals("red delicious", appleVarieties.get(0).getString("name"));
|
||||
assertEquals("granny smith", appleVariety.getString("name"));
|
||||
assertEquals("plantain", bananaVariety);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_for_missing_table_array() throws Exception {
|
||||
Toml toml = new Toml().read("[a]");
|
||||
|
||||
assertNull(toml.getTables("b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_for_missing_table_array_with_index() throws Exception {
|
||||
Toml toml = new Toml();
|
||||
|
||||
assertNull(toml.getTable("a[0]"));
|
||||
assertNull(toml.getString("a[0].c"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_for_index_out_of_bounds() throws Exception {
|
||||
Toml toml = new Toml().read("[[a]]\n c = 1");
|
||||
|
||||
assertNull(toml.getTable("a[1]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_repeated_tables() {
|
||||
new Toml().read("[[a]]\n [a.b]\n [[a]]\n [a.b]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_empty_table_array_name() {
|
||||
new Toml().read("[[]]");
|
||||
}
|
||||
|
||||
private File file(String fileName) {
|
||||
return new File(getClass().getResource(fileName + ".toml").getFile());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TableTest {
|
||||
|
||||
@Test
|
||||
public void should_get_table() throws Exception {
|
||||
Toml toml = new Toml().read("[group]\nkey = \"value\"");
|
||||
|
||||
Toml group = toml.getTable("group");
|
||||
|
||||
assertEquals("value", group.getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_value_for_multi_key() throws Exception {
|
||||
Toml toml = new Toml().read("[group]\nkey = \"value\"");
|
||||
|
||||
assertEquals("value", toml.getString("group.key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_value_for_multi_key_with_no_parent_table() throws Exception {
|
||||
Toml toml = new Toml().read("[group.sub]\nkey = \"value\"");
|
||||
|
||||
assertEquals("value", toml.getString("group.sub.key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_table_for_multi_key() throws Exception {
|
||||
Toml toml = new Toml().read("[group]\nother=1\n[group.sub]\nkey = \"value\"");
|
||||
|
||||
assertEquals("value", toml.getTable("group.sub").getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_table_for_multi_key_with_no_parent_table() throws Exception {
|
||||
Toml toml = new Toml().read("[group.sub]\nkey = \"value\"");
|
||||
|
||||
assertEquals("value", toml.getTable("group.sub").getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_value_from_table_with_sub_table() throws Exception {
|
||||
Toml toml = new Toml().read("[a.b]\nc=1\n[a]\nd=2");
|
||||
|
||||
assertEquals(2, toml.getLong("a.d").intValue());
|
||||
assertEquals(1, toml.getTable("a.b").getLong("c").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_get_empty_table() throws Exception {
|
||||
Toml toml = new Toml().read("[a]");
|
||||
assertTrue(toml.getTable("a").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_for_missing_table() throws Exception {
|
||||
assertNull(new Toml().getTable("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_table_name_with_basic_string() {
|
||||
Toml toml = new Toml().read("[\"a\"]\nb = 'b'");
|
||||
|
||||
assertEquals("b", toml.getString("\"a\".b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_table_name_part_with_basic_string() {
|
||||
Toml toml = new Toml().read("[target.\"cfg(unix)\".dependencies]\nb = 'b'");
|
||||
|
||||
assertEquals("b", toml.getString("target.\"cfg(unix)\".dependencies.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_table_name_part_with_whitespace_and_basic_string() {
|
||||
Toml toml = new Toml().read("[ target . \"cfg (unix)\" . dependencies ]\nb = 'b'");
|
||||
|
||||
assertEquals("b", toml.getString("target.\"cfg (unix)\".dependencies.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_table_name_with_literal_string() {
|
||||
Toml toml = new Toml().read("['a']\nb = 'b'");
|
||||
|
||||
assertEquals("b", toml.getString("'a'.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_table_name_part_with_literal_string() {
|
||||
Toml toml = new Toml().read("[target.'cfg(unix)'.dependencies]\nb = 'b'");
|
||||
|
||||
assertEquals("b", toml.getString("target.'cfg(unix)'.dependencies.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_accept_table_name_part_with_whitespace_and_literal_string() {
|
||||
Toml toml = new Toml().read("[target . 'cfg(unix)' . dependencies]\nb = 'b'");
|
||||
|
||||
assertEquals("b", toml.getString("target.'cfg(unix)'.dependencies.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_when_navigating_to_missing_value() throws Exception {
|
||||
Toml toml = new Toml();
|
||||
|
||||
assertNull(toml.getString("a.b"));
|
||||
assertNull(toml.getList("a.b"));
|
||||
assertNull(toml.getTable("a.b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_when_no_value_for_multi_key() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
|
||||
assertNull(toml.getString("group.key"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_table_defined_twice() throws Exception {
|
||||
new Toml().read("[a]\nb=1\n[a]\nc=2");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_illegal_characters_after_table() throws Exception {
|
||||
new Toml().read("[error] if you didn't catch this, your parser is broken");
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class TomlDefaultsTest {
|
||||
|
||||
private Toml defaultToml;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
defaultToml = new Toml().read("a = \"a\"\n [group]\n a=\"a\"\n [[array]]\n b=1\n [[array]]\n b=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fall_back_to_default_value() {
|
||||
Toml toml = new Toml(defaultToml);
|
||||
|
||||
assertEquals("a", toml.getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_use_value_when_present_in_values_and_defaults() {
|
||||
Toml toml = new Toml(defaultToml).read("a = \"b\"");
|
||||
|
||||
assertEquals("b", toml.getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_null_when_no_defaults_for_key() throws Exception {
|
||||
Toml toml = new Toml(defaultToml).read("");
|
||||
|
||||
assertNull(toml.getString("b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fall_back_to_default_with_multi_key() throws Exception {
|
||||
Toml toml = new Toml(defaultToml).read("");
|
||||
|
||||
assertEquals("a", toml.getString("group.a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fall_back_to_table() throws Exception {
|
||||
Toml toml = new Toml(defaultToml).read("");
|
||||
|
||||
assertEquals("a", toml.getTable("group").getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fall_back_to_table_array() throws Exception {
|
||||
Toml toml = new Toml(defaultToml).read("");
|
||||
|
||||
assertThat(toml.getTables("array"), hasSize(2));
|
||||
assertThat(toml.getLong("array[1].b"), Matchers.equalTo(2L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_perform_shallow_merge() throws Exception {
|
||||
Toml toml = new Toml(defaultToml).read("[group]\nb=1\n [[array]]\n b=0");
|
||||
Toml toml2 = new Toml(defaultToml).read("[[array]]\n b=1\n [[array]]\n b=2\n [[array]]\n b=3");
|
||||
|
||||
assertEquals(1, toml.getTable("group").getLong("b").intValue());
|
||||
assertNull(toml.getTable("group").getString("a"));
|
||||
assertThat(toml.getTables("array"), hasSize(1));
|
||||
assertEquals(0, toml.getLong("array[0].b").intValue());
|
||||
assertThat(toml2.getTables("array"), hasSize(3));
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class TomlReadTest {
|
||||
|
||||
@Test
|
||||
public void should_read_input_stream() throws Exception {
|
||||
Toml toml = new Toml().read(getClass().getResourceAsStream("should_load_from_file.toml"));
|
||||
|
||||
assertEquals("value", toml.getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_reader() throws Exception {
|
||||
Toml toml = new Toml().read(new StringReader("key=1"));
|
||||
|
||||
assertEquals(1, toml.getLong("key").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_on_missing_file() throws Exception {
|
||||
try {
|
||||
new Toml().read(new File("missing"));
|
||||
fail("Exception should have been thrown");
|
||||
} catch (RuntimeException e) {
|
||||
assertThat(e.getCause(), instanceOf(FileNotFoundException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_on_io_error() throws Exception {
|
||||
Reader readerThatThrows = new Reader() {
|
||||
|
||||
@Override
|
||||
public int read(char[] cbuf, int off, int len) throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {}
|
||||
};
|
||||
|
||||
try {
|
||||
new Toml().read(readerThatThrows);
|
||||
fail("Exception should have been thrown");
|
||||
} catch (RuntimeException e) {
|
||||
assertThat(e.getCause(), instanceOf(IOException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_toml_without_defaults() {
|
||||
Toml toml1 = new Toml().read("a = 1");
|
||||
Toml toml2 = new Toml().read(toml1);
|
||||
|
||||
assertEquals(toml1.getLong("a"), toml2.getLong("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_read_toml_and_merge_with_defaults() {
|
||||
Toml toml1 = new Toml().read("a = 1\nc = 3\nd = 5");
|
||||
Toml toml2 = new Toml().read("b = 2\nc = 4");
|
||||
Toml mergedToml = new Toml(toml1).read(toml2);
|
||||
|
||||
assertEquals(toml1.getLong("a"), mergedToml.getLong("a"));
|
||||
assertEquals(toml2.getLong("b"), mergedToml.getLong("b"));
|
||||
assertEquals(toml2.getLong("c"), mergedToml.getLong("c"));
|
||||
assertEquals(toml1.getLong("d"), mergedToml.getLong("d"));
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class TomlTest {
|
||||
|
||||
@Rule
|
||||
public final ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void should_return_null_if_no_value_for_key() throws Exception {
|
||||
Toml toml = new Toml().read("");
|
||||
|
||||
assertNull(toml.getString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_load_from_file() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("should_load_from_file.toml").getFile()));
|
||||
|
||||
assertEquals("value", toml.getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_blank_lines() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("should_support_blank_line.toml").getFile()));
|
||||
|
||||
assertEquals(1, toml.getLong("group.key").intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_allow_comment_after_values() throws Exception {
|
||||
Toml toml = new Toml().read(new File(getClass().getResource("should_allow_comment_after_values.toml").getFile()));
|
||||
|
||||
assertEquals(1, toml.getLong("a").intValue());
|
||||
assertEquals(1.1, toml.getDouble("b").doubleValue(), 0);
|
||||
assertEquals("abc", toml.getString("c"));
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.set(2014, Calendar.AUGUST, 4, 13, 47, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
assertEquals(cal.getTime(), toml.getDate("d"));
|
||||
assertThat(toml.<String>getList("e"), Matchers.contains("a", "b"));
|
||||
assertTrue(toml.getBoolean("f"));
|
||||
assertEquals("abc", toml.getString("g"));
|
||||
assertEquals("abc", toml.getString("h"));
|
||||
assertEquals("abc\nabc", toml.getString("i"));
|
||||
assertEquals("abc\nabc", toml.getString("j"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_be_empty_if_no_values() throws Exception {
|
||||
assertTrue(new Toml().isEmpty());
|
||||
assertFalse(new Toml().read("a = 1").isEmpty());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_empty_key_name() throws Exception {
|
||||
new Toml().read(" = 1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_key_name_with_hash() throws Exception {
|
||||
new Toml().read("a# = 1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_on_key_name_starting_with_square_bracket() throws Exception {
|
||||
new Toml().read("[a = 1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_key_is_overwritten_by_table() {
|
||||
new Toml().read("[a]\nb=1\n[a.b]\nc=2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_fail_when_key_in_root_is_overwritten_by_table() throws Exception {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
new Toml().read("a=1\n [a]");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void should_fail_when_key_is_overwritten_by_another_key() {
|
||||
new Toml().read("[fruit]\ntype=\"apple\"\ntype=\"orange\"");
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.moandjiezana.toml.testutils.ExtraPrimitives;
|
||||
import com.moandjiezana.toml.testutils.FruitArray;
|
||||
import com.moandjiezana.toml.testutils.FruitArray.Fruit;
|
||||
import com.moandjiezana.toml.testutils.TomlPrimitives;
|
||||
import com.moandjiezana.toml.testutils.TomlTableArrays;
|
||||
import com.moandjiezana.toml.testutils.TomlTables;
|
||||
|
||||
public class TomlToClassTest {
|
||||
|
||||
@Test
|
||||
public void should_convert_toml_primitives() throws Exception {
|
||||
Toml toml = new Toml().read(file("should_convert_primitive_values.toml"));
|
||||
|
||||
TomlPrimitives values = toml.to(TomlPrimitives.class);
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(1979, Calendar.MAY, 27, 7, 32, 00);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
assertEquals("string", values.string);
|
||||
assertEquals((Long) 123L, values.number);
|
||||
assertEquals(2.1, values.decimal, 0);
|
||||
assertTrue(values.bool);
|
||||
assertEquals(calendar.getTime(), values.date);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_to_non_toml_primitives() throws Exception {
|
||||
ExtraPrimitives extraPrimitives = new Toml().read(file("should_convert_extra_primitives.toml")).to(ExtraPrimitives.class);
|
||||
|
||||
assertEquals("Did not convert table to map", "value", extraPrimitives.group.get("key"));
|
||||
assertEquals("Did not convert double to BigDecimal", BigDecimal.valueOf(1.2), extraPrimitives.bigDecimal);
|
||||
assertEquals("Did not convert integer to BigInteger", BigInteger.valueOf(5), extraPrimitives.bigInteger);
|
||||
assertEquals("Did not convert integer to short", Short.parseShort("3"), extraPrimitives.aShort);
|
||||
assertEquals("Did not convert integer to Integer", Integer.valueOf(7), extraPrimitives.anInteger);
|
||||
assertEquals("Did not convert string to Character", Character.valueOf('u'), extraPrimitives.character);
|
||||
assertEquals("Did not convert string to URL", new URL("http://www.example.com").toString(), extraPrimitives.url.toString());
|
||||
assertEquals("Did not convert string to URI", new URI("http://www.test.com").toString(), extraPrimitives.uri.toString());
|
||||
assertThat(extraPrimitives.set, contains("a", "b"));
|
||||
assertThat(extraPrimitives.strings, arrayContaining("c", "d"));
|
||||
assertEquals("Did not convert string to enum", ElementType.CONSTRUCTOR, extraPrimitives.elementType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_tables() throws Exception {
|
||||
String fileName = "should_convert_tables.toml";
|
||||
Toml toml = new Toml().read(file(fileName));
|
||||
|
||||
TomlTables tomlTables = toml.to(TomlTables.class);
|
||||
|
||||
assertEquals("value1", tomlTables.group1.string);
|
||||
assertEquals("value2", tomlTables.group2.string);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_tables_with_defaults() throws Exception {
|
||||
Toml defaultToml = new Toml().read("[group2]\n string=\"defaultValue2\"\n number=2\n [group3]\n string=\"defaultValue3\"");
|
||||
Toml toml = new Toml(defaultToml).read(file("should_convert_tables.toml"));
|
||||
|
||||
TomlTables tomlTables = toml.to(TomlTables.class);
|
||||
|
||||
assertEquals("value1", tomlTables.group1.string);
|
||||
assertEquals("value2", tomlTables.group2.string);
|
||||
assertNull(tomlTables.group2.number);
|
||||
assertEquals("defaultValue3", tomlTables.group3.string);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_use_defaults() throws Exception {
|
||||
Toml defaults = new Toml().read(file("should_convert_tables.toml"));
|
||||
Toml toml = new Toml(defaults).read("");
|
||||
|
||||
TomlTables tomlTables = toml.to(TomlTables.class);
|
||||
|
||||
assertEquals("value1", tomlTables.group1.string);
|
||||
assertEquals("value2", tomlTables.group2.string);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_ignore_keys_not_in_class() throws Exception {
|
||||
TomlPrimitives tomlPrimitives = new Toml().read("a=1\nstring=\"s\"").to(TomlPrimitives.class);
|
||||
|
||||
assertEquals("s", tomlPrimitives.string);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_table_array() throws Exception {
|
||||
TomlTableArrays toml = new Toml().read(file("should_convert_table_array_to_class.toml")).to(TomlTableArrays.class);
|
||||
|
||||
assertEquals(2, toml.groupers.size());
|
||||
assertEquals("grouper 1", toml.groupers.get(0).string);
|
||||
assertEquals("grouper 2", toml.groupers.get(1).string);
|
||||
|
||||
assertEquals("My Name", toml.name);
|
||||
assertEquals(12, toml.primitives.number.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_convert_fruit_table_array() throws Exception {
|
||||
FruitArray fruitArray = new Toml().read(file("fruit_table_array.toml")).to(FruitArray.class);
|
||||
|
||||
assertEquals(2, fruitArray.fruit.size());
|
||||
Fruit apple = fruitArray.fruit.get(0);
|
||||
assertEquals("apple", apple.name);
|
||||
assertEquals("red", apple.physical.color);
|
||||
assertEquals("round", apple.physical.shape);
|
||||
assertEquals(2, apple.variety.size());
|
||||
assertEquals("red delicious", apple.variety.get(0).get("name"));
|
||||
assertEquals("granny smith", apple.variety.get(1).get("name"));
|
||||
|
||||
Fruit banana = fruitArray.fruit.get(1);
|
||||
assertEquals("banana", banana.name);
|
||||
assertEquals(1, banana.variety.size());
|
||||
assertEquals("plantain", banana.variety.get(0).get("name"));
|
||||
}
|
||||
|
||||
private File file(String fileName) {
|
||||
return new File(getClass().getResource(fileName).getFile());
|
||||
}
|
||||
}
|
|
@ -1,575 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class TomlWriterTest {
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder testDirectory = new TemporaryFolder();
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void should_write_primitive_types() {
|
||||
class TestClass {
|
||||
public String aString = "hello";
|
||||
int anInt = 4;
|
||||
protected float aFloat = 1.23f;
|
||||
private double aDouble = -5.43;
|
||||
final boolean aBoolean = false;
|
||||
static final int aFinalInt = 1; // Should be skipped
|
||||
Date aDate;
|
||||
}
|
||||
|
||||
TestClass o = new TestClass();
|
||||
|
||||
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Africa/Johannesburg"));
|
||||
calendar.set(2015, Calendar.JULY, 1, 11, 5, 30);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
o.aDate = calendar.getTime();
|
||||
|
||||
String output = new TomlWriter().write(o);
|
||||
String expected = "aString = \"hello\"\n" +
|
||||
"anInt = 4\n" +
|
||||
"aFloat = 1.23\n" +
|
||||
"aDouble = -5.43\n" +
|
||||
"aBoolean = false\n" +
|
||||
"aDate = 2015-07-01T09:05:30Z\n";
|
||||
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
class SubChild {
|
||||
int anInt;
|
||||
}
|
||||
class Child {
|
||||
SubChild subChild;
|
||||
int anInt;
|
||||
}
|
||||
class Parent {
|
||||
Map<String, Object> aMap;
|
||||
Child child;
|
||||
boolean aBoolean;
|
||||
}
|
||||
|
||||
private Parent buildNestedMap() {
|
||||
Parent parent = new Parent();
|
||||
parent.aMap = new LinkedHashMap<String, Object>();
|
||||
parent.aMap.put("foo", 1);
|
||||
parent.aMap.put("bar", "value1");
|
||||
parent.aMap.put("baz.x", true);
|
||||
parent.child = new Child();
|
||||
parent.child.anInt = 2;
|
||||
parent.child.subChild = new SubChild();
|
||||
parent.child.subChild.anInt = 4;
|
||||
parent.aBoolean = true;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_nested_map_with_default_indentation_policy() {
|
||||
String output = new TomlWriter().write(buildNestedMap());
|
||||
String expected = "aBoolean = true\n\n" +
|
||||
"[aMap]\n" +
|
||||
"foo = 1\n" +
|
||||
"bar = \"value1\"\n" +
|
||||
"\"baz.x\" = true\n\n" +
|
||||
"[child]\n" +
|
||||
"anInt = 2\n\n" +
|
||||
"[child.subChild]\n" +
|
||||
"anInt = 4\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_follow_indentation_policy_of_indented_values() {
|
||||
String output = new TomlWriter.Builder().
|
||||
indentValuesBy(2).
|
||||
build().
|
||||
write(buildNestedMap());
|
||||
String expected = "aBoolean = true\n\n" +
|
||||
"[aMap]\n" +
|
||||
" foo = 1\n" +
|
||||
" bar = \"value1\"\n" +
|
||||
" \"baz.x\" = true\n\n" +
|
||||
"[child]\n" +
|
||||
" anInt = 2\n\n" +
|
||||
"[child.subChild]\n" +
|
||||
" anInt = 4\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_follow_indentation_policy_of_indented_tables() {
|
||||
String output = new TomlWriter.Builder().
|
||||
indentTablesBy(2).
|
||||
build().
|
||||
write(buildNestedMap());
|
||||
String expected = "aBoolean = true\n\n" +
|
||||
"[aMap]\n" +
|
||||
"foo = 1\n" +
|
||||
"bar = \"value1\"\n" +
|
||||
"\"baz.x\" = true\n\n" +
|
||||
"[child]\n" +
|
||||
"anInt = 2\n\n" +
|
||||
" [child.subChild]\n" +
|
||||
" anInt = 4\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_follow_indentation_policy_of_indented_tables_and_values() {
|
||||
String output = new TomlWriter.Builder().
|
||||
indentValuesBy(2).
|
||||
indentTablesBy(2).
|
||||
build().
|
||||
write(buildNestedMap());
|
||||
String expected = "aBoolean = true\n\n" +
|
||||
"[aMap]\n" +
|
||||
" foo = 1\n" +
|
||||
" bar = \"value1\"\n" +
|
||||
" \"baz.x\" = true\n\n" +
|
||||
"[child]\n" +
|
||||
" anInt = 2\n\n" +
|
||||
" [child.subChild]\n" +
|
||||
" anInt = 4\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_array_of_tables_from_object() {
|
||||
class Table {
|
||||
int anInt;
|
||||
|
||||
Table(int anInt) {
|
||||
this.anInt = anInt;
|
||||
}
|
||||
}
|
||||
class Config {
|
||||
Table[] table = new Table[]{new Table(1), new Table(2)};
|
||||
List<Table> table2 = Arrays.asList(new Table(3), new Table(4));
|
||||
}
|
||||
Config config = new Config();
|
||||
|
||||
String output = new TomlWriter().write(config);
|
||||
String expected = "[[table]]\n" +
|
||||
"anInt = 1\n\n" +
|
||||
"[[table]]\n" +
|
||||
"anInt = 2\n" +
|
||||
"[[table2]]\n" +
|
||||
"anInt = 3\n\n" +
|
||||
"[[table2]]\n" +
|
||||
"anInt = 4\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_array_of_tables_from_map() throws Exception {
|
||||
List<Map<String, Object>> maps = new ArrayList<Map<String,Object>>();
|
||||
|
||||
HashMap<String, Object> item1 = new HashMap<String, Object>();
|
||||
item1.put("anInt", 1L);
|
||||
HashMap<String, Object> item2 = new HashMap<String, Object>();
|
||||
item2.put("anInt", 2L);
|
||||
|
||||
maps.add(item1);
|
||||
maps.add(item2);
|
||||
|
||||
Map<String, Object> input = new HashMap<String, Object>();
|
||||
input.put("maps", maps);
|
||||
|
||||
String output = new TomlWriter().write(input);
|
||||
|
||||
String expected = "[[maps]]\n" +
|
||||
"anInt = 1\n\n" +
|
||||
"[[maps]]\n" +
|
||||
"anInt = 2\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_array_of_array() {
|
||||
class ArrayTest {
|
||||
int[][] array = {{1, 2, 3}, {4, 5, 6}};
|
||||
}
|
||||
ArrayTest arrayTest = new ArrayTest();
|
||||
|
||||
String output = new TomlWriter.Builder().padArrayDelimitersBy(1).build().write(arrayTest);
|
||||
String expected = "array = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]\n";
|
||||
assertEquals(expected, output);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_list() {
|
||||
class ListTest {
|
||||
List<Integer> aList = new LinkedList<Integer>();
|
||||
}
|
||||
ListTest o = new ListTest();
|
||||
o.aList.add(1);
|
||||
o.aList.add(2);
|
||||
|
||||
assertEquals("aList = [ 1, 2 ]\n", new TomlWriter.Builder().padArrayDelimitersBy(1).build().write(o));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_zero_length_arrays_and_lists() {
|
||||
class TestClass {
|
||||
List<Integer> aList = new LinkedList<Integer>();
|
||||
Float[] anArray = new Float[0];
|
||||
}
|
||||
assertEquals("aList = []\nanArray = []\n", new TomlWriter().write(new TestClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_reject_heterogeneous_arrays() {
|
||||
class BadArray {
|
||||
Object[] array = new Object[2];
|
||||
}
|
||||
BadArray badArray = new BadArray();
|
||||
badArray.array[0] = new Integer(1);
|
||||
badArray.array[1] = "oops";
|
||||
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(Matchers.startsWith("array"));
|
||||
|
||||
new TomlWriter().write(badArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_reject_nested_heterogeneous_array() {
|
||||
class BadArray {
|
||||
Map<String, Object> aMap = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
BadArray badArray = new BadArray();
|
||||
badArray.aMap.put("array", new Object[] { Integer.valueOf(1), "oops" });
|
||||
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage("aMap.array");
|
||||
|
||||
new TomlWriter().write(badArray);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_elide_empty_intermediate_tables() {
|
||||
class C {
|
||||
int anInt = 1;
|
||||
}
|
||||
class B {
|
||||
C c = new C();
|
||||
}
|
||||
class A {
|
||||
B b = new B();
|
||||
}
|
||||
|
||||
assertEquals("[b.c]\nanInt = 1\n", new TomlWriter().write(new A()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_map() throws Exception {
|
||||
assertEquals("a = 1\n", new TomlWriter().write(new Toml().read("a = 1").toMap()));
|
||||
}
|
||||
|
||||
class Base {
|
||||
protected int anInt = 2;
|
||||
}
|
||||
class Impl extends Base {
|
||||
boolean aBoolean = true;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_classes_with_inheritance() {
|
||||
Impl impl = new Impl();
|
||||
String expected = "aBoolean = true\nanInt = 2\n";
|
||||
assertEquals(expected, new TomlWriter().write(impl));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_strings_to_toml_utf8() throws UnsupportedEncodingException {
|
||||
class Utf8Test {
|
||||
String input;
|
||||
}
|
||||
|
||||
Utf8Test utf8Test = new Utf8Test();
|
||||
utf8Test.input = " é foo \u20AC \b \t \n \f \r \" \\ ";
|
||||
assertEquals("input = \" é foo € \\b \\t \\n \\f \\r \\\" \\\\ \"\n", new TomlWriter().write(utf8Test));
|
||||
|
||||
// Check unicode code points greater than 0XFFFF
|
||||
utf8Test.input = " \uD801\uDC28 \uD840\uDC0B ";
|
||||
assertEquals("input = \" 𐐨 𠀋 \"\n", new TomlWriter().write(utf8Test));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_quote_keys() {
|
||||
Map<String, Integer> aMap = new LinkedHashMap<String, Integer>();
|
||||
aMap.put("a.b", 1);
|
||||
aMap.put("5€", 2);
|
||||
aMap.put("c$d", 3);
|
||||
aMap.put("e/f", 4);
|
||||
|
||||
String expected = "\"a.b\" = 1\n" +
|
||||
"\"5€\" = 2\n" +
|
||||
"\"c$d\" = 3\n" +
|
||||
"\"e/f\" = 4\n";
|
||||
assertEquals(expected, new TomlWriter().write(aMap));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_quote_keys_in_object() throws Exception {
|
||||
class A$ {
|
||||
Double µµ = 5.3;
|
||||
}
|
||||
|
||||
class A {
|
||||
int €5 = 5;
|
||||
String français = "langue";
|
||||
A$ a$ = new A$();
|
||||
}
|
||||
|
||||
assertEquals("\"€5\" = 5\n\"français\" = \"langue\"\n\n[\"a$\"]\n\"µµ\" = 5.3\n", new TomlWriter().write(new A()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_urls() throws Exception {
|
||||
class WithUrl {
|
||||
URL url;
|
||||
URI uri;
|
||||
}
|
||||
|
||||
WithUrl from = new WithUrl();
|
||||
from.url = new URL("https://github.com");
|
||||
from.uri = new URI("https://bitbucket.com");
|
||||
|
||||
String expected = "url = \"https://github.com\"\n"
|
||||
+ "uri = \"https://bitbucket.com\"\n";
|
||||
|
||||
assertEquals(expected, new TomlWriter().write(from));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_enum() throws Exception {
|
||||
class WithEnum {
|
||||
RetentionPolicy retentionPolicy = RetentionPolicy.RUNTIME;
|
||||
}
|
||||
|
||||
assertEquals("retentionPolicy = \"RUNTIME\"\n", new TomlWriter().write(new WithEnum()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_char() throws Exception {
|
||||
class WithChar {
|
||||
char c = 'a';
|
||||
}
|
||||
|
||||
assertEquals("c = \"a\"\n", new TomlWriter().write(new WithChar()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_big_numbers() throws Exception {
|
||||
class WithBigNumbers {
|
||||
BigInteger bigInt = BigInteger.valueOf(1);
|
||||
BigDecimal bigDecimal = BigDecimal.valueOf(2.8);
|
||||
}
|
||||
|
||||
String expected = "bigInt = 1\n"
|
||||
+ "bigDecimal = 2.8\n";
|
||||
|
||||
assertEquals(expected, new TomlWriter().write(new WithBigNumbers()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_handle_wrappers() throws Exception {
|
||||
class WithWrappers {
|
||||
Character c = Character.valueOf('b');
|
||||
Long l = Long.valueOf(2);
|
||||
Double d = Double.valueOf(3.4);
|
||||
}
|
||||
|
||||
String expected = "c = \"b\"\n"
|
||||
+ "l = 2\n"
|
||||
+ "d = 3.4\n";
|
||||
|
||||
assertEquals(expected, new TomlWriter().write(new WithWrappers()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_use_specified_time_zone() throws Exception {
|
||||
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
calendar.set(2015, Calendar.JULY, 1, 11, 5, 30);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
Map<String, Date> o = new HashMap<String, Date>();
|
||||
|
||||
o.put("sast", calendar.getTime());
|
||||
|
||||
TomlWriter writer = new TomlWriter.Builder().
|
||||
timeZone(TimeZone.getTimeZone("Africa/Johannesburg")).
|
||||
build();
|
||||
|
||||
assertEquals("sast = 2015-07-01T13:05:30+02:00\n", writer.write(o));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_show_fractional_seconds() throws Exception {
|
||||
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
calendar.set(2015, Calendar.JULY, 1, 11, 5, 30);
|
||||
calendar.set(Calendar.MILLISECOND, 345);
|
||||
|
||||
Map<String, Date> o = new HashMap<String, Date>();
|
||||
|
||||
o.put("date", calendar.getTime());
|
||||
|
||||
TomlWriter writer = new TomlWriter.Builder().
|
||||
showFractionalSeconds().
|
||||
build();
|
||||
|
||||
assertEquals("date = 2015-07-01T11:05:30.345Z\n", writer.write(o));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_show_fractional_seconds_in_specified_time_zone() throws Exception {
|
||||
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
calendar.set(2015, Calendar.JULY, 1, 11, 5, 30);
|
||||
calendar.set(Calendar.MILLISECOND, 345);
|
||||
|
||||
Map<String, Date> o = new LinkedHashMap<String, Date>();
|
||||
|
||||
o.put("date", calendar.getTime());
|
||||
calendar.set(Calendar.MINUTE, 37);
|
||||
o.put("date2", calendar.getTime());
|
||||
|
||||
TomlWriter writer = new TomlWriter.Builder().
|
||||
timeZone(TimeZone.getTimeZone("Africa/Johannesburg")).
|
||||
showFractionalSeconds().
|
||||
build();
|
||||
|
||||
String expected = "date = 2015-07-01T13:05:30.345+02:00\n"
|
||||
+ "date2 = 2015-07-01T13:37:30.345+02:00\n";
|
||||
|
||||
assertEquals(expected, writer.write(o));
|
||||
}
|
||||
|
||||
private static class SimpleTestClass {
|
||||
int a = 1;
|
||||
}
|
||||
|
||||
private static class TransientClass {
|
||||
int a = 2;
|
||||
transient int b = 3;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_to_writer() throws IOException {
|
||||
StringWriter output = new StringWriter();
|
||||
new TomlWriter().write(new SimpleTestClass(), output);
|
||||
|
||||
assertEquals("a = 1\n", output.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_to_outputstream() throws IOException {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
new TomlWriter().write(new SimpleTestClass(), output);
|
||||
|
||||
assertEquals("a = 1\n", output.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_write_to_file() throws IOException {
|
||||
File output = testDirectory.newFile();
|
||||
new TomlWriter().write(new SimpleTestClass(), output);
|
||||
|
||||
assertEquals("a = 1\n", readFile(output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_skip_transient_fields() throws Exception {
|
||||
String toml = new TomlWriter().write(new TransientClass());
|
||||
|
||||
assertEquals("a = 2\n", toml);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_refuse_to_write_string_fragment() {
|
||||
new TomlWriter().write("fragment");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_refuse_to_write_boolean_fragment() {
|
||||
new TomlWriter().write(true);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_refuse_to_write_number_fragment() {
|
||||
new TomlWriter().write(42);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_refuse_to_write_date_fragment() {
|
||||
new TomlWriter().write(new Date());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_refuse_to_write_array_fragment() {
|
||||
new TomlWriter().write(new int[2]);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void should_refuse_to_write_table_array_fragment() {
|
||||
new TomlWriter().write(new SimpleTestClass[2]);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void should_not_write_list() throws Exception {
|
||||
new TomlWriter().write(Arrays.asList("a"));
|
||||
}
|
||||
|
||||
private String readFile(File input) throws IOException {
|
||||
BufferedReader bufferedReader = new BufferedReader(new FileReader(input));
|
||||
|
||||
try {
|
||||
StringBuilder w = new StringBuilder();
|
||||
String line = bufferedReader.readLine();
|
||||
while (line != null) {
|
||||
w.append(line).append('\n');
|
||||
line = bufferedReader.readLine();
|
||||
}
|
||||
|
||||
return w.toString();
|
||||
} finally {
|
||||
bufferedReader.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class Toml_ToMapTest {
|
||||
|
||||
@Test
|
||||
public void should_convert_simple_values() {
|
||||
Map<String, Object> toml = new Toml().read("a = 1").toMap();
|
||||
|
||||
Assert.assertEquals(Long.valueOf(1), toml.get("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void should_covert_table() throws Exception {
|
||||
Map<String, Object> toml = new Toml().read("c = 2\n [a]\n b = 1").toMap();
|
||||
|
||||
Assert.assertEquals(Long.valueOf(1), ((Map<String, Object>) toml.get("a")).get("b"));
|
||||
Assert.assertEquals(Long.valueOf(2), toml.get("c"));
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.moandjiezana.toml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class UnicodeTest {
|
||||
|
||||
@Test
|
||||
public void should_support_short_escape_form() throws Exception {
|
||||
Toml toml = new Toml().read("key = \"Jos\u00E9\\nLocation\tSF\"");
|
||||
|
||||
assertEquals("José\nLocation\tSF", toml.getString("key"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_support_unicode_literal() throws Exception {
|
||||
Toml toml = new Toml().read("key = \"José LöcÄtion SF\"");
|
||||
|
||||
assertEquals("José LöcÄtion SF", toml.getString("key"));
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package com.moandjiezana.toml.testutils;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ExtraPrimitives {
|
||||
|
||||
public Map<String, Object> group;
|
||||
public BigDecimal bigDecimal;
|
||||
public BigInteger bigInteger;
|
||||
public short aShort;
|
||||
public Integer anInteger;
|
||||
public Character character;
|
||||
public ElementType elementType;
|
||||
public URL url;
|
||||
public URI uri;
|
||||
public Set<String> set;
|
||||
public String[] strings;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package com.moandjiezana.toml.testutils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FruitArray {
|
||||
|
||||
public static class Fruit {
|
||||
public String name;
|
||||
public Physical physical;
|
||||
public List<Map<String, String>> variety;
|
||||
}
|
||||
|
||||
public static class Physical {
|
||||
public String color;
|
||||
public String shape;
|
||||
}
|
||||
|
||||
public List<Fruit> fruit;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package com.moandjiezana.toml.testutils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class TomlPrimitives {
|
||||
|
||||
public String string;
|
||||
public Long number;
|
||||
public Double decimal;
|
||||
public Boolean bool;
|
||||
public Date date;
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.moandjiezana.toml.testutils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TomlTableArrays {
|
||||
|
||||
public List<TomlPrimitives> groupers;
|
||||
public String name;
|
||||
public TomlPrimitives primitives;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package com.moandjiezana.toml.testutils;
|
||||
|
||||
|
||||
public class TomlTables {
|
||||
|
||||
public TomlPrimitives group1;
|
||||
public TomlPrimitives group2;
|
||||
public TomlPrimitives group3;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.moandjiezana.toml.testutils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static File file(Class<?> aClass, String file) {
|
||||
return new File(aClass.getResource(file + ".toml").getFile());
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
list = ["a", "b", "c"]
|
|
@ -1 +0,0 @@
|
|||
long = 2
|
|
@ -1,7 +0,0 @@
|
|||
a = "a"
|
||||
b = [1, 2, 3]
|
||||
|
||||
[c]
|
||||
d = true
|
||||
|
||||
[[e]]
|
|
@ -1 +0,0 @@
|
|||
table = { a = "a" }
|
|
@ -1,3 +0,0 @@
|
|||
[[table_array]]
|
||||
|
||||
[[table_array]]
|
|
@ -1 +0,0 @@
|
|||
arrays-and-ints = [1, ["Arrays are not integers."]]
|
|
@ -1 +0,0 @@
|
|||
ints-and-floats = [1, 1.1]
|
|
@ -1 +0,0 @@
|
|||
strings-and-ints = ["hi", 42]
|
|
@ -1 +0,0 @@
|
|||
no-leads = 1987-7-05T17:45:00Z
|
|
@ -1 +0,0 @@
|
|||
no-secs = 1987-07-05T17:45Z
|
|
@ -1 +0,0 @@
|
|||
no-t = 1987-07-0517:45:00Z
|
|
@ -1 +0,0 @@
|
|||
no-z = 1987-07-05T17:45:00
|
|
@ -1 +0,0 @@
|
|||
with-milli = 1987-07-5T17:45:00.12Z
|
|
@ -1,5 +0,0 @@
|
|||
[fruit]
|
||||
type = "apple"
|
||||
|
||||
[fruit.type]
|
||||
apple = "yes"
|
|
@ -1,2 +0,0 @@
|
|||
dupe = false
|
||||
dupe = true
|
|
@ -1,2 +0,0 @@
|
|||
[a]
|
||||
[a]
|
|
@ -1 +0,0 @@
|
|||
[naughty..naughty]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue