StringBuilder codeForComplexFieldExtraction(Descriptors.FieldDescriptor desc, String fieldNameInCode,
      String javaFieldType, int indent, int varNum, String decoderMethod, String additionalExtractions) {
    StringBuilder code = new StringBuilder();
    if (StringUtils.isBlank(additionalExtractions)) {
      additionalExtractions = "";
    }
    if (desc.isRepeated()) {
      varNum++;
      String listVarName = "list" + varNum;
      code.append(completeLine(String.format("List<Object> %s = new ArrayList<>()", listVarName), indent));
      code.append(addIndent(
          String.format("for (%s row: msg.%s()) {", javaFieldType, getProtoFieldListMethodName(fieldNameInCode)),
          indent));
      if (!StringUtils.isBlank(decoderMethod)) {
        code.append(completeLine(
            String.format("%s.add(%s(row%s))", listVarName, decoderMethod, additionalExtractions),
            ++indent));
      } else {
        code.append(completeLine(String.format("%s.add(row%s)", listVarName, additionalExtractions), ++indent));
      }
      code.append(addIndent("}", --indent));
      code.append(addIndent(String.format("if (!%s.isEmpty()) {", listVarName), indent));
      code.append(completeLine(
          String.format("msgMap.put(\"%s\", %s.toArray())", desc.getName(), listVarName),
          ++indent));
      code.append(addIndent("}", --indent));
    } else if (desc.hasPresence()) {
      code.append(addIndent(String.format("if (msg.%s()) {", hasPresenceMethodName(fieldNameInCode)), indent));
      code.append(completeLine(putFieldInMsgMapCode(
          desc.getName(), getProtoFieldMethodName(fieldNameInCode), decoderMethod, additionalExtractions),
          ++indent));
      code.append(addIndent("}", --indent));
    } else {
      code.append(completeLine(putFieldInMsgMapCode(
          desc.getName(), getProtoFieldMethodName(fieldNameInCode), decoderMethod, additionalExtractions),
          indent));
    }
    return code;
  }
@Test
    public void testCodeForComplexFieldExtractionRepeated() {
        MessageCodeGen messageCodeGen = new MessageCodeGen();
        // Repeated decoder method is non-empty
        Descriptors.FieldDescriptor fd = ComplexTypes.TestMessage.getDescriptor()
            .findFieldByName(REPEATED_NESTED_MESSAGES);
        String fieldNameInCode = ProtobufInternalUtils.underScoreToCamelCase(fd.getName(), true);
        String javaType = ProtoBufUtils.getFullJavaName(fd.getMessageType());
        String expectedCode = "  List<Object> list2 = new ArrayList<>();\n"
            + "  for (org.apache.pinot.plugin.inputformat.protobuf.ComplexTypes.TestMessage.NestedMessage "
            + "row: msg.getRepeatedNestedMessagesList()) {\n"
            + "    list2.add(decodeNestedMessage(row));\n"
            + "  }\n"
            + "  if (!list2.isEmpty()) {\n"
            + "    msgMap.put(\"repeated_nested_messages\", list2.toArray());\n"
            + "  }\n";
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(fd, fieldNameInCode, javaType, 1, 1,
                "decodeNestedMessage", "").toString(), expectedCode);
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(fd, fieldNameInCode, javaType, 1, 1,
                "decodeNestedMessage", null).toString(), expectedCode);

        // Repeated both decoder methods and additional extractions present
        expectedCode = "  List<Object> list2 = new ArrayList<>();\n"
            + "  for (org.apache.pinot.plugin.inputformat.protobuf.ComplexTypes.TestMessage.NestedMessage "
            + "row: msg.getRepeatedNestedMessagesList()) {\n"
            + "    list2.add(decodeNestedMessage(row.toString()));\n"
            + "  }\n"
            + "  if (!list2.isEmpty()) {\n"
            + "    msgMap.put(\"repeated_nested_messages\", list2.toArray());\n"
            + "  }\n";
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(fd, fieldNameInCode, javaType, 1, 1,
            "decodeNestedMessage", ".toString()").toString(), expectedCode);


        // Repeated decoder method is non empty
        fd = ComplexTypes.TestMessage.getDescriptor().findFieldByName(REPEATED_BYTES);
        fieldNameInCode = ProtobufInternalUtils.underScoreToCamelCase(fd.getName(), true);
        javaType = "String";
        expectedCode = "  List<Object> list2 = new ArrayList<>();\n"
            + "  for (String row: msg.getRepeatedBytesList()) {\n"
            + "    list2.add(row.name());\n"
            + "  }\n"
            + "  if (!list2.isEmpty()) {\n"
            + "    msgMap.put(\"repeated_bytes\", list2.toArray());\n"
            + "  }\n";
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(fd, fieldNameInCode, javaType, 1, 1,
                "", ".name()").toString(), expectedCode);
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(fd, fieldNameInCode, javaType, 1, 1,
                null, ".name()").toString(), expectedCode);
    }