@Override
  public DirectByteBuffer[] getData() {
    try {
      if (buffer == null) {
        if (msg_type == REQUEST_MESSAGE_TYPE_ID) {
          Map<Object, Object> map = new HashMap<Object, Object>();
          map.put("msg_type", msg_type);
          map.put("piece", piece);
          buffer =
              MessagingUtil.convertPayloadToBencodedByteStream(
                  map, DirectByteBuffer.AL_MSG_UT_METADATA);
        } else if (msg_type == DATA_MESSAGE_TYPE_ID) {
          Map<Object, Object> map = new HashMap<Object, Object>();
          map.put("msg_type", msg_type);
          map.put("piece", piece);
          map.put("total_size", total_size);
          byte[] mapPayload = BEncoder.encode(map);
          buffer =
              DirectByteBufferPool.getBuffer(
                  DirectByteBuffer.AL_MSG_UT_METADATA, mapPayload.length + metadata.length);
          buffer.put(DirectByteBuffer.SS_MSG, mapPayload);
          buffer.put(DirectByteBuffer.SS_MSG, metadata);
          buffer.flip(DirectByteBuffer.SS_MSG);
        } else if (msg_type == REJECT_MESSAGE_TYPE_ID) {
          Map<Object, Object> map = new HashMap<Object, Object>();
          map.put("msg_type", msg_type);
          map.put("piece", piece);
          buffer =
              MessagingUtil.convertPayloadToBencodedByteStream(
                  map, DirectByteBuffer.AL_MSG_UT_METADATA);
        } else {
          if (Logger.isEnabled()) {
            Logger.log(
                new LogEvent(
                    LOGID, LogEvent.LT_ERROR, "METADATA (UT): No valid msg_type=" + msg_type));
          }
          return null;
        }
      }

      return new DirectByteBuffer[] {buffer};
    } catch (Throwable e) {
      // what is the best way to handle this error?
      if (Logger.isEnabled()) {
        Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "METADATA (UT)", e));
      }
      return new DirectByteBuffer[0];
    }
  }
  @Override
  public Message deserialize(DirectByteBuffer data, byte version) throws MessageException {
    try {
      int pos = data.position(DirectByteBuffer.SS_MSG);
      byte[] raw = new byte[data.remaining(DirectByteBuffer.SS_MSG)];
      data.get(DirectByteBuffer.SS_MSG, raw);
      data.position(DirectByteBuffer.SS_MSG, pos);
      Map<?, ?> map = MessagingUtil.convertBencodedByteStreamToPayload(data, 2, getID());

      int msg_type = ((Long) map.get("msg_type")).intValue();
      int piece = ((Long) map.get("piece")).intValue();
      if (msg_type == REQUEST_MESSAGE_TYPE_ID) {
        return new UTMetadata(msg_type, piece, 0, null, (byte) 1);
      } else if (msg_type == DATA_MESSAGE_TYPE_ID) {
        int total_size = ((Long) map.get("total_size")).intValue();
        int offset = BEncoder.encode(map).length;
        byte[] metadata = new byte[raw.length - offset];
        System.arraycopy(raw, offset, metadata, 0, metadata.length);
        return new UTMetadata(msg_type, piece, total_size, metadata, (byte) 1);
      } else if (msg_type == REJECT_MESSAGE_TYPE_ID) {
        return new UTMetadata(msg_type, piece, 0, null, (byte) 1);
      }

      // what is the best way to handle this error?
      if (Logger.isEnabled()) {
        Logger.log(
            new LogEvent(LOGID, LogEvent.LT_ERROR, "METADATA (UT): No valid msg_type=" + msg_type));
      }

      return null;
    } catch (Throwable e) {
      // what is the best way to handle this error?
      if (Logger.isEnabled()) {
        Logger.log(new LogEvent(LOGID, LogEvent.LT_ERROR, "METADATA (UT)", e));
      }
      return null;
    }
  }