package org.javers.core.metamodel.type;
import org.javers.common.collections.EnumerableFunction;
import org.javers.common.collections.Maps;
import org.javers.common.validation.Validate;
import org.javers.core.metamodel.object.OwnerContext;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* @author bartosz walacik
*/
public class MapType extends KeyValueType {
public MapType(Type baseJavaType) {
super(baseJavaType, 2);
}
@Override
public Object map(Object sourceEnumerable, EnumerableFunction mapFunction, OwnerContext owner) {
return mapStatic(sourceEnumerable, mapFunction, owner);
}
/**
* @return immutable Map
*/
public static Map mapStatic(Object sourceEnumerable, EnumerableFunction mapFunction, OwnerContext owner) {
Validate.argumentsAreNotNull(mapFunction, owner);
Map sourceMap = Maps.wrapNull(sourceEnumerable);
Map targetMap = new HashMap(sourceMap.size());
MapEnumerationOwnerContext enumeratorContext = new MapEnumerationOwnerContext(owner);
mapEntrySet(sourceMap.entrySet(), mapFunction, enumeratorContext, (k,v) -> targetMap.put(k,v));
return Collections.unmodifiableMap(targetMap);
}
/**
* Nulls keys are filtered
*/
@Override
public Object map(Object sourceEnumerable, Function mapFunction) {
Validate.argumentsAreNotNull(mapFunction);
Map sourceMap = Maps.wrapNull(sourceEnumerable);
Map targetMap = new HashMap(sourceMap.size());
mapEntrySetFilterNulls(sourceMap.entrySet(), mapFunction, (k,v) -> targetMap.put(k,v));
return targetMap;
}
@Override
public boolean isEmpty(Object map) {
return map == null || ((Map)map).isEmpty();
}
public static void mapEntrySet(Collection<Map.Entry<?,?>> sourceEntries,
EnumerableFunction mapFunction,
MapEnumerationOwnerContext mapEnumerationContext,
BiConsumer entryConsumer) {
for (Map.Entry entry : sourceEntries) {
//key
mapEnumerationContext.switchToKey();
Object mappedKey = mapFunction.apply(entry.getKey(), mapEnumerationContext);
//value
mapEnumerationContext.switchToValue(mappedKey);
Object mappedValue = mapFunction.apply(entry.getValue(), mapEnumerationContext);
entryConsumer.accept(mappedKey, mappedValue);
}
}
public static void mapEntrySetFilterNulls(Collection<Map.Entry<?,?>> sourceEntries,
Function mapFunction,
BiConsumer entryConsumer) {
for (Map.Entry entry : sourceEntries) {
Object mappedKey = mapFunction.apply(entry.getKey());
if (mappedKey == null) continue;;
Object mappedValue = mapFunction.apply(entry.getValue());
entryConsumer.accept(mappedKey, mappedValue);
}
}
}