class_docstr: A class for writing training data to a file.
docstr: Generates text for a message object.
  
  Args:
      message: A message
  
  Returns:
      The text of the message, annotated with the entity data that is contained
      in the message
docstr_tok: ["Generates","text","for","a","message","object",".","Args",":","message",":","A","message","Returns",":","The","text","of","the","message",",","annotated","with","the","entity","data","that","is","contained","in","the","message"]
code: def generate_message(message: Dict[Text, Any]) -> Text:
      """Generates text for a message object.
  
      Args:
          message: A message
  
      Returns:
          The text of the message, annotated with the entity data that is contained
          in the message
      """
      md = ""
      text = message.get("text", "")
  
      pos = 0
  
      # If a message was prefixed with `INTENT_MESSAGE_PREFIX` (this can only happen
      # in end-to-end stories) then potential entities were provided in the json
      # format (e.g. `/greet{"name": "Rasa"}) and we don't have to add the NLU
      # entity annotation
      if not text.startswith(INTENT_MESSAGE_PREFIX):
          entities = message.get("entities", [])
          entities_with_start_and_end = [
              e for e in entities if "start" in e and "end" in e
          ]
          # Multiple entities can share the same position span. To account for that,
          # group all entities by their start positions
          aggregated_entities: Dict[
              int, List[Dict[Text, Any]]
          ] = defaultdict(list)
          for entity in entities_with_start_and_end:
              aggregated_entities[entity["start"]].append(entity)
  
          _raise_on_same_start_and_different_end_positions(
              aggregated_entities
          )
  
          for start, entities in sorted(aggregated_entities.items()):
              md += text[pos:start]
              md += TrainingDataWriter.generate_entity(
                  text,
                  entities[0] if len(entities) == 1 else entities,
              )
              pos = entities[0]["end"]
  
      md += text[pos:]
  
      return md
  
imports: import abc
  import json
  from collections import OrderedDict
  from pathlib import Path
  import rasa.shared.nlu.training_data.util
  from rasa.shared.constants import INTENT_MESSAGE_PREFIX
  from rasa.shared.nlu.constants import INTENT, ENTITY_ATTRIBUTE_VALUE, ENTITY_ATTRIBUTE_START, ENTITY_ATTRIBUTE_END, ENTITY_ATTRIBUTE_TYPE, ENTITY_ATTRIBUTE_GROUP, ENTITY_ATTRIBUTE_ROLE
  import rasa.shared.utils.io
  import typing
  from typing import Text, Dict, Any, Union, List
  from collections import defaultdict
label_desc: Use image node_id 5 for calling the TrainingDataWriter obj's underlying member method code with example usage: obj.generate_message(message) and returns: md