diff --git a/ .gitattributes b/.gitattributes
similarity index 100%
rename from .gitattributes
rename to .gitattributes
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 03a79ab..c76377f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -31,10 +31,10 @@ jobs:
timezoneMacos: "Europe/Berlin"
timezoneWindows: "W. Europe Standard Time"
- - name: Set up JDK 21
+ - name: Set up JDK 17
uses: actions/setup-java@v5.2.0
with:
- java-version: '21'
+ java-version: '17'
distribution: 'temurin'
cache: 'gradle'
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5c59197..ab5e93c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -30,10 +30,10 @@ jobs:
echo "gradle.properties criado:"
cat gradle.properties
- - name: Set up JDK 21
+ - name: Set up JDK 17
uses: actions/setup-java@v5.2.0
with:
- java-version: '21'
+ java-version: '17'
distribution: 'temurin'
cache: 'gradle'
diff --git a/.gitignore b/.gitignore
index 93067e6..3512a58 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,4 @@ bin/
### Mac OS ###
.DS_Store
+/.idea/
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b8..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index 5c147d9..0000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-JToon
\ No newline at end of file
diff --git a/.idea/aws.xml b/.idea/aws.xml
deleted file mode 100644
index b63b642..0000000
--- a/.idea/aws.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
deleted file mode 100644
index 9923ee7..0000000
--- a/.idea/dictionaries/project.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- toon
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 2a65317..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 59f0034..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/sonarlint.xml b/.idea/sonarlint.xml
deleted file mode 100644
index c78dfb6..0000000
--- a/.idea/sonarlint.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 03323a5..ed82cd5 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,10 @@ plugins {
id 'maven-publish'
id 'signing'
id 'jacoco'
+ id 'com.github.spotbugs' version '6.0.15'
+ id 'pmd'
+ id 'checkstyle'
+ id 'info.solidsoft.pitest' version '1.19.0-rc.3'
}
group = 'dev.toonformat'
@@ -35,13 +39,105 @@ jacoco {
reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir')
}
+pitest {
+ pitestVersion = '1.17.4'
+ targetClasses = ['dev.toonformat.jtoon.*']
+ targetTests = ['dev.toonformat.jtoon.*']
+ outputFormats = ['XML', 'HTML']
+ mutationThreshold = 70
+ coverageThreshold = 70
+}
+
+spotbugs {
+ toolVersion = '4.9.8'
+ excludeFilter = file('spotbugs-exclude.xml')
+ effort = "max"
+ reportLevel = "low"
+ reportsDir = layout.buildDirectory.dir('spotbugs')
+}
+
+tasks.spotbugsMain {
+ reports {
+ html {
+ required = true
+ outputLocation = file("${spotbugs.reportsDir.get()}/spotbugs-main.html")
+ }
+ xml {
+ required = true
+ outputLocation = file("${spotbugs.reportsDir.get()}/spotbugs-main.xml")
+ }
+ }
+}
+
+tasks.spotbugsTest {
+ reports {
+ html {
+ required = true
+ outputLocation = file("${spotbugs.reportsDir.get()}/spotbugs-test.html")
+ }
+ xml {
+ required = true
+ outputLocation = file("${spotbugs.reportsDir.get()}/spotbugs-test.xml")
+ }
+ }
+ ignoreFailures = true
+}
+
+pmd {
+ toolVersion = '7.0.0'
+ ruleSetFiles = files('pmd-rules.xml')
+ ruleSets = [] // Disable default rulesets, use custom file only
+ consoleOutput = true
+ ignoreFailures = true
+}
+
+tasks.pmdMain {
+ reports {
+ html.required = true
+ xml.required = true
+ }
+}
+
+tasks.pmdTest {
+ ruleSetFiles = files('pmd-rules-test.xml')
+ ignoreFailures = true
+ reports {
+ html.required = true
+ xml.required = true
+ }
+}
+
+checkstyle {
+ toolVersion = '10.12.5'
+ configFile = file('checkstyle.xml')
+ showViolations = true
+ ignoreFailures = true
+}
+
+tasks.checkstyleMain {
+ reports {
+ xml.required = true
+ html.required = true
+ }
+}
+
+tasks.checkstyleTest {
+ enabled = false
+ ignoreFailures = true
+}
+
dependencies {
implementation 'tools.jackson.core:jackson-databind:3.0.4'
implementation 'tools.jackson.module:jackson-module-afterburner:3.0.4'
+ compileOnly 'com.github.spotbugs:spotbugs-annotations:4.9.8'
testImplementation platform('org.junit:junit-bom:6.0.2')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
- testImplementation 'org.awaitility:awaitility:4.2.1'
+ testImplementation 'org.awaitility:awaitility:4.3.0'
+ testImplementation 'org.pitest:pitest-junit5-plugin:1.2.3'
+ testImplementation 'org.openjdk.jmh:jmh-core:1.37'
+ testImplementation 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
+ testAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
}
test {
@@ -79,6 +175,9 @@ jacocoTestCoverageVerification {
}
}
check.dependsOn jacocoTestReport
+check.dependsOn spotbugsMain
+check.dependsOn pmdMain
+check.dependsOn checkstyleMain
tasks.register('generateJavadoc', Javadoc) {
description = 'Generates Javadoc HTML documentation in the docs/javadoc folder'
@@ -100,3 +199,14 @@ tasks.register('specsValidation', Test) {
include '**/ConformanceTest.class'
}
+tasks.register('jmh', JavaExec) {
+ group = 'verification'
+ description = 'Run JMH benchmarks'
+ classpath = configurations.testRuntimeClasspath + sourceSets.test.runtimeClasspath
+ mainClass = 'dev.toonformat.jtoon.JToonBenchmark'
+ workingDir = projectDir
+ doFirst {
+ file('build/jmh-results').mkdirs()
+ }
+}
+
diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100644
index 0000000..b8f2e90
--- /dev/null
+++ b/checkstyle.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pmd-rules-test.xml b/pmd-rules-test.xml
new file mode 100644
index 0000000..2811908
--- /dev/null
+++ b/pmd-rules-test.xml
@@ -0,0 +1,127 @@
+
+
+
+
+ PMD ruleset for JToon project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pmd-rules.xml b/pmd-rules.xml
new file mode 100644
index 0000000..4c41fed
--- /dev/null
+++ b/pmd-rules.xml
@@ -0,0 +1,100 @@
+
+
+
+
+ PMD ruleset for JToon project
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/settings.gradle b/settings.gradle
index 7e825da..4dc8f38 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,15 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenCentral()
+ }
+ resolutionStrategy {
+ eachPlugin {
+ if (requested.id.id == 'info.solidsoft.pitest') {
+ useModule("info.solidsoft.gradle.pitest:gradle-pitest-plugin:${requested.version}")
+ }
+ }
+ }
+}
+
rootProject.name = 'JToon'
\ No newline at end of file
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
new file mode 100644
index 0000000..b9311e6
--- /dev/null
+++ b/spotbugs-exclude.xml
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/dev/toonformat/jtoon/DecodeOptions.java b/src/main/java/dev/toonformat/jtoon/DecodeOptions.java
index 8163247..452676e 100644
--- a/src/main/java/dev/toonformat/jtoon/DecodeOptions.java
+++ b/src/main/java/dev/toonformat/jtoon/DecodeOptions.java
@@ -18,7 +18,7 @@ public record DecodeOptions(
boolean strict,
PathExpansion expandPaths) {
/**
- * Default decoding options: 2 spaces indent, comma delimiter, strict validation, path expansion off
+ * Default decoding options: 2 spaces indent, comma delimiter, strict validation, path expansion off.
*/
public static final DecodeOptions DEFAULT = new DecodeOptions(2, Delimiter.COMMA, true, PathExpansion.OFF);
@@ -35,7 +35,7 @@ public DecodeOptions() {
* @param indent number of spaces per indentation level
* @return a new DecodeOptions instance with the specified indent
*/
- public static DecodeOptions withIndent(int indent) {
+ public static DecodeOptions withIndent(final int indent) {
return new DecodeOptions(indent, Delimiter.COMMA, true, PathExpansion.OFF);
}
@@ -45,7 +45,7 @@ public static DecodeOptions withIndent(int indent) {
* @param delimiter the delimiter to use for tabular arrays and inline primitive arrays
* @return a new DecodeOptions instance with the specified delimiter
*/
- public static DecodeOptions withDelimiter(Delimiter delimiter) {
+ public static DecodeOptions withDelimiter(final Delimiter delimiter) {
return new DecodeOptions(2, delimiter, true, PathExpansion.OFF);
}
@@ -55,7 +55,7 @@ public static DecodeOptions withDelimiter(Delimiter delimiter) {
* @param strict whether to enable strict validation mode
* @return a new DecodeOptions instance with the specified strict mode
*/
- public static DecodeOptions withStrict(boolean strict) {
+ public static DecodeOptions withStrict(final boolean strict) {
return new DecodeOptions(2, Delimiter.COMMA, strict, PathExpansion.OFF);
}
}
diff --git a/src/main/java/dev/toonformat/jtoon/Delimiter.java b/src/main/java/dev/toonformat/jtoon/Delimiter.java
index 4e5ebe0..6825120 100644
--- a/src/main/java/dev/toonformat/jtoon/Delimiter.java
+++ b/src/main/java/dev/toonformat/jtoon/Delimiter.java
@@ -5,24 +5,24 @@
*/
public enum Delimiter {
/**
- * Comma delimiter (,) - default option
+ * Comma delimiter (,) - default option.
*/
COMMA(","),
/**
- * Tab delimiter (\t)
+ * Tab delimiter (\t).
*/
TAB("\t"),
/**
- * Pipe delimiter (|)
+ * Pipe delimiter (|).
*/
PIPE("|");
private final String value;
- Delimiter(String value) {
- this.value = value;
+ Delimiter(final String delimiterValue) {
+ this.value = delimiterValue;
}
/**
@@ -34,6 +34,11 @@ public String toString() {
return value;
}
+
+ /**
+ * Returns the character representation of this delimiter.
+ * @return the character value of this delimiter
+ */
public char getValue() {
return value.charAt(0);
}
diff --git a/src/main/java/dev/toonformat/jtoon/EncodeOptions.java b/src/main/java/dev/toonformat/jtoon/EncodeOptions.java
index 43ae51d..c522826 100644
--- a/src/main/java/dev/toonformat/jtoon/EncodeOptions.java
+++ b/src/main/java/dev/toonformat/jtoon/EncodeOptions.java
@@ -21,9 +21,10 @@ public record EncodeOptions(
KeyFolding flatten,
int flattenDepth) {
/**
- * Default encoding options: 2 spaces indent, comma delimiter, no length marker
+ * Default encoding options: 2 spaces indent, comma delimiter, no length marker.
*/
- public static final EncodeOptions DEFAULT = new EncodeOptions(2, Delimiter.COMMA, false, KeyFolding.OFF, Integer.MAX_VALUE);
+ public static final EncodeOptions DEFAULT = new EncodeOptions(
+ 2, Delimiter.COMMA, false, KeyFolding.OFF, Integer.MAX_VALUE);
/**
* Creates EncodeOptions with default values.
@@ -39,7 +40,7 @@ public EncodeOptions() {
* @param indent number of spaces per indentation level
* @return a new EncodeOptions instance with the specified indent
*/
- public static EncodeOptions withIndent(int indent) {
+ public static EncodeOptions withIndent(final int indent) {
return new EncodeOptions(indent, Delimiter.COMMA, false, KeyFolding.OFF, Integer.MAX_VALUE);
}
@@ -50,7 +51,7 @@ public static EncodeOptions withIndent(int indent) {
* @param delimiter the delimiter to use for tabular arrays and inline primitive arrays
* @return a new EncodeOptions instance with the specified delimiter
*/
- public static EncodeOptions withDelimiter(Delimiter delimiter) {
+ public static EncodeOptions withDelimiter(final Delimiter delimiter) {
return new EncodeOptions(2, delimiter, false, KeyFolding.OFF, Integer.MAX_VALUE);
}
@@ -61,7 +62,7 @@ public static EncodeOptions withDelimiter(Delimiter delimiter) {
* @param lengthMarker whether to include the # marker before array lengths
* @return a new EncodeOptions instance with the specified length marker setting
*/
- public static EncodeOptions withLengthMarker(boolean lengthMarker) {
+ public static EncodeOptions withLengthMarker(final boolean lengthMarker) {
return new EncodeOptions(2, Delimiter.COMMA, lengthMarker, KeyFolding.OFF, Integer.MAX_VALUE);
}
@@ -72,18 +73,19 @@ public static EncodeOptions withLengthMarker(boolean lengthMarker) {
* @param flatten optional flag to flatten nested objects to a single level.
* @return a new EncodeOptions instance with the flatten setting
*/
- public static EncodeOptions withFlatten(boolean flatten) {
- return new EncodeOptions(2, Delimiter.COMMA, false, flatten ? KeyFolding.SAFE : KeyFolding.OFF, Integer.MAX_VALUE);
+ public static EncodeOptions withFlatten(final boolean flatten) {
+ return new EncodeOptions(2, Delimiter.COMMA, false,
+ flatten ? KeyFolding.SAFE : KeyFolding.OFF, Integer.MAX_VALUE);
}
/**
- * Creates EncodeOptions with custom flatten flag and the depth of to flatten the nested objects, using default indent and
- * delimiter.
+ * Creates EncodeOptions with custom flatten flag and the depth of to flatten
+ * the nested objects, using default indent and delimiter.
*
* @param flattenDepth optional maximum depth to flatten nested objects.
* @return a new EncodeOptions instance with the flatten setting and the depth of to flatten the nested objects.
*/
- public static EncodeOptions withFlattenDepth(int flattenDepth) {
+ public static EncodeOptions withFlattenDepth(final int flattenDepth) {
return new EncodeOptions(2, Delimiter.COMMA, false, KeyFolding.SAFE, flattenDepth);
}
}
diff --git a/src/main/java/dev/toonformat/jtoon/JToon.java b/src/main/java/dev/toonformat/jtoon/JToon.java
index 518de7f..250f730 100644
--- a/src/main/java/dev/toonformat/jtoon/JToon.java
+++ b/src/main/java/dev/toonformat/jtoon/JToon.java
@@ -26,7 +26,7 @@ private JToon() {
* @param input The object to encode (can be null)
* @return The JToon-formatted string
*/
- public static String encode(Object input) {
+ public static String encode(final Object input) {
return encode(input, EncodeOptions.DEFAULT);
}
@@ -42,8 +42,8 @@ public static String encode(Object input) {
* @param options Encoding options (indent, delimiter, length marker)
* @return The JToon-formatted string
*/
- public static String encode(Object input, EncodeOptions options) {
- JsonNode normalizedValue = JsonNormalizer.normalize(input);
+ public static String encode(final Object input, final EncodeOptions options) {
+ final JsonNode normalizedValue = JsonNormalizer.normalize(input);
return ValueEncoder.encodeValue(normalizedValue, options);
}
@@ -60,7 +60,7 @@ public static String encode(Object input, EncodeOptions options) {
* @return The TOON-formatted string
* @throws IllegalArgumentException if the input is not valid JSON
*/
- public static String encodeJson(String json) {
+ public static String encodeJson(final String json) {
return encodeJson(json, EncodeOptions.DEFAULT);
}
@@ -78,8 +78,8 @@ public static String encodeJson(String json) {
* @return The TOON-formatted string
* @throws IllegalArgumentException if the input is not valid JSON
*/
- public static String encodeJson(String json, EncodeOptions options) {
- JsonNode parsed = JsonNormalizer.parse(json);
+ public static String encodeJson(final String json, final EncodeOptions options) {
+ final JsonNode parsed = JsonNormalizer.parse(json);
return ValueEncoder.encodeValue(parsed, options);
}
@@ -96,7 +96,7 @@ public static String encodeJson(String json, EncodeOptions options) {
* @throws IllegalArgumentException if strict mode is enabled and input is
* invalid
*/
- public static Object decode(String toon) {
+ public static Object decode(final String toon) {
return decode(toon, DecodeOptions.DEFAULT);
}
@@ -114,7 +114,7 @@ public static Object decode(String toon) {
* @throws IllegalArgumentException if strict mode is enabled and input is
* invalid
*/
- public static Object decode(String toon, DecodeOptions options) {
+ public static Object decode(final String toon, final DecodeOptions options) {
return ValueDecoder.decode(toon, options);
}
@@ -132,7 +132,7 @@ public static Object decode(String toon, DecodeOptions options) {
* @throws IllegalArgumentException if strict mode is enabled and input is
* invalid
*/
- public static String decodeToJson(String toon) {
+ public static String decodeToJson(final String toon) {
return decodeToJson(toon, DecodeOptions.DEFAULT);
}
@@ -151,7 +151,7 @@ public static String decodeToJson(String toon) {
* @throws IllegalArgumentException if strict mode is enabled and input is
* invalid
*/
- public static String decodeToJson(String toon, DecodeOptions options) {
+ public static String decodeToJson(final String toon, final DecodeOptions options) {
return ValueDecoder.decodeToJson(toon, options);
}
}
diff --git a/src/main/java/dev/toonformat/jtoon/KeyFolding.java b/src/main/java/dev/toonformat/jtoon/KeyFolding.java
index 3189cea..23d8f45 100644
--- a/src/main/java/dev/toonformat/jtoon/KeyFolding.java
+++ b/src/main/java/dev/toonformat/jtoon/KeyFolding.java
@@ -12,7 +12,7 @@ public enum KeyFolding {
SAFE,
/**
- * Off mode: default
+ * Off mode: default.
*/
OFF
}
diff --git a/src/main/java/dev/toonformat/jtoon/decoder/ArrayDecoder.java b/src/main/java/dev/toonformat/jtoon/decoder/ArrayDecoder.java
index 8d992df..4c4accf 100644
--- a/src/main/java/dev/toonformat/jtoon/decoder/ArrayDecoder.java
+++ b/src/main/java/dev/toonformat/jtoon/decoder/ArrayDecoder.java
@@ -1,12 +1,10 @@
package dev.toonformat.jtoon.decoder;
import dev.toonformat.jtoon.Delimiter;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
-
import static dev.toonformat.jtoon.util.Constants.BACKSLASH;
import static dev.toonformat.jtoon.util.Constants.COLON;
import static dev.toonformat.jtoon.util.Constants.DOUBLE_QUOTE;
@@ -19,6 +17,8 @@
*/
public final class ArrayDecoder {
+ private static final int DELIMITER_GROUP_INDEX = 3;
+
private ArrayDecoder() {
throw new UnsupportedOperationException("Utility class cannot be instantiated");
}
@@ -32,8 +32,8 @@ private ArrayDecoder() {
* @param context decode an object to deal with lines, delimiter and options
* @return parsed array with delimiter
*/
- static List