diff --git a/.gitignore b/.gitignore index 4a4dbd2..5da8d43 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,27 @@ /.idea/ /target/ /mapneat.iml + +logs/ + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Gradle Patch ### +**/build/ + +# End of https://www.toptal.com/developers/gitignore/api/gradle \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..da9702f --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/gradlew @@ -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 + ;; + 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" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -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 diff --git a/src/main/kotlin/net/andreinc/mapneat/dsl/MapNeat.kt b/src/main/kotlin/net/andreinc/mapneat/dsl/MapNeat.kt index a68b8f7..3a544fb 100644 --- a/src/main/kotlin/net/andreinc/mapneat/dsl/MapNeat.kt +++ b/src/main/kotlin/net/andreinc/mapneat/dsl/MapNeat.kt @@ -1,5 +1,7 @@ package net.andreinc.mapneat.dsl +import com.jayway.jsonpath.Configuration +import net.andreinc.mapneat.config.JsonPathConfiguration import net.andreinc.mapneat.model.MapNeatObjectMap import net.andreinc.mapneat.model.MapNeatSource import net.andreinc.mapneat.operation.* @@ -12,7 +14,7 @@ import kotlin.math.exp * * The MapNeat class extends MapNeatObjectMap which holds internal representation of a JSON as a MutableMap */ -class MapNeat(val inputJson: String, val parentObject: MapNeat? = null, val transformationId : String = UUID.randomUUID().toString()) : MapNeatObjectMap(inputJson), Logging { +class MapNeat(val inputJson: String, val parentObject: MapNeat? = null, val transformationId : String = UUID.randomUUID().toString(), private val jsonPathConfig: Configuration = JsonPathConfiguration.mapNeatConfiguration) : MapNeatObjectMap(inputJson, jsonPathConfig), Logging { fun hasParent() : Boolean { return parentObject != null @@ -162,20 +164,20 @@ class MapNeat(val inputJson: String, val parentObject: MapNeat? = null, val tran return getPrettyString() } - fun json(init: MapNeat.() -> Unit) : Map { - return MapNeat(super.source, this, transformationId) + fun json(init: MapNeat.() -> Unit) : Map { + return MapNeat(super.source, this, transformationId, jsonPathConfig) .apply(init) .getObjectMap() } - fun json(json: String, init: MapNeat.() -> Unit) : Map { - return MapNeat(json, this, transformationId) + fun json(json: String, init: MapNeat.() -> Unit) : Map { + return MapNeat(json, this, transformationId, jsonPathConfig) .apply(init) .getObjectMap() } - fun json(source: MapNeatSource, init: MapNeat.() -> Unit): Map { - return MapNeat(source.content, this, transformationId) + fun json(source: MapNeatSource, init: MapNeat.() -> Unit): Map { + return MapNeat(source.content, this, transformationId, jsonPathConfig) .apply(init) .getObjectMap() } @@ -187,7 +189,17 @@ inline fun json(json: String, init: MapNeat.() -> Unit) : MapNeat { .apply(init) } +inline fun json(json: String, jsonPathConfig: Configuration, init: MapNeat.() -> Unit) : MapNeat { + return MapNeat(json, jsonPathConfig = jsonPathConfig) + .apply(init) +} + inline fun json(source: MapNeatSource, init: MapNeat.() -> Unit) : MapNeat { return MapNeat(source.content) .apply(init) } + +inline fun json(source: MapNeatSource, jsonPathConfig: Configuration, init: MapNeat.() -> Unit) : MapNeat { + return MapNeat(source.content, jsonPathConfig = jsonPathConfig) + .apply(init) +} \ No newline at end of file diff --git a/src/main/kotlin/net/andreinc/mapneat/model/MapNeatObjectMap.kt b/src/main/kotlin/net/andreinc/mapneat/model/MapNeatObjectMap.kt index 48a27d6..4553154 100644 --- a/src/main/kotlin/net/andreinc/mapneat/model/MapNeatObjectMap.kt +++ b/src/main/kotlin/net/andreinc/mapneat/model/MapNeatObjectMap.kt @@ -8,7 +8,7 @@ import net.andreinc.mapneat.config.JsonPathConfiguration.mapNeatConfiguration open class MapNeatObjectMap (val source: String, private val jsonPathConfig : Configuration = mapNeatConfiguration) { - protected val targetMap = LinkedHashMap() + protected val targetMap = LinkedHashMap() protected val sourceCtx: ReadContext = JsonPath.using(jsonPathConfig).parse(source) fun sourceCtx() : ReadContext { @@ -19,7 +19,7 @@ open class MapNeatObjectMap (val source: String, private val jsonPathConfig : Co return JsonPath.using(mapNeatConfiguration).parse(targetMap) } - fun getObjectMap() : Map { + fun getObjectMap() : Map { return targetMap } diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/Assign.kt b/src/main/kotlin/net/andreinc/mapneat/operation/Assign.kt index c6c37ac..1583a49 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/Assign.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/Assign.kt @@ -10,12 +10,12 @@ import org.apache.logging.log4j.kotlin.Logging typealias AssignOperationMethod = () -> Any -class Assign(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : +class Assign(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : Operation(sourceCtx, targetMapRef, transformationId), MappingOperation, Logging { - lateinit var value : Any + var value : Any? = null lateinit var method: AssignOperationMethod override fun doOperation() { @@ -26,16 +26,23 @@ class Assign(sourceCtx: ReadContext, targetMapRef: MutableMap, tran } } - override fun getMappedValue(): Any { - return if (this::value.isInitialized) { - if (value is MapNeatObjectMap) { - (value as MapNeatObjectMap).getObjectMap() + override fun getMappedValue(): Any? { + return if (value != null) { + if (value!! is MapNeatObjectMap) { + (value!! as MapNeatObjectMap).getObjectMap() } else { value } } else if (this::method.isInitialized) { - method() - } else { + try { + method() + } catch (ex: NullPointerException) { + null + } + } else if (value == null) { + null + } + else { throw AssignOperationNotInitialized(fullFieldPath) } } diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/Copy.kt b/src/main/kotlin/net/andreinc/mapneat/operation/Copy.kt index 852a383..d7e86ca 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/Copy.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/Copy.kt @@ -6,7 +6,7 @@ import net.andreinc.mapneat.operation.abstract.Operation import net.andreinc.mapneat.operation.abstract.StructuralOperation import org.apache.logging.log4j.kotlin.Logging -class Copy(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : +class Copy(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : Operation(sourceCtx, targetMapRef, transformationId), StructuralOperation, Logging { diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/Delete.kt b/src/main/kotlin/net/andreinc/mapneat/operation/Delete.kt index 67d63bd..dcedbb3 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/Delete.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/Delete.kt @@ -8,7 +8,7 @@ import org.apache.logging.log4j.kotlin.Logging /** * A transformation that deletes a certain field and all of it's children */ -class Delete(sourceCtx: ReadContext, mapReference: MutableMap, transformationId : String) : +class Delete(sourceCtx: ReadContext, mapReference: MutableMap, transformationId : String) : Operation(sourceCtx, mapReference, transformationId), StructuralOperation, Logging { diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/Move.kt b/src/main/kotlin/net/andreinc/mapneat/operation/Move.kt index d1c91e5..70419fd 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/Move.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/Move.kt @@ -10,7 +10,7 @@ import org.apache.logging.log4j.kotlin.Logging * A transformation that moves a branch from one place to another inside the target output * It can be also used to rename fields */ -class Move(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : +class Move(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : Operation(sourceCtx, targetMapRef, transformationId), StructuralOperation, Logging { diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/Shift.kt b/src/main/kotlin/net/andreinc/mapneat/operation/Shift.kt index d9629cd..2668e50 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/Shift.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/Shift.kt @@ -7,7 +7,7 @@ import net.andreinc.mapneat.operation.abstract.Operation import org.apache.logging.log4j.kotlin.Logging import java.lang.Exception -class Shift(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : +class Shift(sourceCtx: ReadContext, targetMapRef: MutableMap, transformationId : String) : Operation(sourceCtx, targetMapRef, transformationId), MappingOperation, Logging { @@ -21,7 +21,7 @@ class Shift(sourceCtx: ReadContext, targetMapRef: MutableMap, trans } } - override fun getMappedValue(): Any { + override fun getMappedValue(): Any? { if (!this::jsonPath.isInitialized) throw JsonPathNotInitialized(fullFieldPath) val result = if (!this.jsonPath.lenient) { @@ -33,7 +33,9 @@ class Shift(sourceCtx: ReadContext, targetMapRef: MutableMap, trans "" } } - return this.jsonPath.processor(result) + return if (result != null) + this.jsonPath.processor(result) + else null } } diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/abstract/MappingOperation.kt b/src/main/kotlin/net/andreinc/mapneat/operation/abstract/MappingOperation.kt index d350732..0083c2b 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/abstract/MappingOperation.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/abstract/MappingOperation.kt @@ -11,16 +11,16 @@ enum class ArrayChange (val isAffecting: Boolean) { interface MappingOperation { - fun getMappedValue(): Any + fun getMappedValue(): Any? - fun doMappingOperation(current: MutableMap, fieldContext: FieldContext) { + fun doMappingOperation(current: MutableMap, fieldContext: FieldContext) { MappingAction(current, fieldContext, getMappedValue()) .doAction() } } @Suppress("UNCHECKED_CAST") -class MappingAction (val current: MutableMap, val fieldContext: FieldContext, val mappedValue: Any) { +class MappingAction (val current: MutableMap, val fieldContext: FieldContext, val mappedValue: Any?) { private var field: String = fieldContext.name private var arrayChange: ArrayChange = fieldContext.arrayChange @@ -60,7 +60,7 @@ class MappingAction (val current: MutableMap, val fieldContext: Fie } // Transforms current one in a mutable list if needed - private fun currentAsMutableList() : MutableList { + private fun currentAsMutableList() : MutableList { if (!current.containsKey(field)) { // If the current path doesn't exist, create an empty MutableList current[field] = mutableListOf() @@ -81,7 +81,7 @@ class MappingAction (val current: MutableMap, val fieldContext: Fie current[field] = mutableListOf(current[field] as Any) } } - return current[field] as MutableList + return current[field] as MutableList } // Maps a certain value on the selected field from the Field Context diff --git a/src/main/kotlin/net/andreinc/mapneat/operation/abstract/Operation.kt b/src/main/kotlin/net/andreinc/mapneat/operation/abstract/Operation.kt index df3da4e..0577aa1 100644 --- a/src/main/kotlin/net/andreinc/mapneat/operation/abstract/Operation.kt +++ b/src/main/kotlin/net/andreinc/mapneat/operation/abstract/Operation.kt @@ -11,9 +11,9 @@ import java.util.* import kotlin.collections.LinkedHashMap class FieldContext(val path: List, val name: String, val arrayChange: ArrayChange) -typealias FieldAction = (MutableMap, FieldContext) -> Unit +typealias FieldAction = (MutableMap, FieldContext) -> Unit -abstract class Operation(private val sourceCtx: ReadContext, val targetMapRef: MutableMap, val transformationId : String = UUID.randomUUID().toString()) { +abstract class Operation(private val sourceCtx: ReadContext, val targetMapRef: MutableMap, val transformationId : String = UUID.randomUUID().toString()) { companion object { // Mainly used for logging purposes @@ -47,9 +47,9 @@ abstract class Operation(private val sourceCtx: ReadContext, val targetMapRef: M for (e in fullPath) { try { if (!current.containsKey(e)) { - current[e] = LinkedHashMap() + current[e] = LinkedHashMap() } - current = current[e] as MutableMap + current = current[e] as MutableMap } catch (ex: ClassCastException) { throw FieldAlreadyExistsAndNotAnObject(fieldName, fullPath) } diff --git a/src/test/kotlin/net/andreinc/mapneat/MapNeatTest.kt b/src/test/kotlin/net/andreinc/mapneat/MapNeatTest.kt index 1a27934..bddf337 100644 --- a/src/test/kotlin/net/andreinc/mapneat/MapNeatTest.kt +++ b/src/test/kotlin/net/andreinc/mapneat/MapNeatTest.kt @@ -2,12 +2,14 @@ package net.andreinc.mapneat import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectWriter +import com.jayway.jsonpath.Configuration +import net.andreinc.mapneat.config.JsonPathConfiguration import net.andreinc.mapneat.dsl.MapNeat import net.andreinc.mapneat.model.MapNeatSource.Companion.fromJson import net.andreinc.mapneat.model.MapNeatSource.Companion.fromXml import org.skyscreamer.jsonassert.JSONAssert -open class MapNeatTest(private val source: String, private val expected: String, private val init: MapNeat.() -> Unit) { +open class MapNeatTest(private val source: String, private val expected: String, private val config: Configuration, private val init: MapNeat.() -> Unit) { private val writer : ObjectWriter = ObjectMapper().writerWithDefaultPrettyPrinter() @@ -17,11 +19,11 @@ open class MapNeatTest(private val source: String, private val expected: String, const val SOURCE_JSON : String = "/source.json" const val EXPECTED_JSON : String = "/target.json" - fun testFromDirectory(dirName: String, xmlSource : Boolean = false, dslInit: MapNeat.() -> Unit) : MapNeatTest { + fun testFromDirectory(dirName: String, config: Configuration = JsonPathConfiguration.mapNeatConfiguration, xmlSource : Boolean = false, dslInit: MapNeat.() -> Unit) : MapNeatTest { val sourceContent = readFile(dirName + if (xmlSource) SOURCE_XML else SOURCE_JSON) val source = (if (xmlSource) fromXml(sourceContent) else fromJson(sourceContent)).content val expected = readFile(dirName + EXPECTED_JSON) - return MapNeatTest(source, expected, dslInit) + return MapNeatTest(source, expected, config, dslInit) } private fun readFile(fileName: String) : String { @@ -30,7 +32,7 @@ open class MapNeatTest(private val source: String, private val expected: String, } private fun compareExpectedWithActual() { - val actualObject = MapNeat(source).apply(init).getObjectMap() + val actualObject = MapNeat(source, jsonPathConfig = config).apply(init).getObjectMap() val actualJson = writer.writeValueAsString(actualObject) JSONAssert.assertEquals(actualJson, expected, true) } diff --git a/src/test/kotlin/net/andreinc/mapneat/other/config/JsonPathConfigProvidedTest.kt b/src/test/kotlin/net/andreinc/mapneat/other/config/JsonPathConfigProvidedTest.kt new file mode 100644 index 0000000..e3d9765 --- /dev/null +++ b/src/test/kotlin/net/andreinc/mapneat/other/config/JsonPathConfigProvidedTest.kt @@ -0,0 +1,24 @@ +package net.andreinc.mapneat.other.config + +import com.jayway.jsonpath.Option +import net.andreinc.mapneat.MapNeatTest.Companion.testFromDirectory +import net.andreinc.mapneat.config.JsonPathConfiguration +import org.junit.jupiter.api.Test + +class JsonPathConfigProvidedTest { + @Test + fun `Test provided configuration supresses exceptions`() { + val config = JsonPathConfiguration.mapNeatConfiguration.addOptions(Option.SUPPRESS_EXCEPTIONS) + + testFromDirectory("config", config) { + "existing" *= "$.something" + "notExisting" *= "$.something1" + "notExistingToRemove" *= "$.something1" + "notExisting1" /= { sourceCtx().read("$.something1") } + "notExisting1" % "notExisting2" + "notExisting2" %= "notExisting3.subPath" + - "something1" + - "notExistingToRemove" + }.doTest() + } +} \ No newline at end of file diff --git a/src/test/resources/config/source.json b/src/test/resources/config/source.json new file mode 100644 index 0000000..04696b9 --- /dev/null +++ b/src/test/resources/config/source.json @@ -0,0 +1 @@ +{"something": "test"} \ No newline at end of file diff --git a/src/test/resources/config/target.json b/src/test/resources/config/target.json new file mode 100644 index 0000000..2919088 --- /dev/null +++ b/src/test/resources/config/target.json @@ -0,0 +1,8 @@ +{ + "existing" : "test", + "notExisting" : null, + "notExisting1" : null, + "notExisting3" : { + "subPath" : null + } +} \ No newline at end of file