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.pipe.assembly;
022    
023    import java.beans.ConstructorProperties;
024    
025    import cascading.operation.Identity;
026    import cascading.pipe.Each;
027    import cascading.pipe.Pipe;
028    import cascading.pipe.SubAssembly;
029    import cascading.tuple.Fields;
030    
031    /**
032     * Class Coerce is a {@link SubAssembly} that will coerce all incoming {@link cascading.tuple.Tuple} values to
033     * the given types.
034     * <p/>
035     * If the given type is a primitive ({@code long}), and the tuple value is null, {@code 0} is returned.
036     * If the type is an Object ({@code java.lang.Long}), and the tuple value is {@code null}, {@code null} is returned.
037     * <p/>
038     * Coerce encapsulates the {@link Identity} function.
039     *
040     * @see cascading.pipe.SubAssembly
041     * @see cascading.operation.Identity
042     */
043    public class Coerce extends SubAssembly
044      {
045      /**
046       * Constructor Coerce creates a new Coerce instance that will coerce all input Tuple values.
047       *
048       * @param previous of type Pipe
049       * @param types    of type Class...
050       */
051      @ConstructorProperties({"previous", "types"})
052      public Coerce( Pipe previous, Class... types )
053        {
054        super( previous );
055    
056        if( types.length > 0 )
057          throw new IllegalArgumentException( "given types array may not be zero length" );
058    
059        setTails( new Each( previous, new Identity( types ) ) );
060        }
061    
062      /**
063       * Constructor Coerce creates a new Coerce instance that will only coerce the given coerceFields Tuple values.
064       * <p/>
065       * Note the resulting output Tuple will contain all the original incoming Fields.
066       *
067       * @param previous     of type Pipe
068       * @param coerceFields of type Fields
069       * @param types        of type Class...
070       */
071      @ConstructorProperties({"previous", "coerceFields", "types"})
072      public Coerce( Pipe previous, Fields coerceFields, Class... types )
073        {
074        super( previous );
075    
076        if( coerceFields == null )
077          throw new IllegalArgumentException( "coerceFields may not be null" );
078    
079        setTails( new Each( previous, coerceFields, new Identity( types ), Fields.REPLACE ) );
080        }
081    
082      /**
083       * Constructor Coerce creates a new Coerce instance that will only coerce the given coerceFields Tuple values.
084       * <p/>
085       * The given {@code coerceFields} instance must contain field type information, otherwise an
086       * {@link IllegalArgumentException} will be thrown.
087       * <p/>
088       * Note the resulting output Tuple will contain all the original incoming Fields.
089       *
090       * @param previous     of type Pipe
091       * @param coerceFields of type Fields
092       */
093      @ConstructorProperties({"previous", "coerceFields"})
094      public Coerce( Pipe previous, Fields coerceFields )
095        {
096        super( previous );
097    
098        if( coerceFields == null )
099          throw new IllegalArgumentException( "coerceFields may not be null" );
100    
101        if( !coerceFields.hasTypes() )
102          throw new IllegalArgumentException( "coerceFields must have field types declared" );
103    
104        setTails( new Each( previous, coerceFields, new Identity( coerceFields ), Fields.REPLACE ) );
105    
106        if( coerceFields.getTypes().length == 0 )
107          throw new IllegalArgumentException( "number of types must not be zero" );
108        }
109      }