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

no.digipost.jdbc.RowMapper Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) Posten Norge AS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package no.digipost.jdbc;

import no.digipost.function.DecaFunction;
import no.digipost.function.HexaFunction;
import no.digipost.function.NonaFunction;
import no.digipost.function.OctoFunction;
import no.digipost.function.PentaFunction;
import no.digipost.function.QuadFunction;
import no.digipost.function.SeptiFunction;
import no.digipost.function.ThrowingFunction;
import no.digipost.function.TriFunction;
import no.digipost.tuple.Tuple;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * Defines how to map a {@link java.sql.ResultSet} to an object.
 * The given {@code ResultSet} is expected to be positioned at the "current" row, i.e. the {@code RowMapper}
 * is not expected to be required to do any cursor placement before doing any value extraction.
 *
 * @param  The type of object this {@code RowMapper} yields from a {@code ResultSet}
 */
@FunctionalInterface
public interface RowMapper {

    static  RowMapper of(ThrowingFunction mapper) {
        return rs -> mapper.apply(rs);
    }


    /**
     * Obtain the result from the current row of a {@code ResultSet}.
     *
     * @param resultSet the {@link ResultSet}
     * @return the result
     *
     * @throws SQLException if any error happens when processing the {@link ResultSet}. May be if the name/label is not valid,
     *                      if a database access error occurs, or this method is called on a closed result set.
     */
    R map(ResultSet resultSet) throws SQLException;


    /**
     * Create a new mapper which takes the result of this mapper and applies
     * the given {@link Function} to yield another result.
     *
     * @param  the output type of the given {@code resultMapper} function,
     *            which also become the type of the result produced by the new
     *            row mapper.
     * @param resultMapper the function to apply to the result
     * @return the new row mapper
     */
    default  RowMapper andThen(Function resultMapper) {
        return rs -> resultMapper.apply(map(rs));
    }


    /**
     * Create a new row mapper which first runs this mapper and then the given mapper, and
     * combines the two results into a tuple-type container.
     *
     * @param otherMapper the mapper to run in addition to this.
     * @return the new mapper
     */
    default  RowMapper.Tupled combinedWith(RowMapper otherMapper) {
        return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
    }




    interface Tupled extends RowMapper> {

        /**
         * Create a new mapper which takes the two results of this mapper and applies
         * the given {@link BiFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(BiFunction resultMapper) {
            return andThen(tu -> resultMapper.apply(tu.first(), tu.second()));
        }

        @Override
        default  RowMapper.Tripled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Tripled extends RowMapper.Tupled, V> {

        /**
         * Create a new mapper which takes the three results of this mapper and applies
         * the given {@link TriFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(TriFunction resultMapper) {
            return andThen(tuv -> {
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second());
            });
        }

        @Override
        default  RowMapper.Quadrupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Quadrupled extends RowMapper.Tripled, V, W> {

        /**
         * Create a new mapper which takes the four results of this mapper and applies
         * the given {@link QuadFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(QuadFunction resultMapper) {
            return andThen(tuvw -> {
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second());
            });
        }

        @Override
        default  RowMapper.Pentupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }


    interface Pentupled extends RowMapper.Quadrupled, V, W, X> {

        /**
         * Create a new mapper which takes the five results of this mapper and applies
         * the given {@link PentaFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(PentaFunction resultMapper) {
            return andThen(tuvwx -> {
                Tuple, V>, W> tuvw = tuvwx.first();
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second(), tuvwx.second());
            });
        }

        @Override
        default  RowMapper.Hextupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Hextupled extends RowMapper.Pentupled, V, W, X, Z> {

        /**
         * Create a new mapper which takes the six results of this mapper and applies
         * the given {@link HexaFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(HexaFunction resultMapper) {
            return andThen(tuvwxz -> {
                Tuple, V>, W>, X> tuvwx = tuvwxz.first();
                Tuple, V>, W> tuvw = tuvwx.first();
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second(), tuvwx.second(), tuvwxz.second());
            });
        }

        @Override
        default  Septupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Septupled extends RowMapper.Hextupled, V, W, X, Z, A> {

        /**
         * Create a new mapper which takes the seven results of this mapper and applies
         * the given {@link SeptiFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(SeptiFunction resultMapper) {
            return andThen(tuvwxza -> {
                Tuple, V>, W>, X>, Z> tuvwxz = tuvwxza.first();
                Tuple, V>, W>, X> tuvwx = tuvwxz.first();
                Tuple, V>, W> tuvw = tuvwx.first();
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second(), tuvwx.second(), tuvwxz.second(), tuvwxza.second());
            });
        }

        @Override
        default  Octupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Octupled extends RowMapper.Septupled, V, W, X, Z, A, B> {

        /**
         * Create a new mapper which takes the eight results of this mapper and applies
         * the given {@link OctoFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(OctoFunction resultMapper) {
            return andThen(tuvwxzab -> {
                Tuple, V>, W>, X>, Z>, A> tuvwxza = tuvwxzab.first();
                Tuple, V>, W>, X>, Z> tuvwxz = tuvwxza.first();
                Tuple, V>, W>, X> tuvwx = tuvwxz.first();
                Tuple, V>, W> tuvw = tuvwx.first();
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second(), tuvwx.second(), tuvwxz.second(), tuvwxza.second(), tuvwxzab.second());
            });
        }

        @Override
        default  Nonupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Nonupled extends RowMapper.Octupled, V, W, X, Z, A, B, C> {

        /**
         * Create a new mapper which takes the nine results of this mapper and applies
         * the given {@link NonaFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(NonaFunction resultMapper) {
            return andThen(tuvwxzabc -> {
                Tuple, V>, W>, X>, Z>, A>, B> tuvwxzab = tuvwxzabc.first();
                Tuple, V>, W>, X>, Z>, A> tuvwxza = tuvwxzab.first();
                Tuple, V>, W>, X>, Z> tuvwxz = tuvwxza.first();
                Tuple, V>, W>, X> tuvwx = tuvwxz.first();
                Tuple, V>, W> tuvw = tuvwx.first();
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second(), tuvwx.second(), tuvwxz.second(), tuvwxza.second(), tuvwxzab.second(), tuvwxzabc.second());
            });
        }

        @Override
        default  Decupled combinedWith(RowMapper otherMapper) {
            return rs -> Tuple.of(this.map(rs), otherMapper.map(rs));
        }

    }

    interface Decupled extends RowMapper.Nonupled, V, W, X, Z, A, B, C, D> {

        /**
         * Create a new mapper which takes the ten results of this mapper and applies
         * the given {@link DecaFunction} to yield another result.
         *
         * @param  the output type of the given {@code resultMapper} function,
         *            which also become the type of the result produced by the new
         *            row mapper.
         * @param resultMapper the function to apply to the result
         * @return the new row mapper
         */
        default  RowMapper andThen(DecaFunction resultMapper) {
            return andThen(tuvwxzabcd -> {
                Tuple, V>, W>, X>, Z>, A>, B>, C> tuvwxzabc = tuvwxzabcd.first();
                Tuple, V>, W>, X>, Z>, A>, B> tuvwxzab = tuvwxzabc.first();
                Tuple, V>, W>, X>, Z>, A> tuvwxza = tuvwxzab.first();
                Tuple, V>, W>, X>, Z> tuvwxz = tuvwxza.first();
                Tuple, V>, W>, X> tuvwx = tuvwxz.first();
                Tuple, V>, W> tuvw = tuvwx.first();
                Tuple, V> tuv = tuvw.first();
                Tuple tu = tuv.first();
                return resultMapper.apply(tu.first(), tu.second(), tuv.second(), tuvw.second(), tuvwx.second(), tuvwxz.second(), tuvwxza.second(), tuvwxzab.second(), tuvwxzabc.second(), tuvwxzabcd.second());
            });
        }

    }


}