    001/*
    002 * Copyright (c) 2007-2016 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
    021package cascading.flow.stream.element;
    022
    023import java.io.IOException;
    024
    025import cascading.CascadingException;
    026import cascading.flow.FlowProcess;
    027import cascading.flow.stream.duct.Duct;
    028import cascading.operation.Function;
    029import cascading.pipe.Each;
    030import cascading.pipe.OperatorException;
    031import cascading.tuple.Fields;
    032import cascading.tuple.Tuple;
    033import cascading.tuple.TupleEntry;
    034import cascading.tuple.TupleEntryCollector;
    035import cascading.tuple.Tuples;
    036
    037/**
    038 *
    039 */
    040public class FunctionEachStage extends EachStage
    041  {
    042  private Function function;
    043
    044  public FunctionEachStage( FlowProcess flowProcess, Each each )
    045    {
    046    super( flowProcess, each );
    047    }
    048
    049  @Override
    050  protected Fields getIncomingPassThroughFields()
    051    {
    052    return incomingScopes.get( 0 ).getIncomingFunctionPassThroughFields();
    053    }
    054
    055  @Override
    056  protected Fields getIncomingArgumentsFields()
    057    {
    058    return incomingScopes.get( 0 ).getIncomingFunctionArgumentFields();
    059    }
    060
    061  @Override
    062  public void initialize()
    063    {
    064    super.initialize();
    065
    066    function = each.getFunction();
    067
    068    operationCall.setArguments( argumentsEntry );
    069
    070    operationCall.setOutputCollector( new TupleEntryCollector( getOperationDeclaredFields() )
    071    {
    072    @Override
    073    protected void collect( TupleEntry input ) throws IOException
    074      {
    075      Tuple outgoing = outgoingBuilder.makeResult( incomingEntry.getTuple(), input.getTuple() );
    076
    077      outgoingEntry.setTuple( outgoing );
    078
    079      try
    080        {
    081        next.receive( FunctionEachStage.this, outgoingEntry );
    082        }
    083      finally
    084        {
    085        Tuples.asModifiable( outgoing );
    086        }
    087      }
    088    } );
    089    }
    090
    091  @Override
    092  public void receive( Duct previous, TupleEntry incomingEntry )
    093    {
    094    this.incomingEntry = incomingEntry;
    095
    096    argumentsEntry.setTuple( argumentsBuilder.makeResult( incomingEntry.getTuple(), null ) );
    097
    098    try
    099      {
    100      function.operate( flowProcess, operationCall ); // adds results to collector
    101      }
    102    catch( CascadingException exception )
    103      {
    104      handleException( exception, argumentsEntry );
    105      }
    106    catch( Throwable throwable )
    107      {
    108      handleException( new OperatorException( each, "operator Each failed executing operation", throwable ), argumentsEntry );
    109      }
    110    }
    111  }