docs: def _check_data_flow_ports(self, data_flow):
          """Checks the validity of the ports of a data flow
  
          Checks whether the ports of a data flow are existing and whether it is allowed to connect these ports.
  
          :param rafcon.core.data_flow.DataFlow data_flow: The data flow to be checked
          :return bool validity, str message: validity is True, when the data flow is valid, False else. message gives
              more information especially if the data flow is not valid
          """
          from_state_id = data_flow.from_state
          to_state_id = data_flow.to_state
          from_data_port_id = data_flow.from_key
          to_data_port_id = data_flow.to_key
  
          # Check whether to and from port are existing
          from_data_port = self.get_data_port(from_state_id, from_data_port_id)
          if not from_data_port:
              return False, "Data flow origin not existing -> {0}".format(data_flow)
          to_data_port = self.get_data_port(to_state_id, to_data_port_id)
          if not to_data_port:
              return False, "Data flow target not existing -> {0}".format(data_flow)
  
          # Data_ports without parents are not allowed to be connected twice
          if not from_data_port.parent:
              return False, "Source data port does not have a parent -> {0}".format(data_flow)
          if not to_data_port.parent:
              return False, "Target data port does not have a parent -> {0}".format(data_flow)
  
          # Check if data ports are identical
          if from_data_port is to_data_port:
              return False, "Source and target data ports of data flow must not be identical -> {}".format(data_flow)
  
          # Check, whether the origin of the data flow is valid
          if from_state_id == self.state_id:  # data_flow originates in container state
              if from_data_port_id not in self.input_data_ports and from_data_port_id not in self.scoped_variables:
                  return False, "Data flow origin port must be an input port or scoped variable, when the data flow " \
                                "starts in the parent state -> {0}".format(data_flow)
          else:  # data flow originates in child state
              if from_data_port_id not in from_data_port.parent.output_data_ports:
                  return False, "Data flow origin port must be an output port, when the data flow " \
                                "starts in the child state -> {0}".format(data_flow)
  
          # Check, whether the target of a data flow is valid
          if to_state_id == self.state_id:  # data_flow ends in container state
              if to_data_port_id not in self.output_data_ports and to_data_port_id not in self.scoped_variables:
                  return False, "Data flow target port must be an output port or scoped variable, when the data flow " \
                                "goes to the parent state -> {0}".format(data_flow)
          else:  # data_flow ends in child state
              if to_data_port_id not in to_data_port.parent.input_data_ports:
                  return False, "Data flow target port must be an input port, when the data flow goes to a child state" \
                                " -> {0}".format(data_flow)
  
          # Check if data flow connects two scoped variables
          if isinstance(from_data_port, ScopedVariable) and isinstance(to_data_port, ScopedVariable):
              return False, "Data flows must not connect two scoped variables -> {}".format(data_flow)
  
          # Check, whether the target port is already connected
          for existing_data_flow in self.data_flows.values():
              to_data_port_existing = self.get_data_port(existing_data_flow.to_state, existing_data_flow.to_key)
              from_data_port_existing = self.get_data_port(existing_data_flow.from_state, existing_data_flow.from_key)
              if to_data_port is to_data_port_existing and data_flow is not existing_data_flow:
                  if from_data_port is from_data_port_existing:
                      return False, "Exactly the same data flow is already existing -> {0}".format(data_flow)
  
          return True, "valid"