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

net.sf.staccatocommons.collections.stream.Streams Maven / Gradle / Ivy

/**
 *  Copyright (c) 2011, The Staccato-Commons Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; version 3 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 */

package net.sf.staccatocommons.collections.stream;

import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import net.sf.staccatocommons.collections.restrictions.Projection;
import net.sf.staccatocommons.collections.restrictions.Repeatable;
import net.sf.staccatocommons.collections.stream.impl.CharSequenceStream;
import net.sf.staccatocommons.collections.stream.impl.CollectionStream;
import net.sf.staccatocommons.collections.stream.impl.DequeStream;
import net.sf.staccatocommons.collections.stream.impl.EmptyStream;
import net.sf.staccatocommons.collections.stream.impl.IterableStream;
import net.sf.staccatocommons.collections.stream.impl.IteratorStream;
import net.sf.staccatocommons.collections.stream.impl.ListStream;
import net.sf.staccatocommons.collections.stream.impl.SingleStream;
import net.sf.staccatocommons.collections.stream.impl.internal.UndefinedStream;
import net.sf.staccatocommons.collections.stream.impl.internal.delayed.ConsStream;
import net.sf.staccatocommons.collections.stream.impl.internal.delayed.DelayedSingleStream;
import net.sf.staccatocommons.defs.Applicable;
import net.sf.staccatocommons.defs.Evaluable;
import net.sf.staccatocommons.defs.Thunk;
import net.sf.staccatocommons.iterators.EnumerationIterator;
import net.sf.staccatocommons.iterators.thriter.AbstractThriterator;
import net.sf.staccatocommons.iterators.thriter.NextThriterator;
import net.sf.staccatocommons.lang.predicate.Predicates;
import net.sf.staccatocommons.lang.sequence.Sequence;
import net.sf.staccatocommons.lang.sequence.StopConditions;
import net.sf.staccatocommons.lang.thunk.Thunks;
import net.sf.staccatocommons.restrictions.Conditionally;
import net.sf.staccatocommons.restrictions.Constant;
import net.sf.staccatocommons.restrictions.check.NonNull;
import net.sf.staccatocommons.restrictions.processing.ForceRestrictions;

/**
 * Class methods for creating very simple {@link Stream}s wrapping existing
 * classes from the Java collections framework, specifiying its elements and
 * 
 * @author flbulgarelli
 */
public class Streams {

  private Streams() {}

  /**
   * Creates a new {@link Stream} that retrieves elements from a head's thunk,
   * and another {@link Iterable}, called tail.
   * 
   * This operation is known and cons(tructing), and can be undone by
   * sending {@link Stream#delayedDecons()} to the resulting Stream.
   * 
   * The returned stream is {@link Repeatable} as long as the thunk's head value
   * is always equal, and the tail is repeatable.
   * 
   * @param 
   * @param head
   * @param tail
   * @return a new {@link Stream}
   */
  @Projection
  @Conditionally(Repeatable.class)
  public static  Stream cons(final Thunk head, @NonNull final Stream tail) {
    return new ConsStream(head, (Stream) tail);
  }

  /**
   * Creates a new {@link Stream} that retrieves elements from a head, and
   * another {@link Iterable}, called tail.
   * 
   * This operation is known and cons(tructing), and can be undone by
   * sending {@link Stream#decons()} to the resulting Stream.
   * 
   * * The returned stream is {@link Repeatable} as long as the tail is
   * repeatable.
   * 
   * @param 
   * @param head
   * @param tail
   * @return a new {@link Stream}
   */
  @Projection
  @Conditionally(Repeatable.class)
  public static  Stream cons(final A head, @NonNull final Stream tail) {
    return new ConsStream(Thunks.constant(head), (Stream) tail);
  }

  /**
   * Creates a new {@link Stream} that retrieves the elements from the given
   * array. This stream permits efficient random access and grants repeatable
   * iteration order.
   * 
   * @param 
   *          the element type
   * @param elements
   *          the array that is Stream source
   * @return a new stream that gets its elements from an array
   */
  @Repeatable
  @Projection
  public static  Stream cons(@NonNull A... elements) {
    return from(Arrays.asList(elements));
  }

  /**
   * Creates a one-element new Stream that will retrieve the thunk's value.
   * 
   * This stream is {@link Repeatable} as long as the thunk's value is always
   * equal.
   * 
   * @param 
   * @param element
   * @return a new
   * 
   * @see Thunk#value()
   */
  @Projection
  @Repeatable
  public static  Stream cons(Thunk element) {
    return new DelayedSingleStream(element);
  }

  /**
   * Creates a new Stream that will retrieve just the given element
   * 
   * @param 
   * @param element
   *          the single element the new {@link Stream} will retrieve
   * @return a new {@link Stream}
   */
  @Repeatable
  @Projection
  public static  Stream cons(A element) {
    return new SingleStream(element);
  }

  /**
   * Creates a new infinite {@link Stream} that retrieves element from the
   * sequence
   * Sequence.from(start, generator, StopConditions.stopNever())
   * 
   * @param 
   * @param seed
   *          the initial element of the sequence
   * @param generator
   *          a function used to generated each element from the sequence after
   *          the initial element
   * @return a new {@link Stream}
   * @see Sequence#from(Object, Applicable, Evaluable)
   */
  @Projection
  public static  Stream iterate(@NonNull A seed, @NonNull Applicable generator) {
    return from(Sequence.from(seed, generator, StopConditions.stopNever()));
  }

  /**
   * Creates a new infinite {@link Stream} that retrieves element from the
   * sequence
   * Sequence.from(start, generator, StopConditions.stopNever())
   * 
   * @param 
   * @param seed
   *          the initial element of the sequence
   * @param generator
   *          a function used to generated each element from the sequence after
   *          the initial element
   * @return a new {@link Stream}
   * @see Sequence#from(Object, Applicable, Evaluable)
   */
  @Projection
  public static  Stream iterateUntilNull(@NonNull A seed, @NonNull Applicable generator) {
    return from(Sequence.from(seed, generator, Predicates.null_()));
  }

  /**
   * Creates a new {@link Stream} that retrieves element from the sequence
   * Sequence.from(start, generator, stopCondition)
   * 
   * @param 
   * @param start
   *          the initial element of the sequence
   * @param generator
   *          a function used to generated each element from the sequence after
   *          the initial element
   * @param stopCondition
   *          predicate is satisfied when sequencing should stop, that is, when
   *          the given element and subsequent should not be retrieved.
   * @return a new {@link Stream}
   * @see Sequence#from(Object, Applicable, Evaluable)
   */
  @Projection
  public static  Stream iterate(@NonNull A start, @NonNull Applicable generator,
    @NonNull Evaluable stopCondition) {
    return from(Sequence.from(start, generator, stopCondition));
  }

  /**
   * Creates a new {@link Stream} that retrieves element from the sequence
   * Sequence.from(start, stop)
   * 
   * @param start
   *          the seed of the sequence
   * @param stop
   *          the stop value
   * @return a new {@link Stream}
   */
  @Projection
  public static Stream iterate(int start, int stop) {
    return from(Sequence.fromTo(start, stop));
  }

  /**
   * Answers an infinite Stream that indefinitely retrieves the given element.
   * 
   * @param 
   * @param element
   * @return a new {@link Stream} that repeats the given element
   */
  @Projection
  public static  Stream repeat(final A element) {
    return from(new AbstractThriterator() {
      public boolean hasNext() {
        return true;
      }

      public A next() {
        return element;
      }

      public void advanceNext() throws NoSuchElementException {}

      public A current() {
        return element;
      }
    });
  }

  /**
   * Answers an infinite Stream that indefinitely retrieves the given thunk's
   * value.
   * 
   * @param 
   * @param thunk
   *          the {@link Thunk} whose value to repeat
   * @return a new {@link Stream}
   */
  @Projection
  @ForceRestrictions
  public static  Stream repeat(@NonNull final Thunk thunk) {
    return from(new NextThriterator() {

      public boolean hasNext() {
        return true;
      }

      public A nextImpl() {
        return thunk.value();
      }
    });
  }

  // private static  Stream cycle(@NonNull A element) {
  // //return iterate(element, Functions. identity());
  // }

  /**
   * Create a new {@link Stream} that retrieves elements from the given
   * Iterable.
   * 
   * @param 
   *          the element type
   * @param iterable
   *          the {@link Iterable} to decorate
   * @return the given iterable, if it is {@link Stream}, a new stream that
   *         wraps it, otherwise
   */
  @Projection
  @Conditionally(Repeatable.class)
  public static  Stream from(@NonNull Iterable iterable) {
    return iterable instanceof Stream ? (Stream) iterable : new IterableStream(iterable);
  }

  /**
   * Creates a new {@link Stream} that retrieves elements from the given
   * iterator. The resulting stream can not be iterated more than once, thus it
   * is inherently mutable
   * 
   * @param 
   * @param iterator
   *          source of the the new {@link Stream}
   * @return a new {@link Stream}
   */
  @Projection
  public static  Stream from(@NonNull Iterator iterator) {
    return new IteratorStream(iterator);
  }

  /**
   * Creates a new {@link Stream} that retrieves elements from the given
   * {@link Enumeration}. The resulting stream can not be iterated more than
   * once, thus it is inherently mutable
   * 
   * @param 
   * @param enumeration
   *          source of the new {@link Stream}
   * @return a new {@link Stream}
   */
  @Projection
  public static  Stream from(@NonNull Enumeration enumeration) {
    return from(new EnumerationIterator(enumeration));
  }

  /**
   * Creates a new {@link Stream} that retrieves character elements from the
   * given charSequence
   * 
   * @param charSequence
   *          source of the of characters of the new Stream
   * @return a new {@link Stream}
   */
  @Repeatable
  @Projection
  public static Stream from(@NonNull final CharSequence charSequence) {
    return new CharSequenceStream(charSequence);
  }

  /**
   * Creates a new {@link Stream} that will retrieve elements from the given
   * collection
   * 
   * @param 
   * @param collection
   *          source of the new {@link Stream}
   * @return a new {@link Stream}
   */
  @Repeatable
  @Projection
  public static  Stream from(@NonNull Collection collection) {
    return new CollectionStream(collection);
  }

  /**
   * Creates a new {@link Stream} that retrieves elements from a list. This
   * streams grants repeatable iterator order and supports (not necessary
   * efficient) random access by index.
   * 
   * @param 
   *          the element type
   * @param list
   *          the source of the new {@link Stream}
   * @return a new {@link Stream}
   */
  @Repeatable
  @Projection
  public static  Stream from(@NonNull List list) {
    return new ListStream(list);
  }

  /**
   * Creates a new {@link Stream} that retrieves elements from a {@link Deque}.
   * This streams grants repeatable iterator order and supports (not necessary
   * efficient) random access by index. This stream can be lazily reversed.
   * 
   * @param 
   *          the element type
   * @param list
   *          the source of the new {@link Stream}
   * @return a new {@link Stream}
   */
  @NonNull
  @Repeatable
  @Projection
  public static  Stream from(@NonNull Deque list) {
    return new DequeStream(list);
  }

  // public static  Stream> from(Map iterable) {
  // return new MapEntryStream(iterable);
  // }

  /**
   * Answers a {@link Stream} that has no elements. This stream is immutable and
   * singleton
   * 
   * @param 
   *          the element type
   * @return a singleton empty {@link Stream}
   */
  @Constant
  @Repeatable
  public static  Stream empty() {
    return EmptyStream.empty();
  }

  /**
   * Answers a one element {@link Stream} that throws an exception when trying
   * to access its element.
   * 
   * @param 
   * @return a single elemtn Stream that throws an exception when accessing its
   *         only element
   */
  @Constant
  public static  Stream undefined() {
    return UndefinedStream.undefined();
  }

  /**
   * Answers the Stream class, but preserving its element generic type. This
   * method is mostly aimed to be used with Staccato-Commons-Lambda:
   * 
   * 
   * lambda($(Streams.<User> type()).toList())
   * 
* * @param
* @return (Class<Stream<A>>) Stream.class */ @Constant public static Class> type() { return (Class) Stream.class; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy