/* * Copyright (c) 2007-2010 Concurrent, Inc. All Rights Reserved. * * Project and contact information: http://www.cascading.org/ * * This file is part of the Cascading project. * * Cascading is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cascading 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cascading. If not, see <http://www.gnu.org/licenses/>. */ package cascading.tuple; import cascading.operation.OperationException; /** * Class Tuples is a helper class providing common methods to manipulate {@link Tuple} and {@link TupleEntry} instances. * * @see Tuple * @see TupleEntry */ public class Tuples { /** A constant empty Tuple instance. This instance is immutable. */ public static final Tuple NULL = asUnmodifiable( new Tuple() ); /** * Method asArray copies the elements of the given Tuple instance to the given Object array. * * @param tuple of type Tuple * @param destination of type Object[] * @return Object[] */ public static Object[] asArray( Tuple tuple, Object[] destination ) { if( tuple.size() != destination.length ) throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match destination array size: " + destination.length ); return tuple.elements( destination ); } /** * Method asArray convert the given {@link Tuple} instance into an Object[]. The given Class[] array * denotes the types each tuple element value should be coerced into. * <p/> * Coercion types are Object, String, Integer, Long, Float, Double, Short, and Boolean. * <p/> * If all Tuple element values are null, they will remain null for String and Object, but become zero for the numeric types. * <p/> * The string value 'true' can be converted to the boolean true. * * @param tuple of type Tuple * @param types of type Class[] * @return Object[] */ public static Object[] asArray( Tuple tuple, Class[] types ) { return asArray( tuple, types, new Object[tuple.size()] ); } /** * Method asArray convert the given {@link Tuple} instance into an Object[]. The given Class[] array * denotes the types each tuple element value should be coerced into. * * @param tuple of type Tuple * @param types of type Class[] * @param destination of type Object[] * @return Object[] */ public static Object[] asArray( Tuple tuple, Class[] types, Object[] destination ) { if( tuple.size() != types.length ) throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match number of coercion types: " + types.length ); for( int i = 0; i < types.length; i++ ) destination[ i ] = coerce( tuple, i, types[ i ] ); return destination; } /** * Method coerce returns the value in the tuple at the given position to the requested type. * * @param tuple of type Tuple * @param pos of type int * @param type of type Class * @return returns the value coerced */ public static Object coerce( Tuple tuple, int pos, Class type ) { Object value = tuple.getObject( pos ); return coerce( value, type ); } public static Object coerce( Object value, Class type ) { if( value != null && type == value.getClass() ) return value; if( type == Object.class ) return value; if( type == String.class ) return toString( value ); if( type == Integer.class || type == int.class ) return toInteger( value ); if( type == Long.class || type == long.class ) return toLong( value ); if( type == Double.class || type == double.class ) return toDouble( value ); if( type == Float.class || type == float.class ) return toFloat( value ); if( type == Short.class || type == short.class ) return toShort( value ); if( type == Boolean.class || type == boolean.class ) return toBoolean( value ); if( type != null ) throw new OperationException( "could not coerce value, " + value + " to type: " + type.getName() ); return null; } public static final String toString( Object value ) { if( value == null ) return null; return value.toString(); } public static final int toInteger( Object value ) { if( value instanceof Number ) return ( (Number) value ).intValue(); else if( value == null ) return 0; else return Integer.parseInt( value.toString() ); } public static final long toLong( Object value ) { if( value instanceof Number ) return ( (Number) value ).longValue(); else if( value == null ) return 0; else return Long.parseLong( value.toString() ); } public static final double toDouble( Object value ) { if( value instanceof Number ) return ( (Number) value ).doubleValue(); else if( value == null ) return 0; else return Double.parseDouble( value.toString() ); } public static final float toFloat( Object value ) { if( value instanceof Number ) return ( (Number) value ).floatValue(); else if( value == null ) return 0; else return Float.parseFloat( value.toString() ); } public static final short toShort( Object value ) { if( value instanceof Number ) return ( (Number) value ).shortValue(); else if( value == null ) return 0; else return Short.parseShort( value.toString() ); } public static final boolean toBoolean( Object value ) { if( value instanceof Boolean ) return ( (Boolean) value ).booleanValue(); else if( value == null ) return false; else return Boolean.parseBoolean( value.toString() ); } /** * Method coerce forces each element value in the given Tuple to the corresponding primitive type. * * @param tuple of type Tuple * @param types of type Class[] * @return Tuple */ public static Tuple coerce( Tuple tuple, Class[] types ) { return new Tuple( (Object[]) asArray( tuple, types, new Object[types.length] ) ); } /** * Method extractTuple returns a new Tuple based on the given selector. But sets the values of the * given TupleEntry to null. * * @param tupleEntry of type TupleEntry * @param selector of type Fields * @return Tuple */ public static Tuple extractTuple( TupleEntry tupleEntry, Fields selector ) { if( selector == null || selector.isAll() ) { Tuple result = tupleEntry.tuple; tupleEntry.tuple = Tuple.size( result.size() ); return result; } try { return extract( tupleEntry, selector ); } catch( Exception exception ) { throw new TupleException( "unable to select from: " + tupleEntry.fields.print() + ", using selector: " + selector.print(), exception ); } } /** * Method extract creates a new Tuple from the given selector, but sets the values in the current tuple to null. * * @param tupleEntry of type TupleEntry * @param selector of type Fields * @return Tuple */ public static Tuple extract( TupleEntry tupleEntry, Fields selector ) { return tupleEntry.tuple.extract( tupleEntry.fields.getPos( selector, tupleEntry.fields.size() ) ); } public static Tuple setOnEmpty( TupleEntry baseEntry, TupleEntry valuesEntry ) { Tuple emptyTuple = Tuple.size( baseEntry.getFields().size() ); emptyTuple.set( baseEntry.getFields(), valuesEntry.getFields(), valuesEntry.getTuple() ); return emptyTuple; } /** * Method asUnmodifiable marks the given Tuple instance as unmodifiable. * * @param tuple of type Tuple * @return Tuple */ public static Tuple asUnmodifiable( Tuple tuple ) { tuple.isUnmodifiable = true; return tuple; } /** * Method asModifiable marks the given Tuple instance as modifiable. * * @param tuple of type Tuple * @return Tuple */ public static Tuple asModifiable( Tuple tuple ) { tuple.isUnmodifiable = false; return tuple; } }