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.Stream;
032
033import cascading.flow.FlowProcess;
034import cascading.tap.Tap;
035import cascading.tuple.type.CoercibleType;
036
037/**
038 * TupleEntryStream provides helper methods to create {@link TupleEntry} {@link Stream} instances from
039 * {@link Tap} instances.
040 * <p>
041 * This class is a convenience class over the methods provided on the Tap class that provide the same
042 * functionality. This class exists to help overcome any generics compiler warnings.
043 * <p>
044 * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
045 * is simply accomplished with a try-with-resources statement.
046 */
047public class TupleEntryStream
048  {
049  /**
050   * Method entryStream returns a {@link Stream} of {@link TupleEntry} instances from the given
051   * {@link Tap} instance.
052   * <p>
053   * Also see {@link Tap#entryStream(FlowProcess)}.
054   * <p>
055   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
056   * is simply accomplished with a try-with-resources statement.
057   *
058   * @param tap         the Tap to open
059   * @param flowProcess represents the current platform configuration
060   * @return a Stream of TupleEntry instances
061   */
062  @SuppressWarnings("unchecked")
063  public static Stream<TupleEntry> entryStream( Tap tap, FlowProcess flowProcess )
064    {
065    Objects.requireNonNull( tap );
066
067    return tap.entryStream( flowProcess );
068    }
069
070  /**
071   * Method entryStreamCopy returns a {@link Stream} of {@link TupleEntry} instances from the given
072   * {@link Tap} instance.
073   * <p>
074   * This method returns an TupleEntry instance suitable for caching.
075   * <p>
076   * Also see {@link Tap#entryStreamCopy(FlowProcess)}.
077   * <p>
078   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
079   * is simply accomplished with a try-with-resources statement.
080   *
081   * @param tap         the Tap to open
082   * @param flowProcess represents the current platform configuration
083   * @return a Stream of TupleEntry instances
084   */
085  @SuppressWarnings("unchecked")
086  public static Stream<TupleEntry> entryStreamCopy( Tap tap, FlowProcess flowProcess )
087    {
088    Objects.requireNonNull( tap );
089
090    return tap.entryStreamCopy( flowProcess );
091    }
092
093  /**
094   * Method entryStream returns a {@link Stream} of {@link TupleEntry} instances from the given
095   * {@link Tap} instance.
096   * <p>
097   * Also see {@link Tap#entryStream(FlowProcess, Fields)}.
098   * <p>
099   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
100   * is simply accomplished with a try-with-resources statement.
101   *
102   * @param tap         the Tap to open
103   * @param flowProcess represents the current platform configuration
104   * @param selector    the fields to select from the underlying TupleEntry
105   * @return a Stream of TupleEntry instances
106   */
107  @SuppressWarnings("unchecked")
108  public static Stream<TupleEntry> entryStream( Tap tap, FlowProcess flowProcess, Fields selector )
109    {
110    Objects.requireNonNull( tap );
111    Objects.requireNonNull( selector );
112
113    return tap.entryStream( flowProcess, selector );
114    }
115
116  /**
117   * Method entryStreamCopy returns a {@link Stream} of {@link TupleEntry} instances from the given
118   * {@link Tap} instance.
119   * <p>
120   * This method returns an TupleEntry instance suitable for caching.
121   * <p>
122   * Also see {@link Tap#entryStreamCopy(FlowProcess)}.
123   * <p>
124   * Note, the returned Stream instance must be closed in order to clean up underlying resources. This
125   * is simply accomplished with a try-with-resources statement.
126   *
127   * @param tap         the Tap to open
128   * @param flowProcess represents the current platform configuration
129   * @param selector    the fields to select from the underlying TupleEntry
130   * @return a Stream of TupleEntry instances
131   */
132  @SuppressWarnings("unchecked")
133  public static Stream<TupleEntry> entryStreamCopy( Tap tap, FlowProcess flowProcess, Fields selector )
134    {
135    Objects.requireNonNull( tap );
136    Objects.requireNonNull( selector );
137
138    return tap.entryStreamCopy( flowProcess, selector );
139    }
140
141  /**
142   * Method fieldToObject returns a {@link Function} that returns the object in the given named field or position.
143   *
144   * @param fields the field to select, only first field will be honored
145   * @param <R>    the type of the object returned
146   * @return a Function returning the object or null in the selected field
147   */
148  @SuppressWarnings("unchecked")
149  public static <R> Function<TupleEntry, ? extends R> fieldToObject( Fields fields )
150    {
151    Objects.requireNonNull( fields );
152
153    return value -> (R) value.getObject( fields );
154    }
155
156  /**
157   * Method fieldToObject returns a {@link Function} that returns the object in the given named field or position
158   * coerced to the requested {@link CoercibleType} type.
159   *
160   * @param fields the field to select, only first field will be honored
161   * @param <R>    the type of the object returned
162   * @param type   the CoercibleType to coerce the selected value into
163   * @return a Function returning the object or null in the selected field
164   */
165  @SuppressWarnings("unchecked")
166  public static <R> Function<TupleEntry, R> fieldToObject( Fields fields, CoercibleType<R> type )
167    {
168    Objects.requireNonNull( fields );
169    Objects.requireNonNull( type );
170
171    return value -> (R) value.getObject( fields, type );
172    }
173
174  /**
175   * Method fieldToObject returns a {@link Function} that returns the object in the given named field or position
176   * coerced to the requested {@link Class}.
177   *
178   * @param fields the field to select, only first field will be honored
179   * @param <R>    the type of the object returned
180   * @param type   the Class to coerce the selected value into
181   * @return a Function returning the object or null in the selected field
182   */
183  @SuppressWarnings("unchecked")
184  public static <R> Function<TupleEntry, R> fieldToObject( Fields fields, Class<R> type )
185    {
186    Objects.requireNonNull( fields );
187    Objects.requireNonNull( type );
188
189    return value -> (R) value.getObject( fields, type );
190    }
191
192  /**
193   * Method fieldToInt returns a {@link Function} that returns the int in the given named field or position.
194   *
195   * @param fields the field to select, only first field will be honored
196   * @return the int value in the selected field
197   */
198  public static ToIntFunction<TupleEntry> fieldToInt( Fields fields )
199    {
200    Objects.requireNonNull( fields );
201
202    return value -> value.getInteger( fields );
203    }
204
205  /**
206   * Method fieldToInt returns a {@link Function} that returns the int in the given named field or position.
207   *
208   * @param name the field to select
209   * @return the int value in the selected field
210   */
211  public static ToIntFunction<TupleEntry> fieldToInt( Comparable name )
212    {
213    Objects.requireNonNull( name );
214
215    return value -> value.getInteger( name );
216    }
217
218  /**
219   * Method fieldToLong returns a {@link Function} that returns the long in the given named field or position.
220   *
221   * @param fields the field to select, only first field will be honored
222   * @return the long value in the selected field
223   */
224  public static ToLongFunction<TupleEntry> fieldToLong( Fields fields )
225    {
226    Objects.requireNonNull( fields );
227
228    return value -> value.getLong( fields );
229    }
230
231  /**
232   * Method fieldToLong returns a {@link Function} that returns the long in the given named field or position.
233   *
234   * @param name the field to select
235   * @return the long value in the selected field
236   */
237  public static ToLongFunction<TupleEntry> fieldToLong( Comparable name )
238    {
239    Objects.requireNonNull( name );
240
241    return value -> value.getLong( name );
242    }
243
244  /**
245   * Method fieldToDouble returns a {@link Function} that returns the double in the given named field or position.
246   *
247   * @param fields the field to select, only first field will be honored
248   * @return the double value in the selected field
249   */
250  public static ToDoubleFunction<TupleEntry> fieldToDouble( Fields fields )
251    {
252    Objects.requireNonNull( fields );
253
254    return value -> value.getDouble( fields );
255    }
256
257  /**
258   * Method fieldToDouble returns a {@link Function} that returns the double in the given named field or position.
259   *
260   * @param name the field to select
261   * @return the double value in the selected field
262   */
263  public static ToDoubleFunction<TupleEntry> fieldToDouble( Comparable name )
264    {
265    Objects.requireNonNull( name );
266
267    return value -> value.getDouble( name );
268    }
269
270  /**
271   * Method writeEntry will add each {@link TupleEntry} instance to the {@link TupleEntryCollector} provided
272   * by the given {@link Tap} instance.
273   *
274   * @param stream      a Stream of TupleEntry instances
275   * @param into        a Supplier that returns the Tap to sink each entry into
276   * @param flowProcess represents the current platform configuration
277   * @return returns the given Tap
278   */
279  public static Tap writeEntry( Stream<TupleEntry> stream, Supplier<Tap> into, FlowProcess flowProcess )
280    {
281    return writeEntry( stream, into.get(), flowProcess );
282    }
283
284  /**
285   * Method writeEntry will add each {@link TupleEntry} instance to the {@link TupleEntryCollector} provided
286   * by the given {@link Tap} instance.
287   *
288   * @param stream      a Stream of TupleEntry instances
289   * @param into        the Tap to sink each entry into
290   * @param flowProcess represents the current platform configuration
291   * @return returns the given Tap
292   */
293  @SuppressWarnings("unchecked")
294  public static Tap writeEntry( Stream<TupleEntry> stream, Tap into, FlowProcess flowProcess )
295    {
296    Objects.requireNonNull( into );
297    Objects.requireNonNull( stream );
298
299    try
300      {
301      TupleEntryCollector collector = into.openForWrite( flowProcess );
302
303      stream.forEach( collector::add );
304
305      collector.close();
306      }
307    catch( IOException exception )
308      {
309      throw new UncheckedIOException( exception );
310      }
311
312    return into;
313    }
314
315  /**
316   * Method writeEntry will add each {@link TupleEntry} instance to the {@link TupleEntryCollector} provided
317   * by the given {@link Tap} instance.
318   *
319   * @param iterable    an Iterable of TupleEntry instances
320   * @param into        a Supplier that returns the Tap to sink each entry into
321   * @param flowProcess represents the current platform configuration
322   * @return returns the given Tap
323   */
324  public static Tap writeEntry( Iterable<TupleEntry> iterable, Supplier<Tap> into, FlowProcess flowProcess )
325    {
326    return writeEntry( iterable, into.get(), flowProcess );
327    }
328
329  /**
330   * Method writeEntry will add each {@link TupleEntry} instance to the {@link TupleEntryCollector} provided
331   * by the given {@link Tap} instance.
332   *
333   * @param iterable    an Iterable of TupleEntry instances
334   * @param into        the Tap to sink each entry into
335   * @param flowProcess represents the current platform configuration
336   * @return returns the given Tap
337   */
338  @SuppressWarnings("unchecked")
339  public static Tap writeEntry( Iterable<TupleEntry> iterable, Tap into, FlowProcess flowProcess )
340    {
341    Objects.requireNonNull( into );
342    Objects.requireNonNull( iterable );
343
344    try
345      {
346      TupleEntryCollector collector = into.openForWrite( flowProcess );
347
348      iterable.forEach( collector::add );
349
350      collector.close();
351      }
352    catch( IOException exception )
353      {
354      throw new UncheckedIOException( exception );
355      }
356
357    return into;
358    }
359  }