public Value hexToByteDecode() throws KettleValueException {
    setType( VALUE_TYPE_STRING );
    if ( isNull() ) {
      return this;
    }

    setValue( getString() );

    String hexString = getString();

    int len = hexString.length();
    char[] chArray = new char[( len + 1 ) / 2];
    boolean evenByte = true;
    int nextByte = 0;

    // we assume a leading 0 if the length is not even.
    if ( ( len % 2 ) == 1 ) {
      evenByte = false;
    }

    int nibble;
    int i, j;
    for ( i = 0, j = 0; i < len; i++ ) {
      char c = hexString.charAt( i );

      if ( ( c >= '0' ) && ( c <= '9' ) ) {
        nibble = c - '0';
      } else if ( ( c >= 'A' ) && ( c <= 'F' ) ) {
        nibble = c - 'A' + 0x0A;
      } else if ( ( c >= 'a' ) && ( c <= 'f' ) ) {
        nibble = c - 'a' + 0x0A;
      } else {
        throw new KettleValueException( "invalid hex digit '" + c + "'." );
      }

      if ( evenByte ) {
        nextByte = ( nibble << 4 );
      } else {
        nextByte += nibble;
        chArray[j] = (char) nextByte;
        j++;
      }

      evenByte = !evenByte;
    }
    setValue( new String( chArray ) );

    return this;
  }
@Test
  public void testHexToByteDecode() throws KettleValueException {
    Value vs1 = new Value( "Name1", Value.VALUE_TYPE_INTEGER );

    vs1.setValue( "6120622063" );
    vs1.hexToByteDecode();
    assertEquals( "a b c", vs1.getString() );

    vs1.setValue( "4161426243643039207A5A2E3F2F" );
    vs1.hexToByteDecode();
    assertEquals( "AaBbCd09 zZ.?/", vs1.getString() );

    vs1.setValue( "4161426243643039207a5a2e3f2f" );
    vs1.hexToByteDecode();
    assertEquals( "AaBbCd09 zZ.?/", vs1.getString() );

    // leading 0 if odd.
    vs1.setValue( "F6120622063" );
    vs1.hexToByteDecode();
    assertEquals( "\u000fa b c", vs1.getString() );

    try {
      vs1.setValue( "g" );
      vs1.hexToByteDecode();
      fail( "Expected KettleValueException" );
    } catch ( KettleValueException ex ) {
    }
  }