001    /*
002     * Copyright (c) 2007-2014 Concurrent, Inc. 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    
021    package cascading.tuple;
022    
023    import java.util.Collection;
024    import java.util.Collections;
025    import java.util.List;
026    
027    import cascading.operation.OperationException;
028    import cascading.tuple.coerce.Coercions;
029    import cascading.tuple.type.CoercibleType;
030    
031    /**
032     * Class Tuples is a helper class providing common methods to manipulate {@link Tuple} and {@link TupleEntry} instances.
033     *
034     * @see Tuple
035     * @see TupleEntry
036     */
037    public class Tuples
038      {
039      /**
040       * A utility function for use with Janino expressions to get around its lack of support for varargs.
041       *
042       * @param a of type Object
043       * @return a new Tuple
044       */
045      public static Tuple tuple( Object a )
046        {
047        return new Tuple( a );
048        }
049    
050      /**
051       * A utility function for use with Janino expressions to get around its lack of support for varargs.
052       *
053       * @param a of type Object
054       * @param b of type Object
055       * @return a new Tuple
056       */
057      public static Tuple tuple( Object a, Object b )
058        {
059        return new Tuple( a, b );
060        }
061    
062      /**
063       * A utility function for use with Janino expressions to get around its lack of support for varargs.
064       *
065       * @param a of type Object
066       * @param b of type Object
067       * @param c of type Object
068       * @return a new Tuple
069       */
070      public static Tuple tuple( Object a, Object b, Object c )
071        {
072        return new Tuple( a, b, c );
073        }
074    
075      /**
076       * A utility function for use with Janino expressions to get around its lack of support for varargs.
077       *
078       * @param a of type Object
079       * @param b of type Object
080       * @param c of type Object
081       * @param d of type Object
082       * @return a new Tuple
083       */
084      public static Tuple tuple( Object a, Object b, Object c, Object d )
085        {
086        return new Tuple( a, b, c, d );
087        }
088    
089      /**
090       * A utility function for use with Janino expressions to get around its lack of support for varargs.
091       *
092       * @param a of type Object
093       * @param b of type Object
094       * @param c of type Object
095       * @param d of type Object
096       * @param e of type Object
097       * @return a new Tuple
098       */
099      public static Tuple tuple( Object a, Object b, Object c, Object d, Object e )
100        {
101        return new Tuple( a, b, c, d, e );
102        }
103    
104      /**
105       * A utility function for use with Janino expressions to get around its lack of support for varargs.
106       *
107       * @param a of type Object
108       * @param b of type Object
109       * @param c of type Object
110       * @param d of type Object
111       * @param e of type Object
112       * @param f of type Object
113       * @return a new Tuple
114       */
115      public static Tuple tuple( Object a, Object b, Object c, Object d, Object e, Object f )
116        {
117        return new Tuple( a, b, c, d, e, f );
118        }
119    
120      /**
121       * A utility function for use with Janino expressions to get around its lack of support for varargs.
122       *
123       * @param a of type Object
124       * @param b of type Object
125       * @param c of type Object
126       * @param d of type Object
127       * @param e of type Object
128       * @param f of type Object
129       * @param g of type Object
130       * @return a new Tuple
131       */
132      public static Tuple tuple( Object a, Object b, Object c, Object d, Object e, Object f, Object g )
133        {
134        return new Tuple( a, b, c, d, e, f, g );
135        }
136    
137      /**
138       * A utility function for use with Janino expressions to get around its lack of support for varargs.
139       *
140       * @param a of type Object
141       * @param b of type Object
142       * @param c of type Object
143       * @param d of type Object
144       * @param e of type Object
145       * @param f of type Object
146       * @param g of type Object
147       * @param h of type Object
148       * @return a new Tuple
149       */
150      public static Tuple tuple( Object a, Object b, Object c, Object d, Object e, Object f, Object g, Object h )
151        {
152        return new Tuple( a, b, c, d, e, f, g, h );
153        }
154    
155      /**
156       * Method asArray copies the elements of the given Tuple instance to the given Object array.
157       *
158       * @param tuple       of type Tuple
159       * @param destination of type Object[]
160       * @return Object[]
161       */
162      public static <T> T[] asArray( Tuple tuple, T[] destination )
163        {
164        if( tuple.size() != destination.length )
165          throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match destination array size: " + destination.length );
166    
167        return tuple.elements( destination );
168        }
169    
170      /**
171       * Method asArray convert the given {@link Tuple} instance into an Object[]. The given Class[] array
172       * denotes the types each tuple element value should be coerced into.
173       * <p/>
174       * Coercion types are Object, String, Integer, Long, Float, Double, Short, and Boolean.
175       * <p/>
176       * If all Tuple element values are null, they will remain null for String and Object, but become zero for the numeric types.
177       * <p/>
178       * The string value 'true' can be converted to the boolean true.
179       *
180       * @param tuple of type Tuple
181       * @param types of type Class[]
182       * @return Object[]
183       */
184      @Deprecated
185      public static Object[] asArray( Tuple tuple, Class[] types )
186        {
187        return asArray( tuple, types, new Object[ tuple.size() ] );
188        }
189    
190      /**
191       * Method asArray convert the given {@link Tuple} instance into an Object[]. The given Class[] array
192       * denotes the types each tuple element value should be coerced into.
193       *
194       * @param tuple       of type Tuple
195       * @param types       of type Class[]
196       * @param destination of type Object[]
197       * @return Object[]
198       */
199      @Deprecated
200      public static Object[] asArray( Tuple tuple, Class[] types, Object[] destination )
201        {
202        if( tuple.size() != types.length )
203          throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match number of coercion types: " + types.length );
204    
205        for( int i = 0; i < types.length; i++ )
206          destination[ i ] = coerce( tuple, i, types[ i ] );
207    
208        return destination;
209        }
210    
211      public static Object[] asArray( Tuple tuple, CoercibleType[] coercions, Class[] types, Object[] destination )
212        {
213        if( tuple.size() != types.length )
214          throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match number of coercion types: " + types.length );
215    
216        for( int i = 0; i < types.length; i++ )
217          destination[ i ] = coercions[ i ].coerce( tuple.getObject( i ), types[ i ] );
218    
219        return destination;
220        }
221    
222      public static Collection asCollection( Tuple tuple )
223        {
224        return Collections.unmodifiableCollection( tuple.elements );
225        }
226    
227      /**
228       * Method frequency behaves the same as {@link Collections#frequency(java.util.Collection, Object)}.
229       * <p/>
230       * This method is a convenient way to test for all null values in a tuple.
231       *
232       * @param tuple of type Tuple
233       * @param value of type Object
234       * @return an int
235       */
236      public static int frequency( Tuple tuple, Object value )
237        {
238        return Collections.frequency( tuple.elements, value );
239        }
240    
241      /**
242       * Method frequency behaves the same as {@link Collections#frequency(java.util.Collection, Object)}.
243       * <p/>
244       * This method is a convenient way to test for all null values in a tuple.
245       *
246       * @param tupleEntry of type TupleEntry
247       * @param value      of type Object
248       * @return an int
249       */
250      public static int frequency( TupleEntry tupleEntry, Object value )
251        {
252        return Collections.frequency( tupleEntry.getTuple().elements, value );
253        }
254    
255      /**
256       * Method coerce returns the value in the tuple at the given position to the requested type.
257       * <p/>
258       * If the given type is a primitive (long), and the tuple value is null, 0 is returned.
259       * <p/>
260       * If the type is an Object (Long), and the tuple value is null, null is returned.
261       *
262       * @param tuple of type Tuple
263       * @param pos   of type int
264       * @param type  of type Class
265       * @return returns the value coerced
266       */
267      @Deprecated
268      public static Object coerce( Tuple tuple, int pos, Class type )
269        {
270        Object value = tuple.getObject( pos );
271    
272        return coerce( value, type );
273        }
274    
275      @Deprecated
276      public static Object coerce( Object value, Class type )
277        {
278        return Coercions.coerce( value, type );
279        }
280    
281      @Deprecated
282      public static final String toString( Object value )
283        {
284        return Coercions.STRING.coerce( value );
285        }
286    
287      @Deprecated
288      public static final int toInteger( Object value )
289        {
290        return Coercions.INTEGER.coerce( value );
291        }
292    
293      @Deprecated
294      public static final long toLong( Object value )
295        {
296        return Coercions.LONG.coerce( value );
297        }
298    
299      @Deprecated
300      public static final double toDouble( Object value )
301        {
302        return Coercions.DOUBLE.coerce( value );
303        }
304    
305      @Deprecated
306      public static final float toFloat( Object value )
307        {
308        return Coercions.FLOAT.coerce( value );
309        }
310    
311      @Deprecated
312      public static final short toShort( Object value )
313        {
314        return Coercions.SHORT.coerce( value );
315        }
316    
317      @Deprecated
318      public static final boolean toBoolean( Object value )
319        {
320        return Coercions.BOOLEAN.coerce( value );
321        }
322    
323      @Deprecated
324      public static final Integer toIntegerObject( Object value )
325        {
326        return Coercions.INTEGER_OBJECT.coerce( value );
327        }
328    
329      @Deprecated
330      public static final Long toLongObject( Object value )
331        {
332        return Coercions.LONG_OBJECT.coerce( value );
333        }
334    
335      @Deprecated
336      public static final Double toDoubleObject( Object value )
337        {
338        return Coercions.DOUBLE_OBJECT.coerce( value );
339        }
340    
341      @Deprecated
342      public static final Float toFloatObject( Object value )
343        {
344        return Coercions.FLOAT_OBJECT.coerce( value );
345        }
346    
347      @Deprecated
348      public static final Short toShortObject( Object value )
349        {
350        return Coercions.SHORT_OBJECT.coerce( value );
351        }
352    
353      @Deprecated
354      public static final Boolean toBooleanObject( Object value )
355        {
356        return Coercions.BOOLEAN_OBJECT.coerce( value );
357        }
358    
359      /**
360       * Method coerce forces each element value in the given Tuple to the corresponding primitive type.
361       *
362       * @param tuple of type Tuple
363       * @param types of type Class[]
364       * @return Tuple
365       */
366      @Deprecated
367      public static Tuple coerce( Tuple tuple, Class[] types )
368        {
369        return new Tuple( (Object[]) asArray( tuple, types, new Object[ types.length ] ) );
370        }
371    
372      /**
373       * Method coerce forces each element value in the given Tuple to the corresponding primitive type.
374       * <p/>
375       * This method expects the destination Tuple was created with the same size at the types array.
376       *
377       * @param tuple       of type Tuple
378       * @param types       of type Class[]
379       * @param destination of type Tuple
380       * @return Tuple
381       */
382      @Deprecated
383      public static Tuple coerce( Tuple tuple, Class[] types, Tuple destination )
384        {
385        if( tuple.size() != types.length )
386          throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match number of coercion types: " + types.length );
387    
388        if( destination.size() != types.length )
389          throw new OperationException( "number of destination tuple values: " + destination.size() + ", does not match number of coercion types: " + types.length );
390    
391        for( int i = 0; i < types.length; i++ )
392          destination.set( i, coerce( tuple, i, types[ i ] ) );
393    
394        return destination;
395        }
396    
397      /**
398       * Method extractTuple returns a new Tuple based on the given selector. But sets the values of the
399       * given TupleEntry to null.
400       *
401       * @param tupleEntry of type TupleEntry
402       * @param selector   of type Fields
403       * @return Tuple
404       */
405      public static Tuple extractTuple( TupleEntry tupleEntry, Fields selector )
406        {
407        if( selector == null || selector.isAll() )
408          {
409          Tuple result = tupleEntry.tuple;
410    
411          tupleEntry.setTuple( Tuple.size( result.size() ) );
412    
413          return result;
414          }
415    
416        try
417          {
418          return extract( tupleEntry, selector );
419          }
420        catch( Exception exception )
421          {
422          throw new TupleException( "unable to select from: " + tupleEntry.getFields().printVerbose() + ", using selector: " + selector.printVerbose(), exception );
423          }
424        }
425    
426      /**
427       * Method extract creates a new Tuple from the given selector, but sets the values in the current tuple to null.
428       *
429       * @param tupleEntry of type TupleEntry
430       * @param selector   of type Fields
431       * @return Tuple
432       */
433      public static Tuple extract( TupleEntry tupleEntry, Fields selector )
434        {
435        return tupleEntry.tuple.extract( tupleEntry.getFields().getPos( selector, tupleEntry.getFields().size() ) );
436        }
437    
438      public static Tuple nulledCopy( TupleEntry tupleEntry, Fields selector )
439        {
440        return tupleEntry.tuple.nulledCopy( tupleEntry.getFields().getPos( selector, tupleEntry.getFields().size() ) );
441        }
442    
443      public static Tuple nulledCopy( Fields declarator, Tuple tuple, Fields selector )
444        {
445        return tuple.nulledCopy( declarator.getPos( selector, declarator.size() ) );
446        }
447    
448      public static Tuple setOnEmpty( TupleEntry baseEntry, TupleEntry valuesEntry )
449        {
450        Tuple emptyTuple = Tuple.size( baseEntry.getFields().size() );
451    
452        emptyTuple.set( baseEntry.getFields(), valuesEntry.getFields(), valuesEntry.getTuple() );
453    
454        return emptyTuple;
455        }
456    
457      /**
458       * Method asUnmodifiable marks the given Tuple instance as unmodifiable.
459       *
460       * @param tuple of type Tuple
461       * @return Tuple
462       */
463      public static Tuple asUnmodifiable( Tuple tuple )
464        {
465        tuple.isUnmodifiable = true;
466    
467        return tuple;
468        }
469    
470      /**
471       * Method asModifiable marks the given Tuple instance as modifiable.
472       *
473       * @param tuple of type Tuple
474       * @return Tuple
475       */
476      public static Tuple asModifiable( Tuple tuple )
477        {
478        tuple.isUnmodifiable = false;
479    
480        return tuple;
481        }
482    
483      public static Tuple setUnmodifiable( Tuple tuple, boolean isUnmodifiable )
484        {
485        tuple.isUnmodifiable = isUnmodifiable;
486    
487        return tuple;
488        }
489    
490      public static Tuple create( List<Object> arrayList )
491        {
492        return new Tuple( arrayList );
493        }
494      }