class Validator extends BaseStep implements StepInterface {

  void readSourceValuesFromInfoSteps() throws KettleStepException {
    Map<String, Integer> inputStepWasProcessed = new HashMap<>();
    for ( int i = 0; i < meta.getValidations().size(); i++ ) {
      Validation field = meta.getValidations().get( i );
      List<StreamInterface> streams = meta.getStepIOMeta().getInfoStreams();

      // If we need to source the allowed values data from a different step, we do this here as well
      //
      if ( field.isSourcingValues() ) {
        if ( streams.get( i ).getStepMeta() == null ) {
          throw new KettleStepException(
            "There is no valid source step specified for the allowed values of validation ["
              + field.getName() + "]" );
        }
        if ( Utils.isEmpty( field.getSourcingField() ) ) {
          throw new KettleStepException(
            "There is no valid source field specified for the allowed values of validation ["
              + field.getName() + "]" );
        }

        // Still here : OK, read the data from the specified step...
        // The data is stored in data.listValues[i] and data.constantsMeta
        //
        String stepName = streams.get( i ).getStepname();
        if ( inputStepWasProcessed.containsKey( stepName ) ) {
          // step was processed for other StreamInterface
          data.listValues[ i ] = data.listValues[ inputStepWasProcessed.get( stepName ) ];
          data.constantsMeta[ i ] = data.constantsMeta[ inputStepWasProcessed.get( stepName ) ];
          continue;
        }
        RowSet allowedRowSet = findInputRowSet( stepName );
        int fieldIndex = -1;
        List<Object> allowedValues = new ArrayList<Object>();
        Object[] allowedRowData = getRowFrom( allowedRowSet );
        while ( allowedRowData != null ) {
          RowMetaInterface allowedRowMeta = allowedRowSet.getRowMeta();
          if ( fieldIndex < 0 ) {
            fieldIndex = allowedRowMeta.indexOfValue( field.getSourcingField() );
            if ( fieldIndex < 0 ) {
              throw new KettleStepException( "Source field ["
                + field.getSourcingField() + "] is not found in the source row data" );
            }
            data.constantsMeta[ i ] = allowedRowMeta.getValueMeta( fieldIndex );
          }
          Object allowedValue = allowedRowData[ fieldIndex ];
          if ( allowedValue != null ) {
            allowedValues.add( allowedValue );
          }

          // Grab another row too...
          //
          allowedRowData = getRowFrom( allowedRowSet );
        }
        // Set the list values in the data block...
        //
        data.listValues[ i ] = allowedValues.toArray( new Object[ allowedValues.size() ] );
        inputStepWasProcessed.put( stepName, i );
      }
    }
  }

  public  Validator( StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
                    Trans trans );

}