    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      }