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

io.polaris.core.converter.MapConverter Maven / Gradle / Ivy

There is a newer version: 3.2.1
Show newest version
package io.polaris.core.converter;

import io.polaris.core.json.JsonSerializer;
import io.polaris.core.lang.JavaType;
import io.polaris.core.lang.TypeRef;
import io.polaris.core.lang.Types;
import io.polaris.core.lang.bean.Beans;
import io.polaris.core.lang.copier.Copiers;
import io.polaris.core.lang.copier.CopyOptions;
import io.polaris.core.reflect.Reflects;
import io.polaris.core.service.StatefulServiceLoader;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author Qt
 * @since 1.8
 */
public class MapConverter extends AbstractConverter> {
	/** Map类型 */
	private final JavaType> mapType;
	/** 键类型 */
	private final JavaType keyType;
	/** 值类型 */
	private final JavaType valueType;

	public MapConverter(JavaType> mapType) {
		this(mapType, JavaType.of(mapType.getActualType(Map.class, 0)),
			JavaType.of(mapType.getActualType(Map.class, 1)));
	}

	public MapConverter(Type mapType) {
		this(JavaType.of(mapType));
	}

	public MapConverter(JavaType> mapType, JavaType keyType, JavaType valueType) {
		this.mapType = mapType;
		this.keyType = keyType == null ? (JavaType) JavaType.of(Object.class) : keyType;
		this.valueType = valueType == null ? (JavaType) JavaType.of(Object.class) : valueType;
	}


	@Override
	public JavaType> getTargetType() {
		return this.mapType;
	}

	@Override
	protected  Map doConvert(S value, JavaType> targetType, JavaType sourceType) {
		if (this.mapType.getRawClass().isAssignableFrom(sourceType.getRawClass())) {
			boolean matchKeyType = false, matchValueType = false;
			{
				Type sourceKeyType = sourceType.getActualType(Map.class, 0);
				if (sourceKeyType instanceof Class) {
					if (this.keyType.getRawClass().isAssignableFrom((Class) sourceKeyType)) {
						matchKeyType = true;
					}
				} else if (this.keyType.getRawType() == sourceKeyType) {
					matchKeyType = true;
				}
			}
			{
				Type sourceValueType = sourceType.getActualType(Map.class, 1);
				if (sourceValueType instanceof Class) {
					if (this.valueType.getRawClass().isAssignableFrom((Class) sourceValueType)) {
						matchValueType = true;
					}
				} else if (this.valueType.getRawType() == sourceValueType) {
					matchValueType = true;
				}
			}
			if (matchKeyType && matchValueType) {
				// 元素泛型匹配
				return (Map) value;
			}
		}

		if (value instanceof Map) {
			Map map;
			try {
				map = (Map) Reflects.newInstanceIfPossible(Types.getClass(mapType));
				if (map == null) {
					map = new HashMap<>();
				}
			} catch (Exception e) {
				map = new HashMap<>();
			}
			convertMapToMap((Map) value, map);
			return map;
		} else if (Beans.isBeanClass(value.getClass())) {
			LinkedHashMap tmp = Copiers.copy(value, new LinkedHashMap<>(), CopyOptions.create().ignoreNull(false));
			// 二次转换,转换键值类型
			return doConvert(tmp, targetType, JavaType.of(new TypeRef>() {
			}));
		} else if (value instanceof CharSequence) {
			// 扩展json实现,
			Optional optional = StatefulServiceLoader.load(JsonSerializer.class).optionalService();
			if (optional.isPresent()) {
				String json = value.toString();
				return optional.get().deserialize(json, targetType.getRawType());
			}
		}
		throw new ConversionException("源对象类型不支持");
	}

	private void convertMapToMap(Map srcMap, Map targetMap) {
		srcMap.forEach((key, value) -> targetMap.put(Converters.convert(this.keyType, key),
			Converters.convert(this.valueType, value)));
	}
}