001/*
002 * Copyright (c) 2016-2017 Chris K Wensel. All Rights Reserved.
003 *
004 * Project and contact information: http://www.cascading.org/
005 *
006 * This file is part of the Cascading project.
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *     http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020
021package cascading.tuple;
022
023import java.io.IOException;
024import java.io.UncheckedIOException;
025import java.util.Objects;
026import java.util.function.Function;
027import java.util.function.Supplier;
028import java.util.function.ToDoubleFunction;
029import java.util.function.ToIntFunction;
030import java.util.function.ToLongFunction;
031import java.util.stream.DoubleStream;
032import java.util.stream.IntStream;
033import java.util.stream.LongStream;
034import java.util.stream.Stream;
035
036import cascading.flow.FlowProcess;
037import cascading.tap.Tap;
038
039/**
040 * TupleStream provides helper methods to create {@link Tuple} {@link Stream} instances from {@link Tap} instances.
041 * <p>
042 * This class is a convenience class over the methods provided on the Tap class that provide the same
043 * functionality. This class exists to help overcome any generics compiler warnings.
044 * <p>
045 * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
046 * is simply accomplished with a try-with-resources statement.
047 */
048public class TupleStream
049  {
050  /**
051   * Method tupleStream returns a {@link Stream} of {@link Tuple} instances from the given
052   * {@link Tap} instance.
053   * <p>
054   * Also see {@link Tap#tupleStream(FlowProcess)}.
055   * <p>
056   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
057   * is simply accomplished with a try-with-resources statement.
058   *
059   * @param tap         the Tap to open
060   * @param flowProcess represents the current platform configuration
061   * @return a Stream of Tuple instances
062   */
063  @SuppressWarnings("unchecked")
064  public static Stream<Tuple> tupleStream( Tap tap, FlowProcess flowProcess )
065    {
066    Objects.requireNonNull( tap );
067
068    return tap.tupleStream( flowProcess );
069    }
070
071  /**
072   * Method tupleStreamCopy returns a {@link Stream} of {@link Tuple} instances from the given
073   * {@link Tap} instance.
074   * <p>
075   * This method returns an Tuple instance suitable for caching.
076   * <p>
077   * Also see {@link Tap#tupleStreamCopy(FlowProcess)}.
078   * <p>
079   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
080   * is simply accomplished with a try-with-resources statement.
081   *
082   * @param tap         the Tap to open
083   * @param flowProcess represents the current platform configuration
084   * @return a Stream of TupleEntry instances
085   */
086  @SuppressWarnings("unchecked")
087  public static Stream<Tuple> tupleStreamCopy( Tap tap, FlowProcess flowProcess )
088    {
089    Objects.requireNonNull( tap );
090
091    return tap.tupleStreamCopy( flowProcess );
092    }
093
094  /**
095   * Method tupleStream returns a {@link Stream} of {@link Tuple} instances from the given
096   * {@link Tap} instance.
097   * <p>
098   * Also see {@link Tap#tupleStream(FlowProcess)}.
099   * <p>
100   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
101   * is simply accomplished with a try-with-resources statement.
102   *
103   * @param tap         the Tap to open
104   * @param flowProcess represents the current platform configuration
105   * @param selector    the fields to select from the underlying Tuple
106   * @return a Stream of TupleE instances
107   */
108  @SuppressWarnings("unchecked")
109  public static Stream<Tuple> tupleStream( Tap tap, FlowProcess flowProcess, Fields selector )
110    {
111    Objects.requireNonNull( tap );
112    Objects.requireNonNull( selector );
113
114    return tap.tupleStream( flowProcess, selector );
115    }
116
117  /**
118   * Method tupleStreamCopy returns a {@link Stream} of {@link Tuple} instances from the given
119   * {@link Tap} instance.
120   * <p>
121   * This method returns an Tuple instance suitable for caching.
122   * <p>
123   * Also see {@link Tap#tupleStreamCopy(FlowProcess)}.
124   * <p>
125   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
126   * is simply accomplished with a try-with-resources statement.
127   *
128   * @param tap         the Tap to open
129   * @param flowProcess represents the current platform configuration
130   * @param selector    the fields to select from the underlying Tuple
131   * @return a Stream of Tuple instances
132   */
133  @SuppressWarnings("unchecked")
134  public static Stream<Tuple> tupleStreamCopy( Tap tap, FlowProcess flowProcess, Fields selector )
135    {
136    Objects.requireNonNull( tap );
137    Objects.requireNonNull( selector );
138
139    return tap.tupleStreamCopy( flowProcess, selector );
140    }
141
142  /**
143   * Method posToObject returns the object at the given tuple position.
144   *
145   * @param pos the ordinal position to select from
146   * @param <R> the object type
147   * @return the value in the given ordinal position
148   */
149  @SuppressWarnings("unchecked")
150  public static <R> Function<Tuple, ? extends R> posToObject( int pos )
151    {
152    return value -> (R) value.getObject( pos );
153    }
154
155  /**
156   * Method posToInt returns the int value at the given tuple position.
157   *
158   * @param pos the ordinal position to select from
159   * @return the value in the given ordinal position
160   */
161  public static ToIntFunction<Tuple> posToInt( int pos )
162    {
163    return value -> value.getInteger( pos );
164    }
165
166  /**
167   * Method posToLong returns the long value at the given tuple position.
168   *
169   * @param pos the ordinal position to select from
170   * @return the value in the given ordinal position
171   */
172  public static ToLongFunction<Tuple> posToLong( int pos )
173    {
174    return value -> value.getLong( pos );
175    }
176
177  /**
178   * Method posToDouble returns the double value at the given tuple position.
179   *
180   * @param pos the ordinal position to select from
181   * @return the value in the given ordinal position
182   */
183  public static ToDoubleFunction<Tuple> posToDouble( int pos )
184    {
185    return value -> value.getDouble( pos );
186    }
187
188  /**
189   * Method writeTuple will add each {@link Tuple} instance to the {@link TupleEntryCollector} provided
190   * by the given {@link Tap} instance.
191   *
192   * @param stream      a Stream of Tuple instances
193   * @param into        a Supplier that returns the Tap to sink each entry into
194   * @param flowProcess represents the current platform configuration
195   * @return returns the given Tap
196   */
197  public static Tap writeTuple( Stream<Tuple> stream, Supplier<Tap> into, FlowProcess flowProcess )
198    {
199    return writeTuple( stream, into.get(), flowProcess );
200    }
201
202  /**
203   * Method writeTuple will add each {@link Tuple} instance to the {@link TupleEntryCollector} provided
204   * by the given {@link Tap} instance.
205   *
206   * @param stream      a Stream of Tuple instances
207   * @param into        the Tap to sink each entry into
208   * @param flowProcess represents the current platform configuration
209   * @return returns the given Tap
210   */
211  @SuppressWarnings("unchecked")
212  public static Tap writeTuple( Stream<Tuple> stream, Tap into, FlowProcess flowProcess )
213    {
214    Objects.requireNonNull( into );
215    Objects.requireNonNull( stream );
216
217    try
218      {
219      TupleEntryCollector collector = into.openForWrite( flowProcess );
220
221      stream.forEach( collector::add );
222
223      collector.close();
224      }
225    catch( IOException exception )
226      {
227      throw new UncheckedIOException( exception );
228      }
229
230    return into;
231    }
232
233  /**
234   * Method writeInt will add each {@code int} instance to the {@link TupleEntryCollector} provided
235   * by the given {@link Tap} instance.
236   *
237   * @param stream      a Stream of int values
238   * @param into        a Supplier that returns the Tap to sink each value into
239   * @param flowProcess represents the current platform configuration
240   * @return returns the given Tap
241   */
242  public static Tap writeInt( IntStream stream, Supplier<Tap> into, FlowProcess flowProcess )
243    {
244    return writeInt( stream, into.get(), flowProcess );
245    }
246
247  /**
248   * Method writeInt will add each {@code int} instance to the {@link TupleEntryCollector} provided
249   * by the given {@link Tap} instance.
250   *
251   * @param stream      a Stream of int values
252   * @param into        the Tap to sink each value into
253   * @param flowProcess represents the current platform configuration
254   * @return returns the given Tap
255   */
256  @SuppressWarnings("unchecked")
257  public static Tap writeInt( IntStream stream, Tap into, FlowProcess flowProcess )
258    {
259    Objects.requireNonNull( into );
260    Objects.requireNonNull( stream );
261
262    Tuple tuple = Tuple.size( 1 );
263
264    try
265      {
266      TupleEntryCollector collector = into.openForWrite( flowProcess );
267
268      stream.forEach( i -> collector.add( reset( tuple, i ) ) );
269
270      collector.close();
271      }
272    catch( IOException exception )
273      {
274      throw new UncheckedIOException( exception );
275      }
276
277    return into;
278    }
279
280  /**
281   * Method writeLong will add each {@code long} instance to the {@link TupleEntryCollector} provided
282   * by the given {@link Tap} instance.
283   *
284   * @param stream      a Stream of long values
285   * @param into        a Supplier that returns the Tap to sink each value into
286   * @param flowProcess represents the current platform configuration
287   * @return returns the given Tap
288   */
289  public static Tap writeLong( LongStream stream, Supplier<Tap> into, FlowProcess flowProcess )
290    {
291    return writeLong( stream, into.get(), flowProcess );
292    }
293
294  /**
295   * Method writeLong will add each {@code long} instance to the {@link TupleEntryCollector} provided
296   * by the given {@link Tap} instance.
297   *
298   * @param stream      a Stream of long values
299   * @param into        the Tap to sink each value into
300   * @param flowProcess represents the current platform configuration
301   * @return returns the given Tap
302   */
303  @SuppressWarnings("unchecked")
304  public static Tap writeLong( LongStream stream, Tap into, FlowProcess flowProcess )
305    {
306    Objects.requireNonNull( into );
307    Objects.requireNonNull( stream );
308
309    Tuple tuple = Tuple.size( 1 );
310
311    try
312      {
313      TupleEntryCollector collector = into.openForWrite( flowProcess );
314
315      stream.forEach( i -> collector.add( reset( tuple, i ) ) );
316
317      collector.close();
318      }
319    catch( IOException exception )
320      {
321      throw new UncheckedIOException( exception );
322      }
323
324    return into;
325    }
326
327  /**
328   * Method writeDouble will add each {@code double} instance to the {@link TupleEntryCollector} provided
329   * by the given {@link Tap} instance.
330   *
331   * @param stream      a Stream of double values
332   * @param into        a Supplier that returns the Tap to sink each value into
333   * @param flowProcess represents the current platform configuration
334   * @return returns the given Tap
335   */
336  public static Tap writeDouble( DoubleStream stream, Supplier<Tap> into, FlowProcess flowProcess )
337    {
338    return writeDouble( stream, into.get(), flowProcess );
339    }
340
341  /**
342   * Method writeDouble will add each {@code double} instance to the {@link TupleEntryCollector} provided
343   * by the given {@link Tap} instance.
344   *
345   * @param stream      a Stream of double values
346   * @param into        the Tap to sink each value into
347   * @param flowProcess represents the current platform configuration
348   * @return returns the given Tap
349   */
350  @SuppressWarnings("unchecked")
351  public static Tap writeDouble( DoubleStream stream, Tap into, FlowProcess flowProcess )
352    {
353    Objects.requireNonNull( into );
354    Objects.requireNonNull( stream );
355
356    Tuple tuple = Tuple.size( 1 );
357
358    try
359      {
360      TupleEntryCollector collector = into.openForWrite( flowProcess );
361
362      stream.forEach( i -> collector.add( reset( tuple, i ) ) );
363
364      collector.close();
365      }
366    catch( IOException exception )
367      {
368      throw new UncheckedIOException( exception );
369      }
370
371    return into;
372    }
373
374  private static Tuple reset( Tuple tuple, Object value )
375    {
376    tuple.set( 0, value );
377    return tuple;
378    }
379  }