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 testCodeForComplexFieldExtractionNonRepeated() {
        MessageCodeGen messageCodeGen = new MessageCodeGen();
        // Message type
        Descriptors.FieldDescriptor fd = ComplexTypes.TestMessage.getDescriptor().findFieldByName(NESTED_MESSAGE);
        String fieldNameInCode = ProtobufInternalUtils.underScoreToCamelCase(fd.getName(), true);
        String javaType = ProtoBufUtils.getFullJavaName(fd.getMessageType());
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "decodeNestedMessage", "").toString(),
            "  if (msg.hasNestedMessage()) {\n"
                + "    msgMap.put(\"nested_message\", decodeNestedMessage(msg.getNestedMessage()));\n" + "  }\n");
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "decodeNestedMessage", null).toString(),
            "  if (msg.hasNestedMessage()) {\n"
                + "    msgMap.put(\"nested_message\", decodeNestedMessage(msg.getNestedMessage()));\n" + "  }\n");

        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "decodeNestedMessage", ".toString()").toString(),
            "  if (msg.hasNestedMessage()) {\n"
                + "    msgMap.put(\"nested_message\", decodeNestedMessage(msg.getNestedMessage().toString()));\n"
                + "  }\n");

        // Complex type with no presence i.e Scalar type with additional Extractions eg bytes, enum, bool
        fd = ComplexTypes.TestMessage.getDescriptor().findFieldByName(BOOL_FIELD);
        fieldNameInCode = ProtobufInternalUtils.underScoreToCamelCase(fd.getName(), true);
        javaType = "String";
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "String.valueOf", "").toString(),
            "  msgMap.put(\"bool_field\", String.valueOf(msg.getBoolField()));\n");
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "String.valueOf", null).toString(),
            "  msgMap.put(\"bool_field\", String.valueOf(msg.getBoolField()));\n");

        fd = ComplexTypes.TestMessage.getDescriptor().findFieldByName(ENUM_FIELD);
        fieldNameInCode = ProtobufInternalUtils.underScoreToCamelCase(fd.getName(), true);
        javaType = "String";
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "", ".name()").toString(),
            "  msgMap.put(\"enum_field\", msg.getEnumField().name());\n");
        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, null, ".name()").toString(),
            "  msgMap.put(\"enum_field\", msg.getEnumField().name());\n");

        assertEquals(messageCodeGen.codeForComplexFieldExtraction(
            fd, fieldNameInCode, javaType, 1, 1, "String.valueOf", ".name()").toString(),
            "  msgMap.put(\"enum_field\", String.valueOf(msg.getEnumField().name()));\n");
    }