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

de.chojo.sadu.mapper.DefaultMapper Maven / Gradle / Ivy

Go to download

SADU module to map values received from a database to java objects using the queries module.

The newest version!
/*
 *     SPDX-License-Identifier: LGPL-3.0-or-later
 *
 *     Copyright (C) RainbowDashLabs and Contributor
 */

package de.chojo.sadu.mapper;

import de.chojo.sadu.core.exceptions.ThrowingBiFunction;
import de.chojo.sadu.core.types.SqlType;
import de.chojo.sadu.mapper.rowmapper.RowMapper;
import de.chojo.sadu.mapper.util.Results;
import de.chojo.sadu.mapper.wrapper.Row;

import java.math.BigDecimal;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import static de.chojo.sadu.mapper.reader.StandardReader.UUID_FROM_BYTES;
import static de.chojo.sadu.mapper.reader.StandardReader.UUID_FROM_STRING;

public final class DefaultMapper {
    private DefaultMapper() {
        throw new UnsupportedOperationException("This is a utility class.");
    }

    public static RowMapper createShort(List types) {
        return create(Short.class, Row::getShort, types);
    }

    public static RowMapper createInteger(List types) {
        return create(Integer.class, Row::getInt, types);
    }

    public static RowMapper createLong(List types) {
        return create(Long.class, Row::getLong, types);
    }

    public static RowMapper createFloat(List types) {
        return create(Float.class, Row::getFloat, types);
    }

    public static RowMapper createDouble(List types) {
        return create(Double.class, Row::getDouble, types);
    }

    public static RowMapper createBigDecimal(List types) {
        return create(BigDecimal.class, Row::getBigDecimal, types);
    }

    public static RowMapper createString(List types) {
        return create(String.class, Row::getString, types);
    }

    public static RowMapper createBoolean(List types) {
        return create(Boolean.class, Row::getBoolean, types);
    }

    public static RowMapper createBytes(List types) {
        return create(Byte[].class, (row, columnIndex) -> convertByteArray(row.getBytes(columnIndex)), types);
    }

    public static RowMapper createUuid(List textTypes, List byteTypes) {
        return RowMapper.forClass(java.util.UUID.class)
                .mapper(row -> {
                    var meta = row.getMetaData();
                    var columnIndexOfType = Results.getFirstColumnIndexOfType(meta, textTypes);
                    if (columnIndexOfType.isPresent()) {
                        return row.get(columnIndexOfType.get(), UUID_FROM_STRING);
                    }
                    columnIndexOfType = Results.getFirstColumnIndexOfType(meta, byteTypes);
                    var index = columnIndexOfType.orElseThrow(() -> {
                        List sqlTypes = new ArrayList<>(textTypes);
                        sqlTypes.addAll(byteTypes);
                        return createException(sqlTypes, meta);
                    });
                    return row.get(index, UUID_FROM_BYTES);
                })
                .build();
    }

    public static  RowMapper create(Class clazz, ThrowingBiFunction mapper, List types) {
        return RowMapper.forClass(clazz)
                .mapper(row -> {
                    var meta = row.getMetaData();
                    var columnIndexOfType = Results.getFirstColumnIndexOfType(meta, types);
                    var index = columnIndexOfType.orElseThrow(() -> createException(types, meta));
                    return mapper.apply(row, index);
                }).build();
    }

    private static SQLException createException(List types, ResultSetMetaData meta) {
        var type = types.stream()
                .map(SqlType::descr)
                .collect(Collectors.joining(", "));
        var available = "error";
        try {
            available = getColumnTypes(meta).entrySet().stream()
                    .map(e -> "%s : %s".formatted(e.getKey(), e.getValue()))
                    .collect(Collectors.joining(", "));
        } catch (SQLException e) {
            // ignore
        }
        return new SQLException("No column of type %s present. Available: %s".formatted(type, available));
    }

    private static Map getColumnTypes(ResultSetMetaData meta) throws SQLException {
        Map columns = new LinkedHashMap<>();
        for (var i = 1; i <= meta.getColumnCount(); i++) {
            columns.put(
                    "%s | %s".formatted(i, meta.getColumnLabel(i)),
                    "%s (%s)".formatted(meta.getColumnTypeName(i), meta.getColumnType(i)));
        }
        return columns;
    }

    private static Byte[] convertByteArray(byte[] primBytes) {
        var bytes = new Byte[primBytes.length];
        Arrays.setAll(bytes, n -> primBytes[n]);
        return bytes;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy