class ValueMetaBase implements ValueMetaInterface {

  @Override
  public int compare( Object data1, Object data2 ) throws KettleValueException {
    boolean n1 = isNull( data1 );
    boolean n2 = isNull( data2 );

    if ( n1 && !n2 ) {
      if ( isSortedDescending() ) {
        // BACKLOG-14028
        return 1;
      } else {
        return -1;
      }
    }
    if ( !n1 && n2 ) {
      if ( isSortedDescending() ) {
        return -1;
      } else {
        return 1;
      }
    }
    if ( n1 && n2 ) {
      return 0;
    }

    int cmp = 0;
    switch ( getType() ) {
      case TYPE_STRING:
        // if (isStorageBinaryString() && identicalFormat &&
        // storageMetadata.isSingleByteEncoding()) return
        // compareBinaryStrings((byte[])data1, (byte[])data2); TODO
        String one = getString( data1 );
        String two = getString( data2 );

        if ( collatorDisabled ) {
          if ( caseInsensitive ) {
            cmp = one.compareToIgnoreCase( two );
          } else {
            cmp = one.compareTo( two );
          }
        } else {
          cmp = collator.compare( one, two );
        }
        break;

      case TYPE_INTEGER:
        // if (isStorageBinaryString() && identicalFormat) return
        // compareBinaryStrings((byte[])data1, (byte[])data2); TODO
        cmp = getInteger( data1 ).compareTo( getInteger( data2 ) );
        break;

      case TYPE_NUMBER:
        cmp = Double.compare( getNumber( data1 ).doubleValue(), getNumber( data2 ).doubleValue() );
        break;

      case TYPE_DATE:
        cmp = Long.valueOf( getDate( data1 ).getTime() ).compareTo( Long.valueOf( getDate( data2 ).getTime() ) );
        break;

      case TYPE_BIGNUMBER:
        cmp = getBigNumber( data1 ).compareTo( getBigNumber( data2 ) );
        break;

      case TYPE_BOOLEAN:
        if ( getBoolean( data1 ).booleanValue() == getBoolean( data2 ).booleanValue() ) {
          cmp = 0; // true == true, false == false
        } else if ( getBoolean( data1 ).booleanValue() && !getBoolean( data2 ).booleanValue() ) {
          cmp = 1; // true > false
        } else {
          cmp = -1; // false < true
        }
        break;

      case TYPE_BINARY:
        byte[] b1 = (byte[]) data1;
        byte[] b2 = (byte[]) data2;

        int length = b1.length < b2.length ? b1.length : b2.length;

        for ( int i = 0; i < length; i++ ) {
          cmp = b1[i] - b2[i];
          if ( cmp != 0 ) {
            cmp = cmp < 0 ? -1 : 1;
            break;
          }
        }

        cmp = b1.length - b2.length;

        break;
      default:
        throw new KettleValueException( toString() + " : Comparing values can not be done with data type : "
            + getType() );
    }

    if ( isSortedDescending() ) {
      return -cmp;
    } else {
      return cmp;
    }
  }

  public  ValueMetaBase();
  public  ValueMetaBase( String name );
  public  ValueMetaBase( String name, int type );
  public  ValueMetaBase( String name, int type, int length, int precision );
  public  ValueMetaBase( Node node );
  @Deprecated public  ValueMetaBase( DataInputStream inputStream );
  @Deprecated public  ValueMetaBase( String name, int type, int storageType );

}