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

com.jnape.palatable.lambda.lens.lenses.OptionalLens Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
package com.jnape.palatable.lambda.lens.lenses;

import com.jnape.palatable.lambda.lens.Lens;

import java.util.Optional;

import static com.jnape.palatable.lambda.lens.Lens.simpleLens;

/**
 * Lenses that operate on {@link Optional}s.
 */
public final class OptionalLens {

    private OptionalLens() {
    }

    /**
     * Convenience static factory method for creating a lens that focuses on a value as an {@link Optional}.
     *
     * @param  the value type
     * @return a lens that focuses on the value as an Optional
     */
    public static  Lens.Simple> asOptional() {
        return simpleLens(Optional::ofNullable, (v, optV) -> optV.orElse(v));
    }

    /**
     * Given a lens and a default S, lift S into Optional.
     *
     * @param lens     the lens
     * @param defaultS the S to use if an empty Optional value is given
     * @param       the type of the "larger" value for reading
     * @param       the type of the "larger" value for putting
     * @param       the type of the "smaller" value that is read
     * @param       the type of the "smaller" update value
     * @return the lens with S lifted
     */
    public static  Lens, T, A, B> liftS(Lens lens, S defaultS) {
        return lens.mapS(optS -> optS.orElse(defaultS));
    }

    /**
     * Given a lens, lift T into Optional.
     *
     * @param lens the lens
     * @param   the type of the "larger" value for reading
     * @param   the type of the "larger" value for putting
     * @param   the type of the "smaller" value that is read
     * @param   the type of the "smaller" update value
     * @return the lens with T lifted
     */
    public static  Lens, A, B> liftT(Lens lens) {
        return lens.mapT(Optional::ofNullable);
    }

    /**
     * Given a lens, lift A into Optional.
     *
     * @param lens the lens
     * @param   the type of the "larger" value for reading
     * @param   the type of the "larger" value for putting
     * @param   the type of the "smaller" value that is read
     * @param   the type of the "smaller" update value
     * @return the lens with A lifted
     */
    public static  Lens, B> liftA(Lens lens) {
        return lens.mapA(Optional::ofNullable);
    }

    /**
     * Given a lens and a default B, lift B into Optional.
     *
     * @param lens     the lens
     * @param defaultB the B to use if an empty Optional value is given
     * @param       the type of the "larger" value for reading
     * @param       the type of the "larger" value for putting
     * @param       the type of the "smaller" value that is read
     * @param       the type of the "smaller" update value
     * @return the lens with B lifted
     */
    public static  Lens> liftB(Lens lens, B defaultB) {
        return lens.mapB(optB -> optB.orElse(defaultB));
    }

    /**
     * Given a lens with S lifted into Optional, flatten S back down.
     *
     * @param lens the lens
     * @param   the type of the "larger" value for reading
     * @param   the type of the "larger" value for putting
     * @param   the type of the "smaller" value that is read
     * @param   the type of the "smaller" update value
     * @return the lens with S flattened
     */
    public static  Lens unLiftS(Lens, T, A, B> lens) {
        return lens.mapS(Optional::ofNullable);
    }

    /**
     * Given a lens with T lifted into Optional and a default T, flatten T back
     * down.
     *
     * @param lens     the lens
     * @param defaultT the T to use if lens produces an empty Optional
     * @param       the type of the "larger" value for reading
     * @param       the type of the "larger" value for putting
     * @param       the type of the "smaller" value that is read
     * @param       the type of the "smaller" update value
     * @return the lens with T flattened
     */
    public static  Lens unLiftT(Lens, A, B> lens, T defaultT) {
        return lens.mapT(optT -> optT.orElse(defaultT));
    }

    /**
     * Given a lens with A lifted into Optional and a default A, flatten A back
     * down.
     *
     * @param lens     the lens
     * @param defaultA the A to use if lens produces an empty Optional
     * @param       the type of the "larger" value for reading
     * @param       the type of the "larger" value for putting
     * @param       the type of the "smaller" value that is read
     * @param       the type of the "smaller" update value
     * @return the lens with A flattened
     */
    public static  Lens unLiftA(Lens, B> lens, A defaultA) {
        return lens.mapA(optA -> optA.orElse(defaultA));
    }

    /**
     * Given a lens with B lifted, flatten B back down.
     *
     * @param lens the lens
     * @param   the type of the "larger" value for reading
     * @param   the type of the "larger" value for putting
     * @param   the type of the "smaller" value that is read
     * @param   the type of the "smaller" update value
     * @return the lens with B flattened
     */
    public static  Lens unLiftB(Lens> lens) {
        return lens.mapB(Optional::ofNullable);
    }
}