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

se.fortnox.reactivewizard.db.deserializing.DeserializerUtil Maven / Gradle / Ivy

There is a newer version: 24.6.0
Show newest version
package se.fortnox.reactivewizard.db.deserializing;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import se.fortnox.reactivewizard.json.JsonDeserializerFactory;
import se.fortnox.reactivewizard.util.CamelSnakeConverter;
import se.fortnox.reactivewizard.util.PropertyResolver;
import se.fortnox.reactivewizard.util.ReflectionUtil;

import java.lang.reflect.Type;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;

class DeserializerUtil {
    private static final Logger                  LOG                       = LoggerFactory.getLogger(DeserializerUtil.class);
    private static final JsonDeserializerFactory JSON_DESERIALIZER_FACTORY = new JsonDeserializerFactory();

    static  Map createPropertyDeserializers(Class cls, ResultSetMetaData metaData,
        BiFunction, Deserializer, T> deserializerFactory
    ) throws SQLException {
        Map propertyDeserializers = new LinkedHashMap<>();

        String[] columns = extractColumnLabels(metaData);
        for (int i = 0; i < columns.length; i++) {
            String   column       = columns[i];
            String   propertyName = CamelSnakeConverter.snakeToCamel(column);
            String[] propertyPath = propertyName.split("\\.");

            Optional propertyResolver = ReflectionUtil.getPropertyResolver(cls, propertyPath);
            if (propertyResolver.isPresent()) {
                T propertyDeserializer = createPropertyDeserializer((PropertyResolver) propertyResolver.get(), metaData, i + 1, deserializerFactory);
                propertyDeserializers.put(propertyPath, propertyDeserializer);
            } else {
                LOG.warn("Tried to deserialize column " + column + ", but found no matching property named " + propertyName + " in " + cls.getSimpleName());
            }
        }
        return Collections.unmodifiableMap(propertyDeserializers);
    }

    private static  T createPropertyDeserializer(PropertyResolver propertyResolver, ResultSetMetaData metaData,
        int columnIndex, BiFunction, Deserializer, T> deserializerFactory
    ) throws SQLException {
        Class type       = propertyResolver.getPropertyType();
        int      columnType = metaData.getColumnType(columnIndex);

        Deserializer simpleProp = ColumnDeserializerFactory.getColumnDeserializer(type, columnType, columnIndex);
        if (simpleProp == null) {
            return jsonPropertyDeserializer(propertyResolver, columnIndex, deserializerFactory);
        }

        return deserializerFactory.apply(propertyResolver, simpleProp);
    }

    private static  T jsonPropertyDeserializer(PropertyResolver propertyResolver,
        int columnIndex,
        BiFunction, Deserializer, T> deserializerFactory
    ) {
        Type propertyGenericType = propertyResolver.getPropertyGenericType();
        Function deserializer = JSON_DESERIALIZER_FACTORY.createDeserializer(propertyGenericType);

        return deserializerFactory.apply(propertyResolver, (rs) -> {
            String columnValue = rs.getString(columnIndex);
            if (columnValue == null) {
                return Optional.empty();
            }
            Object value       = deserializer.apply(columnValue);
            return Optional.ofNullable(value);
        });
    }

    private static String[] extractColumnLabels(ResultSetMetaData metaData) throws SQLException {
        String[] columnLabels = new String[metaData.getColumnCount()];
        for (int i = 0; i < columnLabels.length; i++) {
            columnLabels[i] = metaData.getColumnLabel(i + 1);
        }
        return columnLabels;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy