001/*
002 * Copyright (c) 2016-2017 Chris K Wensel. All Rights Reserved.
003 * Copyright (c) 2007-2017 Xplenty, Inc. All Rights Reserved.
004 *
005 * Project and contact information: http://www.cascading.org/
006 *
007 * This file is part of the Cascading project.
008 *
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *     http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 */
021
022package cascading.tuple;
023
024import java.util.Collection;
025import java.util.Collections;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029
030import cascading.operation.OperationException;
031import cascading.tuple.type.CoercibleType;
032
033/**
034 * Class Tuples is a helper class providing common methods to manipulate {@link Tuple} and {@link TupleEntry} instances.
035 *
036 * @see Tuple
037 * @see TupleEntry
038 */
039public class Tuples
040  {
041  /**
042   * A utility function for use with Janino expressions to get around its lack of support for varargs.
043   *
044   * @param a of type Object
045   * @return a new Tuple
046   */
047  public static Tuple tuple( Object a )
048    {
049    return new Tuple( a );
050    }
051
052  /**
053   * A utility function for use with Janino expressions to get around its lack of support for varargs.
054   *
055   * @param a of type Object
056   * @param b of type Object
057   * @return a new Tuple
058   */
059  public static Tuple tuple( Object a, Object b )
060    {
061    return new Tuple( a, b );
062    }
063
064  /**
065   * A utility function for use with Janino expressions to get around its lack of support for varargs.
066   *
067   * @param a of type Object
068   * @param b of type Object
069   * @param c of type Object
070   * @return a new Tuple
071   */
072  public static Tuple tuple( Object a, Object b, Object c )
073    {
074    return new Tuple( a, b, c );
075    }
076
077  /**
078   * A utility function for use with Janino expressions to get around its lack of support for varargs.
079   *
080   * @param a of type Object
081   * @param b of type Object
082   * @param c of type Object
083   * @param d of type Object
084   * @return a new Tuple
085   */
086  public static Tuple tuple( Object a, Object b, Object c, Object d )
087    {
088    return new Tuple( a, b, c, d );
089    }
090
091  /**
092   * A utility function for use with Janino expressions to get around its lack of support for varargs.
093   *
094   * @param a of type Object
095   * @param b of type Object
096   * @param c of type Object
097   * @param d of type Object
098   * @param e of type Object
099   * @return a new Tuple
100   */
101  public static Tuple tuple( Object a, Object b, Object c, Object d, Object e )
102    {
103    return new Tuple( a, b, c, d, e );
104    }
105
106  /**
107   * A utility function for use with Janino expressions to get around its lack of support for varargs.
108   *
109   * @param a of type Object
110   * @param b of type Object
111   * @param c of type Object
112   * @param d of type Object
113   * @param e of type Object
114   * @param f of type Object
115   * @return a new Tuple
116   */
117  public static Tuple tuple( Object a, Object b, Object c, Object d, Object e, Object f )
118    {
119    return new Tuple( a, b, c, d, e, f );
120    }
121
122  /**
123   * A utility function for use with Janino expressions to get around its lack of support for varargs.
124   *
125   * @param a of type Object
126   * @param b of type Object
127   * @param c of type Object
128   * @param d of type Object
129   * @param e of type Object
130   * @param f of type Object
131   * @param g of type Object
132   * @return a new Tuple
133   */
134  public static Tuple tuple( Object a, Object b, Object c, Object d, Object e, Object f, Object g )
135    {
136    return new Tuple( a, b, c, d, e, f, g );
137    }
138
139  /**
140   * A utility function for use with Janino expressions to get around its lack of support for varargs.
141   *
142   * @param a of type Object
143   * @param b of type Object
144   * @param c of type Object
145   * @param d of type Object
146   * @param e of type Object
147   * @param f of type Object
148   * @param g of type Object
149   * @param h of type Object
150   * @return a new Tuple
151   */
152  public static Tuple tuple( Object a, Object b, Object c, Object d, Object e, Object f, Object g, Object h )
153    {
154    return new Tuple( a, b, c, d, e, f, g, h );
155    }
156
157  /**
158   * Method asArray copies the elements of the given Tuple instance to the given Object array.
159   *
160   * @param tuple       of type Tuple
161   * @param destination of type Object[]
162   * @return Object[]
163   */
164  public static <T> T[] asArray( Tuple tuple, T[] destination )
165    {
166    if( tuple.size() != destination.length )
167      throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match destination array size: " + destination.length );
168
169    return tuple.elements( destination );
170    }
171
172  public static Object[] asArray( Tuple tuple, CoercibleType[] coercions, Class[] types, Object[] destination )
173    {
174    if( tuple.size() != types.length )
175      throw new OperationException( "number of input tuple values: " + tuple.size() + ", does not match number of coercion types: " + types.length );
176
177    for( int i = 0; i < types.length; i++ )
178      destination[ i ] = coercions[ i ].coerce( tuple.getObject( i ), types[ i ] );
179
180    return destination;
181    }
182
183  public static Map<String, Object> asMap( Fields fields, TupleEntry arguments )
184    {
185    Map<String, Object> result = new HashMap<>();
186
187    for( Comparable comparable : fields )
188      result.put( comparable.toString(), arguments.getObject( comparable ) );
189
190    return result;
191    }
192
193  public static Map<Comparable, Object> asComparableMap( Fields fields, TupleEntry arguments )
194    {
195    Map<Comparable, Object> result = new HashMap<>();
196
197    for( Comparable comparable : fields )
198      result.put( comparable, arguments.getObject( comparable ) );
199
200    return result;
201    }
202
203  public static Collection asCollection( Tuple tuple )
204    {
205    return Collections.unmodifiableCollection( tuple.elements );
206    }
207
208  /**
209   * Method frequency behaves the same as {@link Collections#frequency(java.util.Collection, Object)}.
210   * <p>
211   * This method is a convenient way to test for all null values in a tuple.
212   *
213   * @param tuple of type Tuple
214   * @param value of type Object
215   * @return an int
216   */
217  public static int frequency( Tuple tuple, Object value )
218    {
219    return Collections.frequency( tuple.elements, value );
220    }
221
222  /**
223   * Method frequency behaves the same as {@link Collections#frequency(java.util.Collection, Object)}.
224   * <p>
225   * This method is a convenient way to test for all null values in a tuple.
226   *
227   * @param tupleEntry of type TupleEntry
228   * @param value      of type Object
229   * @return an int
230   */
231  public static int frequency( TupleEntry tupleEntry, Object value )
232    {
233    return Collections.frequency( tupleEntry.getTuple().elements, value );
234    }
235
236  /**
237   * Method extractTuple returns a new Tuple based on the given selector. But sets the values of the
238   * given TupleEntry to null.
239   *
240   * @param tupleEntry of type TupleEntry
241   * @param selector   of type Fields
242   * @return Tuple
243   */
244  public static Tuple extractTuple( TupleEntry tupleEntry, Fields selector )
245    {
246    if( selector == null || selector.isAll() )
247      {
248      Tuple result = tupleEntry.tuple;
249
250      tupleEntry.setTuple( Tuple.size( result.size() ) );
251
252      return result;
253      }
254
255    try
256      {
257      return extract( tupleEntry, selector );
258      }
259    catch( Exception exception )
260      {
261      throw new TupleException( "unable to select from: " + tupleEntry.getFields().printVerbose() + ", using selector: " + selector.printVerbose(), exception );
262      }
263    }
264
265  /**
266   * Method extract creates a new Tuple from the given selector, but sets the values in the current tuple to null.
267   *
268   * @param tupleEntry of type TupleEntry
269   * @param selector   of type Fields
270   * @return Tuple
271   */
272  public static Tuple extract( TupleEntry tupleEntry, Fields selector )
273    {
274    return tupleEntry.tuple.extract( tupleEntry.getFields().getPos( selector, tupleEntry.getFields().size() ) );
275    }
276
277  public static Tuple nulledCopy( TupleEntry tupleEntry, Fields selector )
278    {
279    return tupleEntry.tuple.nulledCopy( tupleEntry.getFields().getPos( selector, tupleEntry.getFields().size() ) );
280    }
281
282  public static Tuple nulledCopy( Fields declarator, Tuple tuple, Fields selector )
283    {
284    // use tuple.size() in case declarator is UNKNOWN and selector has relative pos
285    return tuple.nulledCopy( declarator.getPos( selector, tuple.size() ) );
286    }
287
288  public static Tuple setOnEmpty( TupleEntry baseEntry, TupleEntry valuesEntry )
289    {
290    Tuple emptyTuple = Tuple.size( baseEntry.getFields().size() );
291
292    emptyTuple.set( baseEntry.getFields(), valuesEntry.getFields(), valuesEntry.getTuple() );
293
294    return emptyTuple;
295    }
296
297  /**
298   * Method asUnmodifiable marks the given Tuple instance as unmodifiable.
299   *
300   * @param tuple of type Tuple
301   * @return Tuple
302   */
303  public static <T extends Tuple> T asUnmodifiable( T tuple )
304    {
305    tuple.isUnmodifiable = true;
306
307    return tuple;
308    }
309
310  /**
311   * Method asModifiable marks the given Tuple instance as modifiable.
312   *
313   * @param tuple of type Tuple
314   * @return Tuple
315   */
316  public static <T extends Tuple> T asModifiable( T tuple )
317    {
318    tuple.isUnmodifiable = false;
319
320    return tuple;
321    }
322
323  public static <T extends Tuple> T setUnmodifiable( T tuple, boolean isUnmodifiable )
324    {
325    tuple.isUnmodifiable = isUnmodifiable;
326
327    return tuple;
328    }
329
330  public static Tuple create( List<Object> arrayList )
331    {
332    return new Tuple( arrayList );
333    }
334  }