All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.codearte.accurest.util.JsonPathJsonConverter.groovy Maven / Gradle / Ivy

package io.codearte.accurest.util

import groovy.json.JsonSlurper
import io.codearte.accurest.dsl.internal.DslProperty
import io.codearte.accurest.dsl.internal.ExecutionProperty

import java.util.regex.Pattern
/**
 * @author Marcin Grzejszczak
 */
class JsonPathJsonConverter {

	private static final Boolean SERVER_SIDE = false
	private static final Boolean CLIENT_SIDE = true

	public static final String ROOT_JSON_PATH_ELEMENT = '$'
	public static final String ALL_ELEMENTS = "[*]"

	public static JsonPaths transformToJsonPathWithTestsSideValues(def json) {
		return transformToJsonPathWithValues(json, SERVER_SIDE)
	}

	public static JsonPaths transformToJsonPathWithStubsSideValues(def json) {
		return transformToJsonPathWithValues(json, CLIENT_SIDE)
	}

	private static JsonPaths transformToJsonPathWithValues(def json, boolean clientSide) {
		if(!json) {
			return new JsonPaths()
		}
		JsonPaths pathsAndValues = [] as Set
		Object convertedJson = getClientOrServerSideValues(json, clientSide)
		traverseRecursivelyForKey(convertedJson, ROOT_JSON_PATH_ELEMENT) { String key, Object value ->
			if (value instanceof ExecutionProperty) {
				return
			}
			JsonPathEntry entry = getValueToInsert(key, value)
			pathsAndValues.add(entry)
		}
		return pathsAndValues
	}

	private static Object getClientOrServerSideValues(json, boolean clientSide) {
		return MapConverter.transformValues(json) {
			boolean dslProp = it instanceof DslProperty
			if (dslProp) {
				DslProperty dslProperty = ((DslProperty) it)
				return clientSide ?
						getClientOrServerSideValues(dslProperty.clientValue, clientSide) : getClientOrServerSideValues(dslProperty.serverValue, clientSide)
			}
			return it
		}
	}

	protected static def traverseRecursively(Class parentType, String key, def value, Closure closure) {
		if (value instanceof String && value) {
			try {
				def json = new JsonSlurper().parseText(value)
				if (json instanceof Map) {
					return convertWithKey(parentType, key, json, closure)
				}
			} catch (Exception ignore) {
				return closure(key, value)
			}
		} else if (isAnEntryWithNonCollectionLikeValue(value)) {
			return convertWithKey(List, key, value as Map, closure)
		} else if (isAnEntryWithoutNestedStructures(value)) {
			return convertWithKey(List, key, value as Map, closure)
		} else if (value instanceof Map) {
			return convertWithKey(Map, key, value as Map, closure)
		} else if (value instanceof List) {
			value.each { def element ->
				traverseRecursively(List, "$key[*]", element, closure)
			}
			return value
		}
		try {
			return closure(key, value)
		} catch (Exception ignore) {
			return value
		}
	}

	private static boolean isAnEntryWithNonCollectionLikeValue(def value) {
		if (!(value instanceof Map)) {
			return false
		}
		Map valueAsMap = ((Map) value)
		boolean mapHasOneEntry = valueAsMap.size() == 1
		if (!mapHasOneEntry) {
			return false
		}
		Object valueOfEntry = valueAsMap.entrySet().first().value
		return !(valueOfEntry instanceof Map || valueOfEntry instanceof List)
	}

	private static boolean isAnEntryWithoutNestedStructures(def value) {
		if (!(value instanceof Map)) {
			return false
		}
		Map valueAsMap = ((Map) value)
		return valueAsMap.entrySet().every { Map.Entry entry ->
			[String, Number].any { entry.value.getClass().isAssignableFrom(it) }
		}
	}

	private static Map convertWithKey(Class parentType, String parentKey, Map map, Closure closureToExecute) {
		return map.collectEntries {
			String entrykey, value ->
				[entrykey, traverseRecursively(parentType, "${parentKey}.${entrykey}", value, closureToExecute)]
		}
	}

	private static void traverseRecursivelyForKey(def json, String rootKey, Closure closure) {
		traverseRecursively(Map, rootKey, json, closure)
	}

	private static JsonPathEntry getValueToInsert(String key, Object value) {
		return convertToListElementFiltering(key, value)
	}

	protected static JsonPathEntry convertToListElementFiltering(String key, Object value) {
		if (key.endsWith(ALL_ELEMENTS)) {
			int lastAllElements = key.lastIndexOf(ALL_ELEMENTS)
			String keyWithoutAllElements = key.substring(0, lastAllElements)
			return JsonPathEntry.simple("""$keyWithoutAllElements[?(@ ${compareWith(value)})]""".toString(), value)
		}
		return getKeyForTraversalOfListWithNonPrimitiveTypes(key, value)
	}

	private static JsonPathEntry getKeyForTraversalOfListWithNonPrimitiveTypes(String key, Object value) {
		int lastDot = key.lastIndexOf('.')
		String keyWithoutLastElement = key.substring(0, lastDot)
		String lastElement = key.substring(lastDot + 1).replaceAll(~/\[\*\]/, "")
		return new JsonPathEntry(
				"""$keyWithoutLastElement[?(@.$lastElement ${compareWith(value)})]""".toString(),
				lastElement,
				value
		)
	}

	protected static String compareWith(Object value) {
		if (value instanceof Pattern) {
			return """=~ /${(value as Pattern).pattern()}/"""
		}
		return """== ${potentiallyWrappedWithQuotesValue(value)}"""
	}

	protected static String potentiallyWrappedWithQuotesValue(Object value) {
		return value instanceof Number ? value : "'$value'"
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy