plugins/transforms/selectvalues/src/main/java/org/apache/hop/pipeline/transforms/selectvalues/SelectValues.java
private synchronized Object[] selectValues( IRowMeta rowMeta, Object[] rowData ) throws HopValueException {
    if ( data.firstselect ) {
      data.firstselect = false;

      // We need to create a new meta-data row to drive the output
      // We also want to know the indexes of the selected fields in the source row.
      //
      data.fieldnrs = new int[ meta.getSelectFields().length ];
      for ( int i = 0; i < data.fieldnrs.length; i++ ) {
        data.fieldnrs[ i ] = rowMeta.indexOfValue( meta.getSelectFields()[ i ].getName() );
        if ( data.fieldnrs[ i ] < 0 ) {
          logError( BaseMessages.getString( PKG, "SelectValues.Log.CouldNotFindField", meta.getSelectFields()[ i ]
            .getName() ) );
          setErrors( 1 );
          stopAll();
          return null;
        }
      }

      // Check for doubles in the selected fields... AFTER renaming!!
      //
      int[] cnt = new int[ meta.getSelectFields().length ];
      for ( int i = 0; i < meta.getSelectFields().length; i++ ) {
        cnt[ i ] = 0;
        for ( int j = 0; j < meta.getSelectFields().length; j++ ) {
          String one = Const.NVL( meta.getSelectFields()[ i ].getRename(), meta.getSelectFields()[ i ].getName() );
          String two = Const.NVL( meta.getSelectFields()[ j ].getRename(), meta.getSelectFields()[ j ].getName() );
          if ( one.equals( two ) ) {
            cnt[ i ]++;
          }

          if ( cnt[ i ] > 1 ) {
            logError( BaseMessages.getString( PKG, "SelectValues.Log.FieldCouldNotSpecifiedMoreThanTwice", one ) );
            setErrors( 1 );
            stopAll();
            return null;
          }
        }
      }

      // See if we need to include (and sort) the non-specified fields as well...
      //
      if ( meta.isSelectingAndSortingUnspecifiedFields() ) {
        // Select the unspecified fields.
        // Sort the fields
        // Add them after the specified fields...
        //
        List<String> extra = new ArrayList<>();
        ArrayList<Integer> unspecifiedKeyNrs = new ArrayList<>();
        for ( int i = 0; i < rowMeta.size(); i++ ) {
          String fieldName = rowMeta.getValueMeta( i ).getName();
          if ( Const.indexOfString( fieldName, meta.getSelectName() ) < 0 ) {
            extra.add( fieldName );
          }
        }
        Collections.sort( extra );
        for ( String fieldName : extra ) {
          int index = rowMeta.indexOfValue( fieldName );
          unspecifiedKeyNrs.add( index );
        }

        // Create the extra field list...
        //
        data.extraFieldnrs = new int[ unspecifiedKeyNrs.size() ];
        for ( int i = 0; i < data.extraFieldnrs.length; i++ ) {
          data.extraFieldnrs[ i ] = unspecifiedKeyNrs.get( i );
        }
      } else {
        data.extraFieldnrs = new int[] {};
      }
    }

    // Create a new output row
    Object[] outputData = new Object[ data.selectRowMeta.size() ];
    int outputIndex = 0;

    // Get the field values
    //
    for ( int idx : data.fieldnrs ) {
      // Normally this can't happen, except when streams are mixed with different
      // number of fields.
      //
      if ( idx < rowMeta.size() ) {
        IValueMeta valueMeta = rowMeta.getValueMeta( idx );

        // TODO: Clone might be a 'bit' expensive as it is only needed in case you want to copy a single field to 2 or
        // more target fields.
        // And even then it is only required for the last n-1 target fields.
        // Perhaps we can consider the requirements for cloning at init(), store it in a boolean[] and just consider
        // this at runtime
        //
        outputData[ outputIndex++ ] = valueMeta.cloneValueData( rowData[ idx ] );
      } else {
        if ( log.isDetailed() ) {
          logDetailed( BaseMessages.getString( PKG, "SelectValues.Log.MixingStreamWithDifferentFields" ) );
        }
      }
    }

    // Do we need to drag the rest of the row also in there?
    //
    for ( int idx : data.extraFieldnrs ) {
      outputData[ outputIndex++ ] = rowData[ idx ]; // always just a copy, can't be specified twice.
    }

    return outputData;
  }
/**
   * Only select the values that are still needed...
   * <p/>
   * Put the values in the right order...
   * <p/>
   * Change the meta-data information if needed...
   * <p/>
   *
   * @param rowMeta The row to manipulate
   * @param rowData the row data to manipulate
   * @return true if everything went well, false if we need to stop because of an error!
   */
Only select the values that are still needed

Put the values in the right order

Change the meta-data information if needed


@param rowMeta The row to manipulate
@param rowData the row data to manipulate
@return true if everything went well, false if we need to stop because of an error!
Only select the values that are still needed Put the values in the right order Change the meta - data information if needed @param rowMeta The row to manipulate @param rowData the row data to manipulate @return true if everything went well false if we need to stop because of an error!
private synchronized Object[] selectValues( IRowMeta rowMeta, Object[] rowData ) throws HopValueException {
    if ( data.firstselect ) {
      data.firstselect = false;
      data.fieldnrs = new int[ meta.getSelectFields().length ];
      for ( int i = 0; i < data.fieldnrs.length; i++ ) {
        data.fieldnrs[ i ] = rowMeta.indexOfValue( meta.getSelectFields()[ i ].getName() );
        if ( data.fieldnrs[ i ] < 0 ) {
          logError( BaseMessages.getString( PKG, "SelectValues.Log.CouldNotFindField", meta.getSelectFields()[ i ]
            .getName() ) );
          setErrors( 1 );
          stopAll();
          return null;
        }
      }
       Check for doubles in the selected fields... AFTER renaming!!
      int[] cnt = new int[ meta.getSelectFields().length ];
      for ( int i = 0; i < meta.getSelectFields().length; i++ ) {
        cnt[ i ] = 0;
        for ( int j = 0; j < meta.getSelectFields().length; j++ ) {
          String one = Const.NVL( meta.getSelectFields()[ i ].getRename(), meta.getSelectFields()[ i ].getName() );
          String two = Const.NVL( meta.getSelectFields()[ j ].getRename(), meta.getSelectFields()[ j ].getName() );
          if ( one.equals( two ) ) {
            cnt[ i ]++;
          }
          if ( cnt[ i ] > 1 ) {
            logError( BaseMessages.getString( PKG, "SelectValues.Log.FieldCouldNotSpecifiedMoreThanTwice", one ) );
            setErrors( 1 );
            stopAll();
            return null;
          }
        }
      }
       See if we need to include (and sort) the non-specified fields as well...
      if ( meta.isSelectingAndSortingUnspecifiedFields() ) {
         Select the unspecified fields.
         Sort the fields
         Add them after the specified fields...
        List<String> extra = new ArrayList<>();
        ArrayList<Integer> unspecifiedKeyNrs = new ArrayList<>();
        for ( int i = 0; i < rowMeta.size(); i++ ) {
          String fieldName = rowMeta.getValueMeta( i ).getName();
          if ( Const.indexOfString( fieldName, meta.getSelectName() ) < 0 ) {
            extra.add( fieldName );
          }
        }
        Collections.sort( extra );
        for ( String fieldName : extra ) {
          int index = rowMeta.indexOfValue( fieldName );
          unspecifiedKeyNrs.add( index );
        }
         Create the extra field list...
        data.extraFieldnrs = new int[ unspecifiedKeyNrs.size() ];
        for ( int i = 0; i < data.extraFieldnrs.length; i++ ) {
          data.extraFieldnrs[ i ] = unspecifiedKeyNrs.get( i );
        }
      } else {
        data.extraFieldnrs = new int[] {};
      }
    }
     Create a new output row
    Object[] outputData = new Object[ data.selectRowMeta.size() ];
    int outputIndex = 0;
     Get the field values
    for ( int idx : data.fieldnrs ) {
       Normally this can't happen, except when streams are mixed with different
       number of fields.
      if ( idx < rowMeta.size() ) {
        IValueMeta valueMeta = rowMeta.getValueMeta( idx );
         TODO: Clone might be a 'bit' expensive as it is only needed in case you want to copy a single field to 2 or
         more target fields.
         And even then it is only required for the last n-1 target fields.
         Perhaps we can consider the requirements for cloning at init(), store it in a boolean[] and just consider
         this at runtime
        outputData[ outputIndex++ ] = valueMeta.cloneValueData( rowData[ idx ] );
      } else {
        if ( log.isDetailed() ) {
          logDetailed( BaseMessages.getString( PKG, "SelectValues.Log.MixingStreamWithDifferentFields" ) );
        }
      }
    }
     Do we need to drag the rest of the row also in there?
    for ( int idx : data.extraFieldnrs ) {
      outputData[ outputIndex++ ] = rowData[ idx ];  always just a copy, can't be specified twice.
    }
    return outputData;
  }
private synchronized Object [ ] selectValues ( IRowMeta rowMeta , Object [ ] rowData ) throws HopValueException { if ( data . firstselect ) { data . firstselect = false ; data . fieldnrs = new int [ meta . getSelectFields ( ) . length ] ; for ( int i = 0 ; i < data . fieldnrs . length ; i ++ ) { data . fieldnrs [ i ] = rowMeta . indexOfValue ( meta . getSelectFields ( ) [ i ] . getName ( ) ) ; if ( data . fieldnrs [ i ] < 0 ) { logError ( BaseMessages . getString ( PKG , "SelectValues.Log.CouldNotFindField" , meta . getSelectFields ( ) [ i ] . getName ( ) ) ) ; setErrors ( 1 ) ; stopAll ( ) ; return null ; } } int [ ] cnt = new int [ meta . getSelectFields ( ) . length ] ; for ( int i = 0 ; i < meta . getSelectFields ( ) . length ; i ++ ) { cnt [ i ] = 0 ; for ( int j = 0 ; j < meta . getSelectFields ( ) . length ; j ++ ) { String one = Const . NVL ( meta . getSelectFields ( ) [ i ] . getRename ( ) , meta . getSelectFields ( ) [ i ] . getName ( ) ) ; String two = Const . NVL ( meta . getSelectFields ( ) [ j ] . getRename ( ) , meta . getSelectFields ( ) [ j ] . getName ( ) ) ; if ( one . equals ( two ) ) { cnt [ i ] ++ ; } if ( cnt [ i ] > 1 ) { logError ( BaseMessages . getString ( PKG , "SelectValues.Log.FieldCouldNotSpecifiedMoreThanTwice" , one ) ) ; setErrors ( 1 ) ; stopAll ( ) ; return null ; } } } if ( meta . isSelectingAndSortingUnspecifiedFields ( ) ) { List < String > extra = new ArrayList < > ( ) ; ArrayList < Integer > unspecifiedKeyNrs = new ArrayList < > ( ) ; for ( int i = 0 ; i < rowMeta . size ( ) ; i ++ ) { String fieldName = rowMeta . getValueMeta ( i ) . getName ( ) ; if ( Const . indexOfString ( fieldName , meta . getSelectName ( ) ) < 0 ) { extra . add ( fieldName ) ; } } Collections . sort ( extra ) ; for ( String fieldName : extra ) { int index = rowMeta . indexOfValue ( fieldName ) ; unspecifiedKeyNrs . add ( index ) ; } data . extraFieldnrs = new int [ unspecifiedKeyNrs . size ( ) ] ; for ( int i = 0 ; i < data . extraFieldnrs . length ; i ++ ) { data . extraFieldnrs [ i ] = unspecifiedKeyNrs . get ( i ) ; } } else { data . extraFieldnrs = new int [ ] { } ; } } Object [ ] outputData = new Object [ data . selectRowMeta . size ( ) ] ; int outputIndex = 0 ; for ( int idx : data . fieldnrs ) { if ( idx < rowMeta . size ( ) ) { IValueMeta valueMeta = rowMeta . getValueMeta ( idx ) ; outputData [ outputIndex ++ ] = valueMeta . cloneValueData ( rowData [ idx ] ) ; } else { if ( log . isDetailed ( ) ) { logDetailed ( BaseMessages . getString ( PKG , "SelectValues.Log.MixingStreamWithDifferentFields" ) ) ; } } } for ( int idx : data . extraFieldnrs ) { outputData [ outputIndex ++ ] = rowData [ idx ] ; } return outputData ; }
Only select the values that are still needed...
 <p/>
 Put the values in the right order...
 <p/>
 Change the meta-data information if needed...
 <p/>
Only select the values that are still needed ... <p / > Put the values in the right order ... <p / > Change the meta - data information if needed ... <p / >
// We need to create a new meta-data row to drive the output // We also want to know the indexes of the selected fields in the source row. // // Check for doubles in the selected fields... AFTER renaming!! // // See if we need to include (and sort) the non-specified fields as well... // // Select the unspecified fields. // Sort the fields // Add them after the specified fields... // // Create the extra field list... // // Create a new output row // Get the field values // // Normally this can't happen, except when streams are mixed with different // number of fields. // // TODO: Clone might be a 'bit' expensive as it is only needed in case you want to copy a single field to 2 or // more target fields. // And even then it is only required for the last n-1 target fields. // Perhaps we can consider the requirements for cloning at init(), store it in a boolean[] and just consider // this at runtime // // Do we need to drag the rest of the row also in there? // // always just a copy, can't be specified twice.