class MemoryGroupByMeta extends BaseTransformMeta implements ITransformMeta<MemoryGroupBy, MemoryGroupByData> {

  @Override
  public void getFields( IRowMeta r, String origin, IRowMeta[] info, TransformMeta nextTransform,
                         IVariables variables, IHopMetadataProvider metadataProvider ) {
    // Check compatibility mode
    boolean compatibilityMode = ValueMetaBase.convertStringToBoolean(
      variables.getVariable( Const.HOP_COMPATIBILITY_MEMORY_GROUP_BY_SUM_AVERAGE_RETURN_NUMBER_TYPE, "N" ) );

    // re-assemble a new row of metadata
    //
    IRowMeta fields = new RowMeta();

    // Add the grouping fields in the correct order...
    //
    for ( int i = 0; i < groupField.length; i++ ) {
      IValueMeta valueMeta = r.searchValueMeta( groupField[ i ] );
      if ( valueMeta != null ) {
        valueMeta.setStorageType( IValueMeta.STORAGE_TYPE_NORMAL );
        fields.addValueMeta( valueMeta );
      }
    }

    // Re-add aggregates
    //
    for ( int i = 0; i < subjectField.length; i++ ) {
      IValueMeta subj = r.searchValueMeta( subjectField[ i ] );
      if ( subj != null || aggregateType[ i ] == TYPE_GROUP_COUNT_ANY ) {
        String value_name = aggregateField[ i ];
        int value_type = IValueMeta.TYPE_NONE;
        int length = -1;
        int precision = -1;

        switch ( aggregateType[ i ] ) {
          case TYPE_GROUP_FIRST:
          case TYPE_GROUP_LAST:
          case TYPE_GROUP_FIRST_INCL_NULL:
          case TYPE_GROUP_LAST_INCL_NULL:
          case TYPE_GROUP_MIN:
          case TYPE_GROUP_MAX:
            value_type = subj.getType();
            break;
          case TYPE_GROUP_COUNT_DISTINCT:
          case TYPE_GROUP_COUNT_ALL:
          case TYPE_GROUP_COUNT_ANY:
            value_type = IValueMeta.TYPE_INTEGER;
            break;
          case TYPE_GROUP_CONCAT_COMMA:
            value_type = IValueMeta.TYPE_STRING;
            break;
          case TYPE_GROUP_SUM:
          case TYPE_GROUP_AVERAGE:
            if ( !compatibilityMode && subj.isNumeric() ) {
              value_type = subj.getType();
            } else {
              value_type = IValueMeta.TYPE_NUMBER;
            }
            break;
          case TYPE_GROUP_MEDIAN:
          case TYPE_GROUP_PERCENTILE:
          case TYPE_GROUP_STANDARD_DEVIATION:
            value_type = IValueMeta.TYPE_NUMBER;
            break;
          case TYPE_GROUP_CONCAT_STRING:
            value_type = IValueMeta.TYPE_STRING;
            break;
          default:
            break;
        }

        if ( aggregateType[ i ] == TYPE_GROUP_COUNT_ALL
          || aggregateType[ i ] == TYPE_GROUP_COUNT_DISTINCT || aggregateType[ i ] == TYPE_GROUP_COUNT_ANY ) {
          length = IValueMeta.DEFAULT_INTEGER_LENGTH;
          precision = 0;
        } else if ( aggregateType[ i ] == TYPE_GROUP_SUM
          && value_type != IValueMeta.TYPE_INTEGER && value_type != IValueMeta.TYPE_NUMBER
          && value_type != IValueMeta.TYPE_BIGNUMBER ) {
          // If it ain't numeric, we change it to Number
          //
          value_type = IValueMeta.TYPE_NUMBER;
          precision = -1;
          length = -1;
        }

        if ( value_type != IValueMeta.TYPE_NONE ) {
          IValueMeta v;
          try {
            v = ValueMetaFactory.createValueMeta( value_name, value_type );
          } catch ( HopPluginException e ) {
            log.logError(
              BaseMessages.getString( PKG, "MemoryGroupByMeta.Exception.UnknownValueMetaType" ), value_type, e );
            v = new ValueMetaNone( value_name );
          }
          v.setOrigin( origin );
          v.setLength( length, precision );

          if ( subj != null ) {
            v.setConversionMask( subj.getConversionMask() );
          }

          fields.addValueMeta( v );
        }
      }
    }

    // Now that we have all the fields we want, we should clear the original row and replace the values...
    //
    r.clear();
    r.addRowMeta( fields );
  }

  public  MemoryGroupByMeta();

}