Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.tarantool.driver.mappers.DefaultMessagePackMapper Maven / Gradle / Ivy
Go to download
Tarantool Cartridge driver for Tarantool versions 1.10+ based on Netty framework
package io.tarantool.driver.mappers;
import io.tarantool.driver.api.MessagePackMapperBuilder;
import io.tarantool.driver.exceptions.TarantoolClientException;
import io.tarantool.driver.mappers.converters.ConverterWrapper;
import io.tarantool.driver.mappers.converters.ObjectConverter;
import io.tarantool.driver.mappers.converters.ValueConverter;
import io.tarantool.driver.mappers.converters.object.DefaultListToArrayValueConverter;
import io.tarantool.driver.mappers.converters.object.DefaultMapToMapValueConverter;
import io.tarantool.driver.mappers.converters.value.defaults.DefaultArrayValueToListConverter;
import io.tarantool.driver.mappers.converters.value.defaults.DefaultMapValueToMapConverter;
import io.tarantool.driver.mappers.converters.value.defaults.DefaultNullToNilValueConverter;
import org.msgpack.value.NilValue;
import org.msgpack.value.Value;
import org.msgpack.value.ValueType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import static io.tarantool.driver.mappers.MapperReflectionUtils.getInterfaceParameterClass;
/**
* Default implementation of {@link MessagePackObjectMapper} and {@link MessagePackValueMapper}.
* Deals with standard Java objects
*
* @author Alexey Kuzin
* @author Artyom Dubinin
*/
public class DefaultMessagePackMapper implements MessagePackMapper {
private static final long serialVersionUID = 20220418L;
private final Map>>> valueConverters;
private final Map>>> objectConverters;
private final ObjectConverter nilConverter = new DefaultNullToNilValueConverter();
/**
* Basic constructor
*/
public DefaultMessagePackMapper() {
valueConverters = new HashMap<>();
objectConverters = new HashMap<>();
}
/**
* Copying constructor
*
* @param mapper another mapper instance
*/
public DefaultMessagePackMapper(DefaultMessagePackMapper mapper) {
this();
this.valueConverters.putAll(mapper.valueConverters);
this.objectConverters.putAll(mapper.objectConverters);
}
@SuppressWarnings("unchecked")
private ObjectConverter
getObjectConverter(O o, Function>> getter) {
if (o == null) {
return (ObjectConverter) nilConverter;
}
Optional> converter = findObjectConverter(o.getClass(), getter);
if (!converter.isPresent()) {
throw new MessagePackObjectMapperException("ObjectConverter for type %s is not found", o.getClass());
}
return converter.get();
}
@Override
@SuppressWarnings("unchecked")
public V toValue(O o) {
Function>> getter =
typeName -> objectConverters.getOrDefault(typeName, Collections.emptyList()).stream()
.map(c -> (ObjectConverter) c.getConverter())
.filter(c -> c.canConvertObject(o))
.findFirst();
ObjectConverter converter = getObjectConverter(o, getter);
return converter.toValue(o);
}
@Override
@SuppressWarnings("unchecked")
public O fromValue(V v) {
Function>> getter =
typeName -> valueConverters.getOrDefault(typeName, Collections.emptyList()).stream()
.map(c -> (ValueConverter) c.getConverter())
.filter(c -> c.canConvertValue(v))
.findFirst();
return fromValue(v, getter);
}
@Override
@SuppressWarnings("unchecked")
public O fromValue(V v, Class targetClass) {
Function>> getter =
typeName -> valueConverters.getOrDefault(typeName, Collections.emptyList()).stream()
.filter(c -> checkConverterByTargetType(c.getTargetClass(), targetClass))
.map(c -> (ValueConverter) c.getConverter())
.filter(c -> c.canConvertValue(v))
.findFirst();
return fromValue(v, getter);
}
private O fromValue(V v, Function>> getter) {
Optional> converter = findValueConverter(v.getValueType(), getter);
if (!converter.isPresent()) {
throw new MessagePackValueMapperException("ValueConverter for type %s is not found", v.getClass());
}
return converter.get().fromValue(v);
}
private Optional findObjectConverter(Class> objectClass, Function> getter) {
Optional converter = getter.apply(objectClass.getTypeName());
if (!converter.isPresent() && objectClass.getSuperclass() != null) {
converter = findObjectConverter(objectClass.getSuperclass(), getter);
}
if (!converter.isPresent()) {
for (Class> iface : objectClass.getInterfaces()) {
converter = findObjectConverter(iface, getter);
if (converter.isPresent()) {
break;
}
}
}
return converter;
}
private Optional findValueConverter(ValueType valueType, Function> getter) {
return getter.apply(valueType);
}
/**
* Perform {@link ValueConverter} converter registration. The target object class for registration is determined
* automatically
*
* @param valueType MessagePack source type
* @param converter entity-to-object converter
* @param MessagePack's entity type that the converter accepts and/or returns
* @param java object's type that the converter accepts and/or returns
* @see ValueConverter
*/
public void registerValueConverter(
ValueType valueType,
ValueConverter converter) {
try {
Class objectClass = getInterfaceParameterClass(converter, ValueConverter.class, 1);
registerValueConverter(valueType, objectClass, converter);
} catch (InterfaceParameterClassNotFoundException | InterfaceParameterTypeNotFoundException e) {
throw new TarantoolClientException("Failed to determine the target parameter type of the generic " +
"interface, try to use the method registerValueConverter(valueClass, objectClass, converter) " +
"for registering the converter");
}
}
@Override
public void registerValueConverter(
ValueType valueType,
Class extends O> objectClass,
ValueConverter converter) {
List>> converters =
valueConverters.computeIfAbsent(valueType, k -> new LinkedList<>());
converters.add(0, new ConverterWrapper<>(converter, objectClass));
}
public void registerValueConverterWithoutTargetClass(
ValueType valueType,
ValueConverter converter) {
List>> converters =
valueConverters.computeIfAbsent(valueType, k -> new LinkedList<>());
converters.add(0, new ConverterWrapper<>(converter, Object.class));
}
/**
* Check if the specified converter can convert to the specified object type
*/
private boolean checkConverterByTargetType(Class> targetClassOfConverter, Class> targetClass) {
return targetClassOfConverter.isAssignableFrom(targetClass);
}
@Override
@SuppressWarnings("unchecked")
public Optional> getValueConverter(
ValueType valueType,
Class targetClass) {
Function>> getter =
typeName -> valueConverters.getOrDefault(typeName, Collections.emptyList()).stream()
.filter(c -> checkConverterByTargetType(c.getTargetClass(), targetClass))
.map(c -> (ValueConverter) c.getConverter())
.findFirst();
return findValueConverter(valueType, getter);
}
/**
* Perform {@link ObjectConverter} converter registration. The source object class and target entity class for
* registration are determined automatically
*
* @param converter object-to-entity converter
* @param MessagePack's entity type that the converter accepts and/or returns
* @param java object's type that the converter accepts and/or returns
* @see ObjectConverter
*/
public void registerObjectConverter(ObjectConverter converter) {
try {
registerObjectConverter(
getInterfaceParameterClass(converter, ObjectConverter.class, 0), converter);
} catch (InterfaceParameterClassNotFoundException | InterfaceParameterTypeNotFoundException e) {
throw new TarantoolClientException("Failed to determine the target parameter type of the generic " +
"interface, try to use the method registerObjectConverter(objectClass, valueClass, converter) " +
"for registering the converter");
}
}
/**
* Adds a Java object converter to this mappers instance. The target value class for registration is determined
* automatically
*
* @param objectClass object class to register the converter for
* @param converter entity-to-object converter
* @param the target MessagePack entity type
* @param the source object type
* @see ObjectConverter
*/
public void registerObjectConverter(
Class extends O> objectClass, ObjectConverter converter) {
try {
Class valueClass = getInterfaceParameterClass(converter, ObjectConverter.class, 1);
registerObjectConverter(objectClass, valueClass, converter);
} catch (InterfaceParameterClassNotFoundException | InterfaceParameterTypeNotFoundException e) {
throw new TarantoolClientException("Failed to determine the target parameter type of the generic " +
"interface, try to use the method registerObjectConverter(objectClass, valueClass, converter) " +
"for registering the converter");
}
}
@Override
public void registerObjectConverter(
Class extends O> objectClass,
Class valueClass,
ObjectConverter converter) {
List>> converters =
objectConverters.computeIfAbsent(objectClass.getTypeName(), k -> new LinkedList<>());
converters.add(0, new ConverterWrapper<>(converter, valueClass));
}
@Override
@SuppressWarnings("unchecked")
public Optional> getObjectConverter(
Class objectClass,
Class valueClass) {
Function>> getter =
typeName -> objectConverters.getOrDefault(typeName, Collections.emptyList()).stream()
.filter(c -> checkConverterByTargetType(c.getTargetClass(), valueClass))
.map(c -> (ObjectConverter) c.getConverter())
.findFirst();
return findObjectConverter(objectClass, getter);
}
@Override
public MessagePackMapper copy() {
return new DefaultMessagePackMapper(this);
}
/**
* Builder for {@link DefaultMessagePackMapper}
*/
public static class Builder implements MessagePackMapperBuilder {
private final DefaultMessagePackMapper mapper;
/**
* Basic constructor, initialized with an empty mapper
*/
public Builder() {
mapper = new DefaultMessagePackMapper();
}
/**
* Basic constructor, initialized with the specified mapper
*
* @param mapper a mapper instance
*/
public Builder(DefaultMessagePackMapper mapper) {
this.mapper = new DefaultMessagePackMapper(mapper);
}
@Override
public Builder withDefaultMapValueConverter() {
mapper.registerValueConverter(ValueType.MAP, new DefaultMapValueToMapConverter(mapper));
return this;
}
@Override
public Builder withDefaultMapObjectConverter() {
mapper.registerObjectConverter(new DefaultMapToMapValueConverter(mapper));
Class> cls = (Class>) (Object) HashMap.class;
mapper.registerObjectConverter(cls, new DefaultMapToMapValueConverter(mapper));
return this;
}
@Override
public Builder withDefaultArrayValueConverter() {
mapper.registerValueConverter(ValueType.ARRAY, new DefaultArrayValueToListConverter(mapper));
return this;
}
@Override
public Builder withDefaultListObjectConverter() {
mapper.registerObjectConverter(new DefaultListToArrayValueConverter(mapper));
Class> cls = (Class>) (Object) ArrayList.class;
mapper.registerObjectConverter(cls, new DefaultListToArrayValueConverter(mapper));
return this;
}
@Override
public Builder withValueConverter(ValueType valueType, ValueConverter converter) {
mapper.registerValueConverter(valueType, converter);
return this;
}
@Override
public Builder withValueConverter(
ValueType valueType, Class objectClass,
ValueConverter converter) {
mapper.registerValueConverter(valueType, objectClass, converter);
return this;
}
@Override
public Builder withObjectConverter(ObjectConverter converter) {
mapper.registerObjectConverter(converter);
return this;
}
@Override
public Builder withObjectConverter(Class objectClass, ObjectConverter converter) {
mapper.registerObjectConverter(objectClass, converter);
return this;
}
@Override
public Builder withObjectConverter(
Class objectClass, Class valueClass,
ObjectConverter converter) {
mapper.registerObjectConverter(objectClass, valueClass, converter);
return this;
}
@Override
public DefaultMessagePackMapper build() {
return mapper;
}
}
}