package io.monokkel.core.utils;
import java.util.*;
import static java.util.stream.Collectors.toMap;
/**
* Created by tarjei on 20/09/14.
*/
public class MapTransformation {
/**
*
* A function that transforms a map by utilizing data from a matching map. The target map is filtered and the expressions
* map is sent to the supplied function. The function supports sub-maps i.e. a map within the map. The expression object
* CAN (but do not need to) match this sub-map structure and only expressions in the sub-map will be passed to the function.
*
* Example of mapToBeTransformed in JSON format:
* {
* "key1":"value",
* "key2":{
* "subkey":"value"
* }
* }
*
* Example of corresponding expressions in JSON format:
* {
* "key1":"some transformation value",
* "key2":{
* "subkey":"some transformation value"
* }
* }
*
* The calls to the function object will in this case be:
*
* transform("key1","some transformation value",{"key1":"some transformation value", "key2":{"subkey":"some transformation value"}}
* transform("subkey","some transformation value","subkey":"some transformation value"}
*
* @return a transformed map containing all key values in the original map
*/
public static Map<String, Object> transformAgainstMap(final Map<String, Object> mapToBeTransformed, final Map<String, Object> expressions, final MapTransformationFunction<String,Object> mapTransformationFunction)
{
return mapToBeTransformed.entrySet().stream().collect(toMap(Map.Entry::getKey, entry -> applyOnMap(entry.getKey(), entry.getValue(), expressions, mapTransformationFunction)));
}
@SuppressWarnings("unchecked")
private static Object applyOnMap(String key, Object value, final Map<String, Object> expressionObject, final MapTransformationFunction<String,Object> mapTransformationFunction) {
if (ParserUtils.isAValidJsonBaseType(value)) {
return mapTransformationFunction.transform(key, value, expressionObject);
} else if (value instanceof Map) {
final Map expressionSubObject = (Map) expressionObject.getOrDefault(key, new LinkedHashMap<>());
final Map uncleaned = (Map) value;
return transformAgainstMap(uncleaned, expressionSubObject, mapTransformationFunction);
} else if (value instanceof ArrayList) {
// Not supported yet
return value;
} else {
return value;
}
}
}