private void validateAndTransform(Message inMsg, int msgOffset) throws IOException {
    if (transformers == null || transformers.isEmpty()) {
      // Write the message without any transformations.
      sievedMessageInfoList.add(inMsg.getMessageInfo());
      msgStreamList.add(inMsg.getStream());
    } else {
      long sieveStartTime = SystemTime.getInstance().milliseconds();
      Message msg = inMsg;
      TransformationOutput output = null;
      for (Transformer transformer : transformers) {
        output = transformer.transform(msg);
        if (output.getException() != null || output.getMsg() == null) {
          break;
        } else {
          msg = output.getMsg();
        }
      }
      if (output.getException() != null) {
        if (output.getException() instanceof MessageFormatException) {
          logger.error(
              "Error validating/transforming the message at {} with messageInfo {} and hence skipping the message",
              msgOffset, inMsg.getMessageInfo(), output.getException());
          numInvalidMessages += 1;
          messageSievingCorruptMessagesDiscardedCount.inc();
          invalidMessages.add(inMsg.getMessageInfo());
        } else {
          throw new IOException("Encountered exception during transformation", output.getException());
        }
      } else if (output.getMsg() == null) {
        logger.trace("Transformation is on, and the message with id {} does not have a replacement and was discarded.",
            inMsg.getMessageInfo().getStoreKey());
        hasDeprecatedMessages = true;
        messageSievingDeprecatedMessagesDiscardedCount.inc();
      } else {
        MessageInfo tfmMsgInfo = output.getMsg().getMessageInfo();
        sievedMessageInfoList.add(tfmMsgInfo);
        msgStreamList.add(output.getMsg().getStream());
        logger.trace("Original message length {}, transformed bytes read {}", inMsg.getMessageInfo().getSize(),
            tfmMsgInfo.getSize());
      }
      singleMessageSieveTime.update(SystemTime.getInstance().milliseconds() - sieveStartTime);
    }
  }
Validates and potentially transforms the given input stream consisting of message data. It does so using the list
of {@link Transformer}s associated with this instance.
message corruption and acceptable formats.
@param inMsg the original {@link Message} that needs to be validated and possibly transformed.
@param msgOffset the offset of the message in the stream.
@throws IOException if an exception was encountered reading or writing bytes to/from streams.
ambry-messageformat/src/main/java/com/github/ambry/messageformat/MessageSievingInputStream.java