package shapes77.util;
// Příliš žluťoučký kůň úpěl ďábelské ó - PŘÍLIŠ ŽLUŤOUČKÝ KŮŇ ÚPĚL ĎÁBELSKÉ Ó

import java.util.function.Supplier;
import java.util.stream.Stream;



/*******************************************************************************
 * Instance interfejsu {@code IStreamable} představují objekty
 * umožňující získat datovod zadaného typu zavoláním jejich metody
 * {@link #stream()}.
 *
 * @param <T> Typ objektů tekoucích získaným datovodem
 */
@FunctionalInterface
public interface IStreamable<T>
{
//\CC== CLASS (STATIC) CONSTANTS ===============================================
//\CM== CLASS (STATIC) METHODS =================================================

    /***************************************************************************
     * Tovární metoda, která vytvoří objekt typu {@link IStreamable}, přičemž
     * pro získání jeho datovodu bude použit tovární objekt zadaný v parametru.
     *
     * @param <T>            Typ objektů tekoucích vytvořeným datovodem
     * @param streamSupplier Tovární objekt vytvářející datovod
     * @return Požadovaný objekt typu {@link IStreamable}
     */
    public static <T> IStreamable<T> get(Supplier<Stream<T>> streamSupplier)
    {
        return new Impl<>(streamSupplier);
    }



//##############################################################################
//\AG== ABSTRACT GETTERS AND SETTERS ===========================================
//\AM== REMAINING ABSTRACT METHODS =============================================

    /***************************************************************************
     * Vrátí datovod sdružený s daným objektem.
     *
     * @return Požadovaný datovod
     */
    public Stream<T> stream();



//\DG== DEFAULT GETTERS AND SETTERS ============================================
//\DM== REMAINING DEFAULT METHODS ==============================================



//##############################################################################
//\NT== NESTED DATA TYPES ======================================================

    /***************************************************************************
     * Pomocná třída umožňující vytvoření objektů typu {@link IStreamable}
     * i z instancí tříd, které toto rozhraní primárně neimplementují,
     * ale mají metodu vracející datovod.
     *
     * @param <E> Typ objektů tekoucích získaným datovodem
     */
    public class Impl<E> implements IStreamable<E>
    {
        /** Tovární metoda sloužící k vytvoření datovodu. */
        private final Supplier<Stream<E>> streamSupplier;


        /***********************************************************************
         * Vytvoří objekt typu {@link IStreamable}, v němž bude datovod
         * získáván prostřednictvím zadané metody.
         *
         * @param streamSupplier Tovární objekt vytvářející požadované datovody
         */
        public Impl(Supplier<Stream<E>> streamSupplier)
        {
            this.streamSupplier = streamSupplier;
        }


        /***********************************************************************
         * Metoda vyžadovaná implementovaným interfejsem
         * a vytvářející datovod sdružený s daným objektem.
         *
         * @return Požadovaný datovod
         */
        @Override
        public Stream<E> stream()
        {
            return streamSupplier.get();
        }
    }
}
