Package cascading.pipe

Source Code of cascading.pipe.Operator

/*
* Copyright (c) 2007-2014 Concurrent, Inc. All Rights Reserved.
*
* Project and contact information: http://www.cascading.org/
*
* This file is part of the Cascading project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cascading.pipe;

import java.util.Set;

import cascading.flow.FlowElement;
import cascading.flow.planner.Scope;
import cascading.operation.Assertion;
import cascading.operation.AssertionLevel;
import cascading.operation.BaseOperation;
import cascading.operation.Operation;
import cascading.operation.PlannedOperation;
import cascading.operation.PlannerLevel;
import cascading.tuple.Fields;
import cascading.tuple.FieldsResolverException;
import cascading.tuple.TupleException;

/**
* An Operator is a type of {@link Pipe}. Operators pass specified arguments to a given {@link cascading.operation.BaseOperation}.
* </p>
* The argFields value select the input fields used by the operation. By default the whole input Tuple is passes as arguments.
* The outFields value select the fields in the result Tuple returned by this Pipe. By default, the operation results
* of the given operation replace the input Tuple.
*/
public abstract class Operator extends Pipe
  {
  /** Field operation */
  protected final Operation operation;
  /** Field argumentSelector */
  protected Fields argumentSelector = Fields.ALL; // use wildcard. let the operation choose
  /** Field outputSelector */
  protected Fields outputSelector = Fields.RESULTS;  // this is overridden by the subclasses via the ctor
  /** Field assertionLevel */
  protected PlannerLevel plannerLevel; // do not initialize a default

  protected Operator( Operation operation )
    {
    this.operation = operation;
    verifyOperation();
    }

  protected Operator( String name, Operation operation )
    {
    super( name );
    this.operation = operation;
    verifyOperation();
    }

  protected Operator( String name, Operation operation, Fields outputSelector )
    {
    super( name );
    this.operation = operation;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( String name, Fields argumentSelector, Operation operation )
    {
    super( name );
    this.operation = operation;
    this.argumentSelector = argumentSelector;
    verifyOperation();
    }

  protected Operator( String name, Fields argumentSelector, Operation operation, Fields outputSelector )
    {
    super( name );
    this.operation = operation;
    this.argumentSelector = argumentSelector;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( Pipe previous, Operation operation )
    {
    super( previous );
    this.operation = operation;
    verifyOperation();
    }

  protected Operator( Pipe previous, Fields argumentSelector, Operation operation )
    {
    super( previous );
    this.operation = operation;
    this.argumentSelector = argumentSelector;
    verifyOperation();
    }

  protected Operator( Pipe previous, Fields argumentSelector, Operation operation, Fields outputSelector )
    {
    super( previous );
    this.operation = operation;
    this.argumentSelector = argumentSelector;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( Pipe previous, Operation operation, Fields outputSelector )
    {
    super( previous );
    this.operation = operation;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( String name, PlannerLevel plannerLevel, PlannedOperation operation, Fields outputSelector )
    {
    super( name );
    this.plannerLevel = plannerLevel;
    this.operation = operation;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( String name, Fields argumentSelector, PlannerLevel plannerLevel, PlannedOperation operation, Fields outputSelector )
    {
    super( name );
    this.plannerLevel = plannerLevel;
    this.operation = operation;
    this.argumentSelector = argumentSelector;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( Pipe previous, PlannerLevel plannerLevel, PlannedOperation operation, Fields outputSelector )
    {
    super( previous );
    this.plannerLevel = plannerLevel;
    this.operation = operation;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected Operator( Pipe previous, Fields argumentSelector, PlannerLevel plannerLevel, PlannedOperation operation, Fields outputSelector )
    {
    super( previous );
    this.plannerLevel = plannerLevel;
    this.operation = operation;
    this.argumentSelector = argumentSelector;
    this.outputSelector = outputSelector;
    verifyOperation();
    }

  protected void verifyOperation()
    {
    if( operation == null )
      throw new IllegalArgumentException( "operation may not be null" );

    if( argumentSelector == null )
      throw new IllegalArgumentException( "argumentSelector may not be null" );

    if( outputSelector == null )
      throw new IllegalArgumentException( "outputSelector may not be null" );

    if( operation instanceof PlannedOperation )
      {
      if( plannerLevel == null )
        throw new IllegalArgumentException( "planner level may not be null" );
      else if( plannerLevel.isNoneLevel() )
        throw new IllegalArgumentException( "given planner level: " + plannerLevel.getClass().getName() + ", may not be NONE" );
      }
    }

  /**
   * Method getOperation returns the operation managed by this Operator object.
   *
   * @return the operation (type Operation) of this Operator object.
   */
  public Operation getOperation()
    {
    return operation;
    }

  /**
   * Method getArgumentSelector returns the argumentSelector of this Operator object.
   *
   * @return the argumentSelector (type Fields) of this Operator object.
   */
  public Fields getArgumentSelector()
    {
    return argumentSelector;
    }

  /**
   * Method getFieldDeclaration returns the fieldDeclaration of this Operator object.
   *
   * @return the fieldDeclaration (type Fields) of this Operator object.
   */
  public Fields getFieldDeclaration()
    {
    return operation.getFieldDeclaration();
    }

  /**
   * Method getOutputSelector returns the outputSelector of this Operator object.
   *
   * @return the outputSelector (type Fields) of this Operator object.
   */
  public Fields getOutputSelector()
    {
    return outputSelector;
    }

  /**
   * Method getAssertionLevel returns the assertionLevel of this Operator object. Only used if the {@link cascading.operation.Operation}
   * is an {@link Assertion}.
   *
   * @return the assertionLevel (type Assertion.Level) of this Operator object.
   */
  @Deprecated
  public AssertionLevel getAssertionLevel()
    {
    return (AssertionLevel) plannerLevel;
    }

  /**
   * Method getPlannerLevel returns the plannerLevel of this Operator object.
   *
   * @return the plannerLevel (type PlannerLevel) of this Operator object.
   */
  public PlannerLevel getPlannerLevel()
    {
    return plannerLevel;
    }

  /**
   * Method hasPlannerLevel returns true if this Operator object holds a {@link PlannedOperation} object with an associated
   * {@link PlannerLevel} level.
   *
   * @return boolean
   */
  public boolean hasPlannerLevel()
    {
    return plannerLevel != null;
    }

  // FIELDS

  protected Fields resolveRemainderFields( Set<Scope> incomingScopes, Fields argumentFields )
    {
    Fields fields = resolveIncomingOperationArgumentFields( getFirst( incomingScopes ) );

    if( fields.isUnknown() )
      return fields;

    return fields.subtract( argumentFields );
    }

  public abstract Scope outgoingScopeFor( Set<Scope> incomingScopes );

  void verifyDeclaredFields( Fields declared )
    {
    if( declared.isDefined() && declared.size() == 0 )
      throw new OperatorException( this, "field declaration: " + getFieldDeclaration().printVerbose() + ", resolves to an empty field set, current grouping is on all fields" );
    }

  void verifyOutputSelector( Fields outputSelector )
    {
    if( outputSelector.isDefined() && outputSelector.size() == 0 )
      throw new OperatorException( this, "output selector: " + getOutputSelector().printVerbose() + ", resolves to an empty field set, current grouping is on all fields" );
    }

  void verifyArguments( Fields argumentSelector )
    {
    if( argumentSelector.isUnknown() )
      return;

    if( operation.getNumArgs() != Operation.ANY && argumentSelector.size() < operation.getNumArgs() )
      throw new OperatorException( this, "resolved wrong number of arguments: " + argumentSelector.printVerbose() + ", expected: " + operation.getNumArgs() );
    }

  Fields resolveOutgoingSelector( Set<Scope> incomingScopes, Fields argumentFields, Fields declaredFields )
    {
    Scope incomingScope = getFirst( incomingScopes );
    Fields outputSelector = getOutputSelector();

    if( outputSelector.isResults() )
      return declaredFields;

    if( outputSelector.isArguments() )
      return argumentFields;

    if( outputSelector.isGroup() )
      return incomingScope.getOutGroupingFields();

    if( outputSelector.isValues() )
      return incomingScope.getOutGroupingValueFields();

    Fields incomingFields = resolveIncomingOperationPassThroughFields( incomingScope );

    // not part of resolve as we need the argumentFields
    if( outputSelector.isSwap() )
      return Fields.asDeclaration( incomingFields.subtract( argumentFields ) ).append( declaredFields );

    try
      {
      return Fields.resolve( outputSelector, Fields.asDeclaration( incomingFields ), declaredFields );
      }
    catch( TupleException exception )
      {
      throw new OperatorException( this, incomingFields, declaredFields, outputSelector, exception );
      }
    }

  Fields resolveArgumentSelector( Set<Scope> incomingScopes )
    {
    Fields argumentSelector = getArgumentSelector();

    try
      {
      Scope incomingScope = getFirst( incomingScopes );

      if( argumentSelector.isAll() )
        return resolveIncomingOperationArgumentFields( incomingScope );

      if( argumentSelector.isGroup() )
        return incomingScope.getOutGroupingFields();

      if( argumentSelector.isValues() )
        return incomingScope.getOutGroupingValueFields();

      return resolveIncomingOperationArgumentFields( incomingScope ).select( argumentSelector );
      }
    catch( FieldsResolverException exception )
      {
      throw new OperatorException( this, OperatorException.Kind.argument, exception.getSourceFields(), argumentSelector, exception );
      }
    catch( Exception exception )
      {
      throw new OperatorException( this, "unable to resolve argument selector: " + argumentSelector.printVerbose(), exception );
      }
    }

  Fields resolveDeclared( Set<Scope> incomingScopes, Fields arguments )
    {
    Fields fieldDeclaration = getFieldDeclaration();

    if( getOutputSelector().isReplace() )
      {
      if( arguments.isDefined() && fieldDeclaration.isDefined() && arguments.size() != fieldDeclaration.size() )
        throw new OperatorException( this, "during REPLACE both the arguments selector and field declaration must be the same size, arguments: " + arguments.printVerbose() + " declaration: " + fieldDeclaration.printVerbose() );

      if( fieldDeclaration.isArguments() ) // there is no type info, so inherit it
        return arguments;

      return arguments.project( fieldDeclaration );
      }

    try
      {
      Scope incomingScope = getFirst( incomingScopes );

      if( fieldDeclaration.isUnknown() )
        return fieldDeclaration;

      if( fieldDeclaration.isArguments() )
        return Fields.asDeclaration( arguments );

      if( fieldDeclaration.isAll() )
        return resolveIncomingOperationPassThroughFields( incomingScope );

      if( fieldDeclaration.isGroup() )
        return incomingScope.getOutGroupingFields();

      // VALUES is the diff between all fields and group fields
      if( fieldDeclaration.isValues() )
        return incomingScope.getOutGroupingValueFields();

      }
    catch( Exception exception )
      {
      throw new OperatorException( this, "could not resolve declared fields in:  " + this, exception );
      }

    return fieldDeclaration;
    }

  // OBJECT OVERRIDES

  @Override
  public String toString()
    {
    return super.toString() + "[" + operation + "]";
    }

  @Override
  protected void printInternal( StringBuffer buffer, Scope scope )
    {
    super.printInternal( buffer, scope );
    buffer.append( "[" );
    BaseOperation.printOperationInternal( operation, buffer, scope );
    buffer.append( "]" );
    }

  @Override
  public boolean isEquivalentTo( FlowElement element )
    {
    boolean equivalentTo = super.isEquivalentTo( element );

    if( !equivalentTo )
      return false;

    Operator operator = (Operator) element;

    equivalentTo = argumentSelector.equals( operator.argumentSelector );

    if( !equivalentTo )
      return false;

    if( !operation.equals( operator.operation ) )
      return false;

    equivalentTo = outputSelector.equals( operator.outputSelector );

    if( !equivalentTo )
      return false;

    return true;
    }

  @SuppressWarnings({"RedundantIfStatement"})
  public boolean equals( Object object )
    {
    if( this == object )
      return true;
    if( object == null || getClass() != object.getClass() )
      return false;
    if( !super.equals( object ) )
      return false;

    Operator operator = (Operator) object;

    if( argumentSelector != null ? !argumentSelector.equals( operator.argumentSelector ) : operator.argumentSelector != null )
      return false;
    if( operation != null ? !operation.equals( operator.operation ) : operator.operation != null )
      return false;
    if( outputSelector != null ? !outputSelector.equals( operator.outputSelector ) : operator.outputSelector != null )
      return false;

    return true;
    }

  @Override
  public int hashCode()
    {
    int result = super.hashCode();
    result = 31 * result + ( operation != null ? operation.hashCode() : 0 );
    result = 31 * result + ( argumentSelector != null ? argumentSelector.hashCode() : 0 );
    result = 31 * result + ( outputSelector != null ? outputSelector.hashCode() : 0 );
    return result;
    }
  }
TOP

Related Classes of cascading.pipe.Operator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.